I want to rotate an object with the face side to the center of another one, but I have some problems with it: when I try to rotate an object to another one and it lies on X axis, it works properly [first two screenshots], but when I try to rotate it as on the screenshot, everything breaks down [second two screenshots].
Before1:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
After1:
0 0 -1 0
-0 -1 0 0
1 0 0 0
0 0 0 1
Before2:
0 0 -1 0
-0 -1 0 0
1 0 0 0
0 0 0 1
After2:
0 0 -0.707107 0
0.5 -0.5 0 0
0.707107 -0.707107 0 0
0 0 0 1
Here's my code:
void ConcreteObject::faceObjectTo(ConcreteObject otherObject) {
Vector<double> temp = {0, 1, 0};
Vector<double> forward = otherObject.getCenter() - this->getCenter();
forward.normalize();
Vector<double> right = temp.cross(forward);
right.normalize();
Vector<double> up = forward.cross(right);
Matrix<double> newMatrix = this->getTransformMatrix().getCurrentState();
newMatrix(0, 0) = right[0];
newMatrix(0, 1) = right[1];
newMatrix(0, 2) = right[2];
newMatrix(1, 0) = up[0];
newMatrix(1, 1) = up[1];
newMatrix(1, 2) = up[2];
newMatrix(2, 0) = forward[0];
newMatrix(2, 1) = forward[1];
newMatrix(2, 2) = forward[2];
TransformMatrix newObjectMatrix(newMatrix);
this->setTransformMatrix(newObjectMatrix);
}
You need to normalize right, there's no reason for temp and forward to be orthogonal, hence even if they are unit vectors, their crossproduct need not be.
Related
I'm working on a project where I am supposed to generate and solve random mazes with DFS and backtracking. So far I have managed to mark single nodes as "visited", and they show up as "1" instead of "0" on the grid, yet when I try to run the "random neighbour selection"-algorithm below, the program only visits a few nodes and then stops. Sometimes it even loops back and forth between i.e coordinate (0, 2) and (0, 1). Any tips? Code:
// Starting node. Set to "visited".
node new_node{0, 0};
set_as_visited(new_node);
node_stack.push(new_node);
// "visited_nodes" is the counter for visited nodes.
if (visited_nodes < (rows * cols)) {
int stack_x = node_stack.top().x;
int stack_y = node_stack.top().y;
std::vector<int> neighbour;
int north_x = stack_x;
int north_y = stack_y - 1;
if (north_y > 0 && !is_visited(north_x, north_y)) {
neighbour.push_back(0);
}
int east_x = stack_x + 1;
int east_y = stack_y;
if (east_x < (rows - 1) && !is_visited(east_x, east_y)) {
neighbour.push_back(1);
}
int west_x = stack_x - 1;
int west_y = stack_y;
if (west_x > 0 && !is_visited(west_x, west_y)) {
neighbour.push_back(2);
}
int south_x = stack_x;
int south_y = stack_y + 1;
if (south_y < (cols - 1) && !is_visited(south_x, south_y)) {
neighbour.push_back(3);
}
if (!neighbour.empty()) {
srand(time(nullptr));
int random_neighbour = neighbour[rand() % neighbour.size()];
node neighbour_to_add{};
switch (random_neighbour) {
case 0: // North
neighbour_to_add.x = north_x;
neighbour_to_add.y = north_y;
break;
case 1: // East
neighbour_to_add.x = east_x;
neighbour_to_add.y = east_y;
break;
case 2: // West
neighbour_to_add.x = west_x;
neighbour_to_add.y = west_y;
break;
case 3: // South
neighbour_to_add.x = south_x;
neighbour_to_add.y = south_y;
break;
}
set_as_visited(neighbour_to_add);
node_stack.push(neighbour_to_add);
}
else node_stack.pop();
}
draw_maze(grid);
Here is my node struct:
struct node {
int x, y;
};
This is what shows up on compile:
1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Process finished with exit code 0
When I try to throw my algorithm into a while-loop, nothing gets printed out at all. I'm not even sure the code is compiling by then. All I see is my working directory.
Thank you in advance!
sorry for the weird question, but I can explain.
Imagine you have 50 marbles that are wet with paint, and you are standing over a large canvas. You will drop each marble in the middle of the canvas, wait until it stops rolling around (assume when the marble stops, it disppears), and then drop your next one until you run out of marbles.
You will notice that when you are finished dropping all the marbles, the canvas is painted all over, with some streaks being darker than others.
That is what I am trying to represent with a 2d grid. So if I were to have 5 marbles, each with a "life" of 2, it would look something like this (given a 10x10 2d array)
/*
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
*/
Note, we dropped in the middle, then the marble went up and right
We moved twice, so our initial maxLife == 2 is now maxLife == 0, so we move onto the next marble
/*
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 2 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
*/
Note, we dropped in the middle again, then the marble went right
We moved twice, so our initial maxLife == 2 is now maxLife == 0, so we move onto the next marble
/*
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 3 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
*/
so on, and so on until we have dropped 5 marbles.
This seems basic enough with a simple nested for loop and recursive method to travel across and increment the array until the base case (when maxLife == 0), is hit. However, I am not getting expected results.
Here is my code :
#include <iostream>
#include <ctime>
using namespace std;
int width, height, xMax, xMin, yMax, yMin, numParticles, maxLife, waterLine;
int main()
{
/* Take in width, height, numParticles, maxLife, removed for code clarity */
int **land = makeParticleMap(width, height, numParticles, maxLife);
printIsland(land, width, height);
return 0;
}
void printIsland(int **land, int width, int height) { ... }
int **makeParticleMap(int width, int height, int numParticles, int maxLife)
{
int **land;
land = new int *[height];
for (int i = 0; i < height; ++i)
{
land[i] = new int[width]; //we have the 2d array
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
land[i][j] = 0;
}
}
int x, y = (width + height) / 2;
while (numParticles != 0) //while we have particles to drop
{
particleRoll(land, width, height, x, y, maxLife);
numParticles--;
}
return land;
}
void particleRoll(int **map, int width, int height, int x, int y, int maxLife)
{
if (maxLife <= 0)
{
return;
}
map[x][y]++;
maxLife--;
int xDir = (randomBool()) ? 1 : -1;
int yDir = (randomBool()) ? 1 : -1;
//i + xDir means: i-- or i++, either roll up or down rows, and j--, j++ same thing across columns
particleRoll(map, width, height, x + xDir, y + yDir, maxLife);
}
bool randomBool() { //returns -1 or 1 }
height and width never change, they are just the sizes of the array, since I am working with an int** instead of a vector.
I am just getting a width x height array of all 0's. I assume that the whole logic problem is within the recursion of particleRoll. I tried approaching it in a DFS style search, like the famous Number of Islands algorithm problem. However, I cannot figure out why my code is working like this.
I am trying to solve a n-knights problem on an 8x8 chessboard recursively. The n-knights problem is a variation of the n-queens problem, where the queens are replaced by knights. No piece can take another piece.
My code so far: http://pastebin.com/TVza3jVU.
The input consists of the number of knights that have to be placed on the chessboard. My code prints a lot of correct boards
Output looks like this (example):
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 3
0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 5
0 0 0 0 0 0 1 0 6
1 1 0 1 0 1 0 0 7
0 1 2 3 4 5 6 7
nrBoards = 49
A '1' stands for a knight.
My problem is as follows:
0 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 3
0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 5
0 0 0 0 0 0 0 0 6
0 0 0 0 0 0 0 0 7
0 1 2 3 4 5 6 7
This is the last board my script will print. It will never put a knight on [0][0]. I can not figure out why. It also skips some configurations. Is there something wrong with my recursion?
From the code you have linked, it seems that one problem is in your checkplace() function. You do not check whether the bounds of x+2, x-2, y+2, y-2 etc are in or out of the interval 0 to 7.
int checkPlace(int y, int x, chessboard boards) {
if (boards.board[y - 2][x - 1] == 1) {
return 0;
}
if (boards.board[y - 1][x - 2] == 1) {
return 0;
}
if (boards.board[y - 2][x + 1] == 1) {
return 0;
}
if (boards.board[y - 1][x + 2] == 1) {
return 0;
}
if (boards.board[y + 1][x + 2] == 1) {
return 0;
}
if (boards.board[y + 1][x - 2] == 1) {
return 0;
}
if (boards.board[y + 2][x - 1] == 1) {
return 0;
}
if (boards.board[y + 2][x + 1] == 1) {
return 0;
}
return 1;
}
Instead:
if ( x-1 >= 0 && y-2 >= 0 && boards.board[y - 2][x - 1] == 1) {
Similarly for others.
Using the Boost Graph Library I am looking for a way to extract the adjacency matrix from an underlying graph represented by either boost::adjacency_list or boost::adjacency_matrix. I'd like to use this matrix in conjunction with boost::numeric::ublas to solve a system of simultaneous linear equations.
Here is a minimal example to get you going:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
using namespace boost;
typedef boost::adjacency_list< listS, vecS, directedS > ListGraph;
typedef boost::adjacency_matrix< directedS > MatrixGraph;
int main(){
ListGraph lg;
add_edge (0, 1, lg);
add_edge (0, 3, lg);
add_edge (1, 2, lg);
add_edge (2, 3, lg);
//How do I get the adjacency matrix underlying lg?
MatrixGraph mg(3);
add_edge (0, 1, mg);
add_edge (0, 3, mg);
add_edge (1, 2, mg);
add_edge (2, 3, mg);
//How do I get the adjacency matrix underlying mg?
}
If anyone could come up with an efficient way to obtain the adjacency matrix I would be much obliged. Ideally the solution is compatible with uBLAS. I wonder if there is a way to avoid iteration through the entire graph.
The easiest way to convert adjacency_list into adjacency_matrix is to use boost::copy_graph
Your code for MatrixGraph mg should be modified as follows
#include <boost/graph/copy.hpp>
#include <cassert>
using namespace boost;
typedef boost::adjacency_list< listS, vecS, directedS > ListGraph;
typedef boost::adjacency_matrix< directedS > MatrixGraph;
int main(){
ListGraph lg;
add_edge(0, 1, lg);
add_edge(0, 3, lg);
add_edge(1, 2, lg);
add_edge(2, 3, lg);
//How do I get the adjacency matrix underlying lg?
//How do I get the adjacency matrix underlying mg?
MatrixGraph mg( num_vertices(lg));
boost::copy_graph(lg, mg);
}
Now, to use adjacency matrix with ublas or similar, you can write a simple "access" class to make syntax more compliant with ublas. Continuing previous snippet we get:
template <class Graph>
class MatrixAccessor
{
public:
typedef typename Graph::Matrix Matrix; //actually a vector<
typedef typename Matrix::const_reference const_reference;
MatrixAccessor(const Graph* g)
: m_g(g)
{
static_assert(boost::is_same<size_t, typename Graph::vertex_descriptor>::value, "Vertex descriptor should be of integer type");
}
const_reference operator()(size_t u, size_t v) const
{
return m_g->get_edge(u, v);
}
const Graph* m_g;
};
void use_matrix(const MatrixGraph & mg)
{
MatrixAccessor<MatrixGraph> matr(&mg);
assert(matr(0, 1) == 1);
assert(matr(0, 2) == 0);
}
In case your adjacency_matrix has some edge-bundled properties, you might need to modify the operator() in MatrixAccessor.
Depending on how much uBLAS you use, you can refine MatrixAccessor further. For example, out_edge_iterator for a given vertex of a MatrixGraph is actually an iterator over matrix column; vertex_iterator can be treated as iterator over matrix rows, etc.
Of course, graph matrix is immutable and as such should be used with care.
just as an easy way and I don't know how much it is efficient.
This is what I came up with:
I have used a small world graph and printed the adjacency matrix.
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/small_world_generator.hpp>
#include <boost/random/linear_congruential.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS> Graph;
typedef small_world_iterator<boost::minstd_rand, Graph> SWGen;
int main()
{
boost::minstd_rand gen;
int N = 20;
int degree = 4;
double rewiring = 0.;
Graph g(SWGen(gen, N, degree, rewiring), SWGen(), 20);
cout << num_edges(g)<< '\n';
typedef graph_traits<Graph>::edge_iterator edge_iterator;
pair<edge_iterator, edge_iterator> ei = edges(g);
for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
cout << "(" << source(*edge_iter, g) << ", " << target(*edge_iter, g) << ")\n";
}
vector<vector<int> > mat(N,vector<int>(N));
for (edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter){
int a = source(*edge_iter, g);
int b = target(*edge_iter, g);
mat[a][b] = 1;
mat[b][a] = 1;
}
for (int i=0; i<N; i++){
for (int j=0; j<N; j++){
cout << mat[i][j]<<" ";
}
cout <<endl;
}
return 0;
}
Output:
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1
1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0
The current revision of the adjacency_matrix has an undocumented public member m_matrix (see line 640). However, it is a flat vector of tuples <bool, bundled_properties> (line 512). Since the underlying storage looks so different from a ublas matrix, it is most likely not possible to convert a graph to a matrix besides iterating over edges.
Could you help me find the right algorithm for image resizing? I have an image of a number. The maximum size is 200x200, I need to get an image with size 15x15 or even less. The image is monochrome (black and white) and the result should be the same. That's the info about my task.
I've already tried one algorithm, here it is
// xscale, yscale - decrease/increase rate
for (int f = 0; f<=49; f++)
{
for (int g = 0; g<=49; g++)//49+1 - final size
{
xpos = (int)f * xscale;
ypos = (int)g * yscale;
picture3[f][g]=picture4[xpos][ypos];
}
}
But it won't work with the decrease of an image, which is my prior target.
Could you help me find an algorithm, which could solve that problem (quality mustn't be perfect, the speed doesn't even matter). Some information about it would be perfect too considering the fact I'm a newbie. Of course, a short piece of c/c++ code (or a library) will be perfect too.
Edit:
I've found an algorithm. Will it be suitable for compressing from 200 to 20?
The general approach is to filter the input to generate a smaller size, and threshold to convert to monochrome. The easiest filter to implement is a simple average, and it often produces OK results. The Sinc filter is theoretically the best but it's impractical to implement and has ringing artifacts which are often undesirable. Many other filters are available, such as Lanczos or Tent (which is the generalized form of Bilinear).
Here's a version of an average filter combined with thresholding. Assuming picture4 is the input with pixel values of 0 or 1, and the output is picture3 in the same format. I also assumed that x is the least significant dimension which is opposite to the usual mathematical notation, and opposite to the coordinates in your question.
int thumbwidth = 15;
int thumbheight = 15;
double xscale = (thumbwidth+0.0) / width;
double yscale = (thumbheight+0.0) / height;
double threshold = 0.5 / (xscale * yscale);
double yend = 0.0;
for (int f = 0; f < thumbheight; f++) // y on output
{
double ystart = yend;
yend = (f + 1) / yscale;
if (yend >= height) yend = height - 0.000001;
double xend = 0.0;
for (int g = 0; g < thumbwidth; g++) // x on output
{
double xstart = xend;
xend = (g + 1) / xscale;
if (xend >= width) xend = width - 0.000001;
double sum = 0.0;
for (int y = (int)ystart; y <= (int)yend; ++y)
{
double yportion = 1.0;
if (y == (int)ystart) yportion -= ystart - y;
if (y == (int)yend) yportion -= y+1 - yend;
for (int x = (int)xstart; x <= (int)xend; ++x)
{
double xportion = 1.0;
if (x == (int)xstart) xportion -= xstart - x;
if (x == (int)xend) xportion -= x+1 - xend;
sum += picture4[y][x] * yportion * xportion;
}
}
picture3[f][g] = (sum > threshold) ? 1 : 0;
}
}
I've now tested this code. Here's the input 200x200 image, followed by a nearest-neighbor reduction to 15x15 (done in Paint Shop Pro), followed by the results of this code. I'll leave you to decide which is more faithful to the original; the difference would be much more obvious if the original had some fine detail.
To properly downscale an image, you should divide your image up into square blocks of pixels and then use something like Bilinear Interpolation in order to find the right color of the pixel that should replace the NxN block of pixels you're doing the interpolation on.
Since I'm not so good at the math involved, I'm not going to try give you an example of how the code would like. Sorry :(
Since you're fine with using a library, you could look into the imagemagick C++ bindings.
You could also output the image in a simple format like a pbm, and then call the imagemagick command to resize it:
system("convert input.pbm -resize 10x10 -compress none output.pbm");
Sample output file (note: you don't need to use a new line for each row):
P1
20 20
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The output file:
P1
10 10
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 1 1 0
0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 1 1 1 1
1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
I've found an implementation of a bilinear interpolaton. C code.
Assuming that:
a - a primary array (which we need to stretch/compress) pointer.
oldw - primary width
oldh - primary height
b - a secondary array (which we get after compressing/stretching) pointer
neww - secondary width
newh - seconday height
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
void resample(void *a, void *b, int oldw, int oldh, int neww, int newh)
{
int i;
int j;
int l;
int c;
float t;
float u;
float tmp;
float d1, d2, d3, d4;
u_int p1, p2, p3, p4; /* nearby pixels */
u_char red, green, blue;
for (i = 0; i < newh; i++) {
for (j = 0; j < neww; j++) {
tmp = (float) (i) / (float) (newh - 1) * (oldh - 1);
l = (int) floor(tmp);
if (l < 0) {
l = 0;
} else {
if (l >= oldh - 1) {
l = oldh - 2;
}
}
u = tmp - l;
tmp = (float) (j) / (float) (neww - 1) * (oldw - 1);
c = (int) floor(tmp);
if (c < 0) {
c = 0;
} else {
if (c >= oldw - 1) {
c = oldw - 2;
}
}
t = tmp - c;
/* coefficients */
d1 = (1 - t) * (1 - u);
d2 = t * (1 - u);
d3 = t * u;
d4 = (1 - t) * u;
/* nearby pixels: a[i][j] */
p1 = *((u_int*)a + (l * oldw) + c);
p2 = *((u_int*)a + (l * oldw) + c + 1);
p3 = *((u_int*)a + ((l + 1)* oldw) + c + 1);
p4 = *((u_int*)a + ((l + 1)* oldw) + c);
/* color components */
blue = (u_char)p1 * d1 + (u_char)p2 * d2 + (u_char)p3 * d3 + (u_char)p4 * d4;
green = (u_char)(p1 >> 8) * d1 + (u_char)(p2 >> 8) * d2 + (u_char)(p3 >> 8) * d3 + (u_char)(p4 >> 8) * d4;
red = (u_char)(p1 >> 16) * d1 + (u_char)(p2 >> 16) * d2 + (u_char)(p3 >> 16) * d3 + (u_char)(p4 >> 16) * d4;
/* new pixel R G B */
*((u_int*)b + (i * neww) + j) = (red << 16) | (green << 8) | (blue);
}
}
}
Hope it will be useful for other users. But nevertheless I still doubth whether it will work in my situation (when not stratching, but compressing an array). Any ideas?
I think, you need Interpolation. There are a lot of algorithms, for example you can use Bilinear interpolation
If you use Win32, then StretchBlt function possibly help.
The StretchBlt function copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary. The system stretches or compresses the bitmap according to the stretching mode currently set in the destination device context.
One approach to downsizing a 200x200 image to, say 100x100, would be to take every 2nd pixel along each row and column. I'll leave you to roll your own code for downsizing to a size which is not a divisor of the original size. And I provide no warranty as to the suitability of this approach for your problem.