Function to find the xy location of a pixel - c

Since my previous question was certainly not very clean. And respectively i couldn't implement an exact solution of my problem. I have been working on a function that returns the byte offset of a pixel located in X/Y coords. For that purpose i have that:
dword bmp_find_xy (dword xp, dword yp)
{
dword w = 50; // to clarify thats the real widh of the sample image i use
dword bpx = (3*8); // using 3*8 as a reminder.
dword offset = (2+sizeof(BMP)+sizeof(DIB)); // this is the offset 54.
dword pitch = w * 3; // determining the widh of pixels. Pitch variable
dword row = w * 3; // determining the widh of pixels. Row variable.
dword pixAddress; // result variable
if(pitch % 4 != 0) pitch += 4 - (pitch % 4); // finding the pitch (row+padding)
pixAddress = (offset) + pitch * yp + ((xp * bpx) / 8); // finding the address
return pixAddress;
}
So the question won't be like "What am i doing wrong/why im receiving weird errors". The question is.. am i doing it correct? On first tests it seems to work. But i am somehow unsure. Once it is confirmed thats the correct way.. I'll delete the question.

Your code looks like it gives the correct result to me. However it is inconsistent in itself.
In the row (yp) addressing, you assume that every pixel has 3 bytes.
In the column (xp) addressing, you assume that every pixel has 3*8 bits.
So why use bytes in the first case, bits in the second case? I think the code would be cleaner like this:
dword width = 50; // image width
dword channels = 3; // number of color channels
dword bpp = 8; // depth in bits
dword single = (channels*bpp)/8; // size of a pixel in bytes
dword offset = (2+sizeof(BMP)+sizeof(DIB)); // this is the offset 54.
dword rowsize = width*single; // size of a row in memory
if (rowsize % 4 != 0)
rowsize += 4 - (rowsize % 4); // account for padding
dword pixAddress; // result variable
pixAddress = offset + yp*rowsize + xp*single; // finding the address
return pixAddress;
Also, you can read the width, channel and bpp from the header.
Next, your code would be faster if you get the address of the first pixel in a row first, then keep it to iterate through the row (not recompute the whole thing every time). Here is an illustration of a typical task running over all pixels. Note that I do not use the same coding style as in the original question here.
unsigned char maxGreen = 0;
for (int y = 0; y < height; y++) {
unsigned char *row = bitmap.getRowPtr(y);
for (int x = 0; x < width; x++) {
unsigned char *pixel = row + bitmap.getColumnOffset(x);
if (pixel[2] > maxGreen)
maxGreen = pixel[2];
}
}
// maxGreen holds the maximum value in the green channel observed in the image
As you can see, in this example the offset, padding etc. calculations only need to be done once per row in the getRowPtr() function. Per pixel we only need to do the offset calculation (a simple multiplication) in the getColumnOffset() function.
This makes the example much faster, when breaking down how many calculations need to be done per pixel.
Last, I would never write code to read a BMP myself! Use a library for that!

Related

Faster way to load matrix into byte array?

I am overlaying a custom drawn view on top of a video frame and sending that overlay pixel information to my microcontroller and encoding it into a byte array. Most of the RGB values are 0 because they are apart of the video frame and not the custom view I am drawing.
I am encoding the 32-bit rgb value into 4 different bytes, for each pixel. However, the frame is very slow and lags because I am looping through the entire frame and converting each value to a byte array. I understand what's causing the issue, but wondering if there is a way to speed it up.
I would remove the 0's and only pass values that have a valid RGB value, but I need to keep the position.
The matrix size has 518400 elements.
for (int i = 0; i < A.size(); i++) {
byte *t = (byte *) &A.mem[i];
byte t1 = t[0];
byte t2 = t[1];
byte t3 = t[2];
byte t4 = t[3];
if (t1 != '\0' || t2 != '\0' || t3 != '\0' || t4 != '\0') {
writeSerialData(t, 4);
}
}
You could check the four bytes against zero in one go:
int iMax = A.size();
for (int i = 0; i < iMax; ) {
int32_t *t = (int32_t *) &A.mem[i++];
if (*t) {
writeSerialData(t, 4);
}
}
Do you control the receiving part of that writeSerialData()? Then you should invent some encoding that specifies a new offset of the following data.
Also, are you using 16 millions colors in your overlay? If you are only using a few colors, they invented palette for that. If you know the colors upfront, you can hard-code them on both ends. If not - send a small header with that palette info before the image. That can cut the size of your data by 4 times. If you only have single color, you can further reduce your data to single bits.
UPDATE
By "encoding" I mean some special format of your data, other than simple RGB value. For example, do you use the Alpha channel (I noticed you didn't call your colors RGBA)? If not - you can use that byte for length-encoding, stating that the following color is repeated that many times (up to 255). This will save you some bandwidth on your zeroes (just say how many are there), as well as on a line of the same color (you don't need to send every pixel).

Stuck implementing boundary checks on frame windows for mean filtering

I have a function that successfully reads rgb values from a ppm and a function that successfully writes to a ppm. What I am trying is a function called denoiseImage that changes rgb values from a ppm using mean filtering with a frame window size n by n where n is odd. My intent is to go through each pixel, using it as the center point for the window n by n that surrounds it. I then take the mean values for each color (r,g,b) and divide by the number of pixels in the window and assign those new values to the rgb of every pixel in the window. However, I am unable to implement a check for the cases where the frame does not fully fit into pixels (for example, the frame center point is the top right pixel, a window of 3x3 will go to non existent points.) When it does not fit fully, I intend to use the available pixels that fit and take the mean of those numbers instead. So far, my code will only work for cases where the frame fully fits. My function:
RGB *denoiseImage(int width, int height, const RGB *image, int n)
{
int firstPos, lastPos, i = 0, j = 0, k, numofPix;
int sumR=0,sumG=0,sumB=0;
numofPix = (width * height);
RGB *pixels = malloc(numofPix * sizeof(RGB));
if (n == 1) //Case where the window size is 1 and therefore the image does not get changed.
{
return pixels;
}
for (j=0;j < numofPix;j++)
{
firstPos = (j - width) - ((n - 1)/2);
lastPos = (j + width) + ((n - 1)/2);
//Need to check boundary cases to prevent segmentation fault
for (k=firstPos;k<=lastPos;k++) //Seg fault. Unable to shrink frame to compensate for cases where the frame does not fit.
{
sumR+=image[k].r;
sumG+=image[k].g;
sumB+=image[k].b;
i++;
if (i = n) //Used to skip elements not in frame
{
j += (width-n);
i = 0;
}
}
sumR = sumR/(n*n); //Calculating mean values
sumG = sumG/(n*n);
sumB = sumB/(n*n);
for (k=firstPos;k<=lastPos;k++) //Assigning the RGB values with the new mean values.
{
pixels[k].r=sumR;
pixels[k].g=sumG;
pixels[k].b=sumB;
printf("%d %d %d ",pixels[k].r, pixels[k].g, pixels[k].b);
}
}
return pixels;
}
int main()
{
RGB *RGBValues;
int width, height, max;
int j = 0,testemp=3; //test temp is a sample frame size
char *testfile = "test.ppm";
char *testfile2 = "makeme.ppm";
RGBValues = readPPM(testfile, &width, &height, &max); //Function reads values from a ppm file correctly
RGBValues = denoiseImage(width,height, RGBValues, testemp,testing);
writePPM(testfile2,width,height,max,RGBValues); //Function writes values to a ppm file correctly
}
How would I implement a way to check if the frame fits or not?
This is a great question and luckily known in the image processing community.
Edges are always treated differently when it comes to 2D filtering.
One way to look at it is to extend the space in 2D and to fill the edges with extrapolated values from the middle.
For example, you may look into the http://www.librow.com/articles/article-1 and search for a media filter.
I am sure that you will find solution soon, since you are going into right direction.

Most memory efficient algorithm for finding a path on a grid

What is the most memory efficient algorithm that can be used to find a path from one grid square to another? The grid may have obstacles that cannot be crossed. Being the shortest path is not necessary, but certainly, is a bonus. The algorithm is going to be coded in C (C++ is available, but I am avoiding it to reduce memory usage) and run on an ATmega328 chip with only 2048 bytes of SRAM. CPU efficiency is not of paramount importance.
EDIT: The grid is 16 by 32 squares, each represented by one bit. The total memory usage is therefore 64 bytes. The grid is stored as a 2D array of unsigned chars and all of the 2048 bytes are available. The output would be an array of integers referencing the squares that should be taken.
If there is an obstacle in a square, the array of squares would have a 1 instead of a zero. These squares should be treated like walls.
This is an unfinished idea for an algorithm which may fit into 2048 bytes, that I came up with while trying to find a non-recursive flood-fill variant.
The first step is to create an additional 32×16 array of 8-bit values; this uses 512 bytes. You then iterate over the grid horizontally, and number the runs of adjacent reachable squares as in the image below:
For a 32×16 grid, the maximum number of runs is 256 (e.g. with a checkerboard pattern, or vertical stripes), so this numbering fits into 8-bit values.
The second step is to iterate over the grid vertically, and group the runs that are adjacent:
After checking vertical line 1:
{0A,11,1A}
{2E}
{44,50,5C}
{72}
{87,8F,98}
After checking vertical line 2:
{0A,11,1A,00,24}
{2E}
{44,50,5C,37,69}
{72}
{87,8F,98,7C}
After checking vertical line 2:
{0A,11,1A,00,24,12,2F}
{2E}
{44,50,5C,37,69,51,73}
{72}
{87,8F,98,7C,90}
... and so on, merging groups if they are linked by adjacent runs. If, at the end, the number of the start and target squares are in the same group, that means there is a path.
Now, if you store the groups as simple lists, like in the example above, this doesn't really give you a path; it just tells you which squares are reachable from the start and target squares, but a path may not need to cross all these squares.
If you stored the groups in a data structure where you know which runs are connected to each other, then it becomes a "shortest path through graph" problem in a smaller space. I'm not sure which data structure would best fit into the remaining 1536 bytes.
(Anyone is welcome to try and take this idea further.)
This method could be used to simplify the grid before running another algorithm. Firstly, the grouping of the runs identifies unreachable parts of the grid; these could be marked as walls in the original grid or a copy of it. Secondly, it identifies dead ends; runs which are only connected to one other run (and which don't contain the start or target square) are unnecessary detours and can also be marked as such. (This should be repeated: removing a singly-connected run may reveal another run to be singly-connected.)
Grid simplified by removing unreachable and singly-linked runs
Running the algorithm again, but with vertical runs and horizontal grouping, could remove additional dead ends.
The JavaScript snippet below is a simple code example for the first part of the algorithm: using the example grid in the images, it numbers the runs, assigns them to groups, merges groups when necessary, and then checks whether the start and target square are in the same group, i.e. whether there is a path.
The grouping method may not be the most efficient, especially when merging groups, but it uses a fixed-size array of maximum 256 bytes (number of runs × 8-bit values), which is probably best in a limited-memory situation.
function gridPath(grid, x1, y1, x2, y2) {
var runs = [], rcount = 0;
for (var i = 0; i < 16; i++) { // number runs
var start = true; runs[i] = [];
for (var j = 0; j < 32; ++j) {
if (grid[i][j] == 0) { // found empty cell
if (start) ++rcount; // start of new run
runs[i][j] = rcount - 1;
start = false;
}
else start = true; // found blocked cell
}
}
var groups = [], gcount = 0;
for (var i = 0; i < rcount; i++) groups[i] = 0xFF;
for (var j = 0; j < 32; ++j) { // assign runs to groups
var g = [];
for (var i = 0; i < 16; ++i) {
if (grid[i][j] == 0) g.push(runs[i][j]);
if ((grid[i][j] == 1 || i == 15) && g.length > 0) {
insertGroup(g);
g = [];
}
}
}
return groups[runs[y1][x1]] == groups[runs[y2][x2]];
function insertGroup(g) {
var matches = [];
for (var i = 0; i < g.length; i++) { // check if runs are already in group
if (groups[g[i]] != 0xFF && matches.indexOf(groups[g[i]]) < 0) {
matches.push(groups[g[i]]);
}
}
if (matches.length == 0) matches.push(gcount++); // start new group
for (var i = 0; i < g.length; i++) { // add runs to group
groups[g[i]] = matches[0];
}
if (matches.length > 1) { // merge groups
for (var i = 0; i < rcount; i++) {
if (matches.indexOf(groups[i]) > 0) groups[i] = matches[0];
}
}
}
}
var grid = [[1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0],
[0,0,0,1,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,0,0,0,0,1,0,0,1,0],
[0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0],
[0,0,1,0,1,0,1,0,1,0,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1,0,0,1],
[1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0],
[0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,1,1,1,0,0,1,0,1,1,0,0,0,0,0,1,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,1,1,1,1,0,1,0],
[0,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,0,0],
[0,1,0,0,0,1,0,0,0,1,1,0,1,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0],
[0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0],
[1,0,0,1,0,0,0,1,0,0,0,1,0,0,1,1,1,0,0,1,0,0,1,0,0,0,1,0,1,0,0,1],
[0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0],
[1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1],
[0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0],
[0,1,0,0,0,1,0,0,0,1,0,0,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0],
[0,0,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0]];
document.write(gridPath(grid, 0, 15, 15, 7));
If you only want to find the target, but do not care about remembering the path that was taken, then random search is pretty much optimal memory wise. It does not need to remember anything about previous states, so the memory use is constant. (Time complexity on the other hand is unbounded, which is not great, but isn't excluded by your requirements)
If you do need to remember the taken path, then you cannot go below linear space complexity with an algorithm that is complete - i.e always finds a path if it exists. Both breadth and depth first searches have linear space complexity, so they would be asymptotically in the same class as the optimal complete algorithm.
Since the memory is very limited, you might prefer to use a memory bounded algorithm, that gives you constant upper bound for memory use, but is not guaranteed to find a path that might exist. I recommend Simplified Memory Bounded A*.
I looked into using Dijkstra (as suggested by Weather Vane), which would require that for each grid cell the distance to the starting point and the direction from the previous cell is stored.
Unfortunately, it is possible for paths on a 32x16 grid to have a distance greater than 255; the longest path I found has distance 319 (see image below, left). This means that the distances won't fit in 8-bits, and the distance matrix has a size of 1024 bytes.
Left: longest path (distance=319). Right: largest number of equidistant cells (72 cells at distance 16)
However, in a square grid where all distances equal 1, you can simplify Dijkstra to a breadth-first search which doesn't use a distance matrix; if you use a fifo queue, the cells are visited in order of distance to the starting cell, so you cannot find a shorter path to an already visited cell.
The fifo queue will contain every cell at a certain distance, then gradually transition to distance + 1, and so on. The maximum size of the queue depends on how many equidistant cells there can be; the maximum I found is 72 (see image above, right) and during the transition from the previous distance this requires a queue that can hold the coordinates of 76 cells, or 152 bytes.
The path which is returned by the algorithm is an array holding the coordinates of a maximum of 320 cells, so it has a maximum size of 640 bytes. Before constructing this array, the queue can be discarded, so only the direction grid and the path are in memory at the same time.
Below is a code example of the simplified algorithm with only a direction matrix and a fifo queue; it can probably be improved on many points, but it demonstrates the idea. The findPath() function uses a minimum of 664 up to a maximum of 1152 bytes of allocated memory (depending on path length) plus around 20 bytes for additional variables.
This could be further reduced, e.g. by storing the direction matrix as 4-bit nibbles, reducing its size from 512 to 256 bytes (but requiring more calculations), or by returning the path as a sequence of up/right/down/left directions instead of cell coordinates, which would require only 2 bits per step, reducing its maximum size from 640 to 80 bytes.
#include <stdlib.h> // gcc -std=c99
short int findPath(char grid[][32], char x1, char y1, char x2, char y2, char **path) {
char (*dir)[16][32] = calloc(512, 1); // allocate direction matrix: 512 bytes (zeros)
(*dir)[y2][x2] = 5; // mark starting cell as visited (search backwards)
char *queue = malloc(152); // allocate fifo queue: 152 bytes
queue[0] = x2; queue[1] = y2; // put starting cell in queue (search backwards)
unsigned char qRead = 0, qWrite = 2; // queue pointers
char qCurSize = 1, qNextSize = 0; // queue size per distance
short int distance = 0; // distance to current cell
char dx[4] = {0, 1, 0, -1}; // up, right, down, left
while (qRead != qWrite && !(*dir)[y1][x1]) { // until queue empty (fail) or target reached
char x = queue[qRead++], y = queue[qRead++]; // take oldest cell from queue
qRead %= 152; // wrap-around queue pointer
for (char i = 0; i < 4; i++) { // check 4 neighbouring cells
char nx = x + dx[i], ny = y + dx[3 - i]; // coordinates of neighbouring cell
if (nx >= 0 && nx < 32 && ny >= 0 && ny < 16 // coordinates not off-grid
&& !grid[ny][nx] && !(*dir)[ny][nx]) { // traversable unvisited cell
(*dir)[ny][nx] = i + 1; // store direction 1-4
queue[qWrite++] = nx; queue[qWrite++] = ny; // put cell in queue
qWrite %= 152; // wrap-around queue pointer
++qNextSize; // increment queue size for next distance
}
}
if (!--qCurSize || (*dir)[y1][x1]) { // current distance done or target reached
qCurSize = qNextSize; // switch to distance + 1
qNextSize = 0;
++distance;
}
}
free(queue); // free up queue memory for path
if (!(*dir)[y1][x1]) distance = -1; // no path found
else { // path found
*path = malloc(distance * 2 + 2); // allocate path array: 2 bytes per step
(*path)[0] = x1; (*path)[1] = y1; // starting position (forward)
for (short int i = 1; i <= distance; i++) { // retrace steps
char d = (*dir)[y1][x1] - 1; // direction of previous step 0-3
x1 -= dx[d]; y1 -= dx[3 - d]; // go back to previous position
(*path)[i * 2] = x1; (*path)[i * 2 + 1] = y1; // add cell to path
}
}
free(*dir); // discard direction matrix
return distance + 1; // return number of cells in path
}
int main() {
char grid[][32] = // max queue size: 76
{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,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,1,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,1,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,1,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,1,0,1,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,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,1,1,1,1,1,1,1,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,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,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,1,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,1,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,1,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,1,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,1,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,0}};
char x1 = 31, y1 = 0, x2 = 16, y2 = 7, *path = NULL;
short int steps = findPath(grid, x1, y1, x2, y2, &path);
// do stuff
free(path); // discard path array
return 0;
}

Accessing portions of a dynamic array in C?

I know, another dynamic array question, this one is a bit different though so maybe it'll be worth answering. I am making a terrain generator in C with SDL, I am drawing 9 chunks surrounding the screen, proportional to the screen size, that way terrains can be generated easier in the future.
This means that I have to be able to resize the array at any given point, so I made a dynamic array (at least according to an answer I found on stack it is) and everything SEEMS to work fine, nothing is crashing, it even draws a single tile....but just one. I am looking at it and yeah, sure enough it's iterating through the array but only writing to one portion of memory. I am using a struct called Tile that just holds the x, y, w, and h of a rectangle.
This is the code I am using to allocate the array
Tile* TileMap = (Tile*)malloc(0 * sizeof(Tile*));
int arrayLen = sizeof(TileMap);
TileMap = (Tile*)realloc(TileMap, (totalTiles) * sizeof(Tile));
arrayLen = sizeof(totalTiles * sizeof(Tile));
The totalTiles are just the number of tiles that I have calculated previously are on the screen, I've checked the math and it's correct, and it even allocates the proper amount of memory. Here is the code I use to initialize the array:
//Clear all elements to zero.
for (int i = 0; i < arrayLen; i++)
{
Tile tile = {};
TileMap[i] = tile;
}
So what's weird to me is it is considering the size of a tile (16 bytes) * the totalTiles (78,000) is equaling 4....When I drill down into the array, it only has one single rect in it that gets cleared as well, so then when I go calculate the sizes of each tile:
//Figure out Y and heights
for (int i = startY; i <= (startY*(-1)) * 2; i += TILE_HEIGHT)
{
TileMap[i].y = i * TILE_HEIGHT;
TileMap[i].h = TILE_HEIGHT;
//Figure out X and widths
for (int j = startX; j <= (startX*(-1)) * 2; j += TILE_WIDTH)
{
TileMap[i].x = i * TILE_WIDTH;
TileMap[i].w = TILE_WIDTH;
}
}
*Side note, the startX is the negative offset I am using to draw chunks behind the camera, so I times it by -1 to make it positive and then time it by two to get one chunk in front of the camera
Alright, so obviously that only initializes one, and here is the render code
for (int i = 0; i < totalTiles; i++)
{
SDL_Rect currentTile;
currentTile.x = TileMap[i].x;
currentTile.y = TileMap[i].y;
currentTile.w = TileMap[i].w;
currentTile.h = TileMap[i].h;
SDL_RenderDrawRect(renderer, &currentTile);
}
free(TileMap);
So what am I doing wrong here? I mean I literally am just baffled right now...And before Vectors get recommended in place of dynamic arrays, I don't really like using them and I want to learn to deal with stuff like this, not just implement some simple fix.
Lots of confusion (which is commonplace with C pointers).
The following code doesn't provide expected answer :arrayLen = sizeof(totalTiles * sizeof(Tile));
totalTiles * sizeof(Tile) is not even a type, I'm surprised it compiles at all. Edit : See molbnilo comment below. so it provides the size of the return type.
Anyway, proper answer should be :
arrayLen = totalTiles;
Because that's what you need in your next loop :
//Clear all elements to zero.
for (int i = 0; i < arrayLen; i++)
{
Tile tile = {};
TileMap[i] = tile;
}
You don't need the size of the table, you need its number of elements.
There are other confusions in your sample, they don't directly impact the rest of the code, but better correct them :
Tile* TileMap = (Tile*)malloc(0 * sizeof(Tile*)); : avoid allocating a size of 0.
int arrayLen = sizeof(TileMap); : no, it's not the arrayLen, just the size of the pointer (hence 4 bytes on 32-bits binaries). Remember TileMap is not defined as a table, but as a pointer allocated with malloc() and then realloc().

Extract from image an smaller image

I am starting learning an openCV and a have question about it.
My target is to recognize captcha.
First I must preprocess an image.
There is an example of captcha
here
So problem is how to crop symbols from image and put it into 2D array(bitmap).
Automatic Partition Detection
The first thing you'd need to do is create the filter array of background colors. This will be the array containing the colors that occur in the background. For that purpose you can just take the offset 20x20 area or leave it as a user option depending on your project standpoint.
typedef unsigned char Pixel [3];
typedef *Pixel PixelArray;
// Function to return offset byte of x/y coordinate
int bmp_get_offset (int width, int x, int y)
{
int w = width;
const int channels = 3;
const int bpp = 8;
const int single = (channels * bmpp) / 8;
const int offset = 54;
int rowsize = w * single;
int pixAddress;
if(rowsize % 4 != 0) rowsize += 4 - (rowsize % 4);
pixAddress = offset + yp * rowsize + xp * single;
return pixAddress;
}
// Function to return specific area (pseudo-code)
PixelArray bmp_get_area (FILE * bmp, int x, int y, int w, int h)
{
PixelArray buffer = buffer_new(bmp); // sets image into a memory-allocated buffer
PixelArray area [h * w];
const int src_width = *((int*)&buffer[(0x12)]);
for(int iWidth = 0; iWidth < w; iWidth++)
for(int iHeight = 0; iHeight < h; iHeight++)
area[iHeight * src_width + iWidth] = buffer[bmp_get_offset(src_width, x + iWidth, y + iHeight)];
return area;
}
Well it didn't go that much pseudo-code.
Now that you have the filter you can limit outer pixels.
Now what you need is a vertical raster scan. Or just vertical scan.
Over the entire captcha image.
Each pixel of the vertical line will be additionally checked if it matches some color from the already-obtained area.
If all the pixels of the line (that has the size of the image's height) return positive when checked whether pixel is close to or matches area color, an aray indexer will increment so that we have where the last character ends.
Edit 1
For 3 seconds I GIMPed the color curves of the image, resulting in a plain background:
So this respectively simplifies the filtering process quite a lot.
The color curves magic I did is actually only a brightness/contrast adjustment control, which is maybe the easiest color processing you can implement (after the invert).
I might periodically edit to clarify some more. This will certainly give you a good practice. A real practice.
Doc:
BMP File Format (More than enough information for you to start working with bitmaps. The most important one is the bitmap structure, which is a combination of BMPINFOHEADER and DIBHEADER).
Tesseract OCR (alternative that will do everything for you. However if you solve your problems with the easiest solution, it will not make you a better programmer)

Resources