Pixel color calculation 255 to 0 - c++

I have been using the algorithm from Microsoft here:
INT iWidth = bitmap.GetWidth();
INT iHeight = bitmap.GetHeight();
Color color, colorTemp;
for(INT iRow = 0; iRow < iHeight; iRow++)
{
for(INT iColumn = 0; iColumn < iWidth; iColumn++)
{
bitmap.GetPixel(iColumn, iRow, &color);
colorTemp.SetValue(color.MakeARGB(
(BYTE)(255 * iColumn / iWidth),
color.GetRed(),
color.GetGreen(),
color.GetBlue()));
bitmap.SetPixel(iColumn, iRow, colorTemp);
}
}
to create a gradient alpha blend. Theirs goes left to right, I need one going from bottom to top, so I changed their line
(BYTE)(255 * iColumn / iWidth)
to
(BYTE)(255 - ((iRow * 255) / iHeight))
This makes row 0 have alpha 255, through to the last row having alpha 8.
How can I alter the calculation to make the alpha go from 255 to 0 (instead of 255 to 8)?

f(x) = 255 * (x - 8) / (255 - 8)?
Where x is in [8, 255] and f(x) is in [0, 255]
The original problem is probably related with the fact that if you have width of 100 and you iterate over horizontal pixels, you'll only get values 0 to 99. So, dividing 99 by 100 is never 1. What you need is something like 255*(column+1)/width

(BYTE)( 255 - 255 * iRow / (iHeight-1) )
iRow is between 0 and (iHeight-1), so if we want a value between 0 and 1 we need to divide by (iHeight-1). We actually want a value between 0 and 255, so we just scale up by 255. Finally we want to start at the maximum and descend to the minimum, so we just subtract the value from 255.
At the endpoints:
iRow = 0
255 - 255 * 0 / (iHeight-1) = 255
iRow = (iHeight-1)
255 - 255 * (iHeight-1) / (iHeight-1) = 255 - 255 * 1 = 0
Note that iHeight must be greater than or equal to 2 for this to work (you'll get a divide by zero if it is 1).
Edit:
This will cause only the last row to have an alpha value of 0. You can get a more even distribution of alpha values with
(BYTE)( 255 - 256 * iRow / iHeight )
however, if iHeight is less than 256 the last row won't have an alpha value of 0.

Try using one of the the following calculations (they give the same result):
(BYTE)(255 - (iRow * 256 - 1) / (iHeight - 1))
(BYTE)((iHeight - 1 - iRow) * 256 - 1) / (iHeight - 1))
This will only work if using signed division (you use the type INT which seems to be the same as int, so it should work).

Related

Matrix with 1d vector

I represent a n*m matrix like chessboard.
1 0 2 0
0 3 0 4
5 0 6 0
0 7 0 8
I don't need to store the zeros in my 1d vector.
vector v = {1, 2, 3, 4.. etc}
I ask the user for a row and column number.
How can i return with i. row j. column element?
if (i+j) % 2 != 0
I return with 0, but i don't know what i need to do when
(i+j) % 2 == 0
Can you help me? (sorry for my bad English)
With regular matrices stored as 1D-vector, coordinate to index would be:
(i + j * width) (or i * height + j depending on convention).
with half case to 0, you just have to divide by 2:
if ((i + j) % 2 != 0) return 0;
else return data[(i + j * width) / 2];

Is there an algorithm for copying neighboring pixel values stored in a 2D-Array?

I have a 2D array of greyscale pixel values that looks like
255 250 250 250 235 251 255 201
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
In implementations I have seen online and in other posts, the program will obtain neighboring pixels specifically in an 3x3 window area.
For example,
for (row = 1; row <= numRows; ++row)
{
for (col = 1; col <= numCols; ++col)
{
//neighbor pixel values are stored in window including this pixel
window[0] = imageArr[row - 1][col - 1];
window[1] = imageArr[row - 1][col];
window[2] = imageArr[row - 1][col + 1];
window[3] = imageArr[row][col - 1];
window[4] = imageArr[row][col];
window[5] = imageArr[row][col + 1];
window[6] = imageArr[row + 1][col - 1];
window[7] = imageArr[row + 1][col];
window[8] = imageArr[row + 1][col + 1];
// do something with window
}
}
I am trying to implement a more dynamic window size.
Ex. If the user wants to find neighboring pixels in an 4x4 area or an 5x5 area
I wasn't planning on answering this, but I may as well now that I've written extensively in comments.
General advice is to simplify your loop by treating row and col as the top-left corner of your window instead of the center. This makes the math straight-forward (and therefore clearer to anyone reading the code), especially for the case of an even-sized window dimension.
Assuming the window is square (dimension N), which appears to be your requirement, the outer loops become:
for (int row = 0; row < numRows - N; ++row)
{
for (int col = 0; col < numCols - N; ++col)
{
// TODO: copy window
// Your window's "center" if you need it
int cx = col + N/2;
int cy = row + N/2;
// TODO: Do something with window...
}
}
Now, let's do the "copy window" loops. This is a simple NxN image copy where the source position is [row + y][col + x]:
// Copy window
for (int y = 0; y < N; ++y)
{
for (int x = 0; x < N ++x)
{
window[y * N + x] = imageArr[row + y][col + x];
}
}
It's pretty simple to extend this to rectangular windows if you need, which would be a good exercise for you to try. Various optimizations are possible, but I think that's out of scope based on your current level, and I actually don't want to promote optimization to beginners. It's better to learn how to write simple, clear code.

Swap two colors using color matrix

How can I swap two colors using a color matrix? For instance swapping red and blue is easy. The matrix would look like:
0 0 1 0 0
0 1 0 0 0
1 0 0 0 0
0 0 0 1 0
0 0 0 0 1
So how can I swap any two colors in general? For example, there is Color1 with R1, G1, B1 and Color2 with R2, G2, B2.
EDIT: By swap I mean Color1 will translate into color2 and color2 will translate into color1. Looks like I need a reflection transformation. How to calculate it?
GIMP reference removed. Sorry for confusion.
This appears to be the section of the color-exchange.c file in the GIMP source that cycles through all the pixels and if a pixel meets the chosen criteria(which can be a range of colors), swaps it with the chosen color:
for (y = y1; y < y2; y++)
{
gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, width);
for (x = 0; x < width; x++)
{
guchar pixel_red, pixel_green, pixel_blue;
guchar new_red, new_green, new_blue;
guint idx;
/* get current pixel-values */
pixel_red = src_row[x * bpp];
pixel_green = src_row[x * bpp + 1];
pixel_blue = src_row[x * bpp + 2];
idx = x * bpp;
/* want this pixel? */
if (pixel_red >= min_red &&
pixel_red <= max_red &&
pixel_green >= min_green &&
pixel_green <= max_green &&
pixel_blue >= min_blue &&
pixel_blue <= max_blue)
{
guchar red_delta, green_delta, blue_delta;
red_delta = pixel_red > from_red ?
pixel_red - from_red : from_red - pixel_red;
green_delta = pixel_green > from_green ?
pixel_green - from_green : from_green - pixel_green;
blue_delta = pixel_blue > from_blue ?
pixel_blue - from_blue : from_blue - pixel_blue;
new_red = CLAMP (to_red + red_delta, 0, 255);
new_green = CLAMP (to_green + green_delta, 0, 255);
new_blue = CLAMP (to_blue + blue_delta, 0, 255);
}
else
{
new_red = pixel_red;
new_green = pixel_green;
new_blue = pixel_blue;
}
/* fill buffer */
dest_row[idx + 0] = new_red;
dest_row[idx + 1] = new_green;
dest_row[idx + 2] = new_blue;
/* copy alpha-channel */
if (has_alpha)
dest_row[idx + 3] = src_row[x * bpp + 3];
}
/* store the dest */
gimp_pixel_rgn_set_row (&destPR, dest_row, x1, y, width);
/* and tell the user what we're doing */
if (!preview && (y % 10) == 0)
gimp_progress_update ((gdouble) y / (gdouble) height);
}
EDIT/ADDITION
Another way you could have transformed red to blue would be with this matrix:
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
-1 0 1 0 1
The only values that really matter are the bottom ones in this matrix.
This would be the same as saying subtract 255 from red, keep green the same, and then add 255 to blue. You could cut the alpha in half like so as well like so:
-1 0 1 -0.5 1
So (just like the gimp source) you just need to find the difference between your current color and your target color, for each channel, and then apply the difference. Instead of channel values from 0 to 255 you would use values from 0 to 1.
You could have changed it from red to green like so:
-1 1 0 0 1
See here for some good info:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms533875%28v=vs.85%29.aspx
Good luck.
I solved it by creating a reflection matrix via D3DXMatrixReflect using a plane that's perpendicular to the vector AB and intersects the midpoint of the AB.
D3DXVECTOR3 AB( colorA.r-colorB.r, colorA.g-colorB.g, colorA.b-colorB.b );
D3DXPLANE plane( AB.x, AB.y, AB.z, -AB.x*midpoint.x-AB.y*midpoint.y-AB.z*midpoint.z );
D3DXMatrixReflect

Wrong pixel locations with glDrawPixels

I have been playing around with trying to draw a 320 by 240 full screen resolution image in opengl using java and lwjgl. I set the resolution to 640 by 480 and doubled the size of the pixels to fill in the space. After a lot of google searching I found some information about using the glDrawPixels function to speed up drawing to the screen. I wanted to test it by assigning random colors to all the pixels on the screen, but it wouldn't fill the screen. I divided the width into 4 sections of 80 pixels each and colored them red, green, blue, and white. I saw that I was interleaving the colors but I can't figure out how.
Here is an image of the output:
Here is where I run the openGL code:
// init OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 640, 0, 480, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
while (!Display.isCloseRequested()) {
pollInput();
// Clear the screen and depth buffer
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
randomizePixels();
GL11.glRasterPos2i(0, 0);
GL11.glDrawPixels(320, 240,GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE,buff);
GL11.glPixelZoom(2, 2);
Display.update();
}
Display.destroy();
}
and here is where I create the pixel color data:
public void randomizePixels(){
for(int y = 0; y < 240; y++){
for(int x = 0; x < 320; x+=4){
/*
pixels[x * 320 + y] = (byte)(-128 + ran.nextInt(256));
pixels[x * 320 + y + 1] = (byte)(-128 + ran.nextInt(256));
pixels[x * 320 + y + 2] = (byte)(-128 + ran.nextInt(256));
pixels[x * 320 + y + 3] = (byte)(-128 + ran.nextInt(256));
*/
if(x >= 0 && x < 80){
pixels[y * 240 + x] = (byte)128;
pixels[y * 240 + x + 1] = (byte)0;
pixels[y * 240 + x + 2] = (byte)0;
pixels[y * 240 + x + 3] = (byte)128;
}else if(x >= 80 && x < 160){
pixels[y * 240 + x] = (byte)0;
pixels[y * 240 + x + 1] = (byte)128;
pixels[y * 240 + x + 2] = (byte)0;
pixels[y * 240 + x + 3] = (byte)128;
}else if(x >= 160 && x < 240){
pixels[y * 240 + x] = (byte)0;
pixels[y * 240 + x + 1] = (byte)0;
pixels[y * 240 + x + 2] = (byte)128;
pixels[y * 240 + x + 3] = (byte)128;
}else if(x >= 240 && x < 320){
pixels[y * 240 + x] = (byte)128;
pixels[y * 240 + x + 1] = (byte)128;
pixels[y * 240 + x + 2] = (byte)128;
pixels[y * 240 + x + 3] = (byte)128;
}
}
}
buff.put(pixels).flip();
}
If you can figure out why I can't get the pixels to line up to the x and y coordinates I want them to go to that would be great. I have read that glDrawPixels probably isn't the best or fastest way to draw pixels to the screen, but I want to understand why I'm having this particular issue before I have to move on to some other method.
Just load your image (unscaled) into a texture and draw a textured quad.
Don't use glDrawPixels. This function was never properly optimized in most drivers and has was deprecated since OpenGL-2 and got removed from OpenGL-3 core and later.
I spot 2 issues in your randomizePixels().
1. Indexing Pixel Buffer
The total size of pixel buffer is 320x240x4 bytes because the pixel type is GL_RGBA. So, indexing each pixel with subscript operator, [], it would be;
for(int y = 0; y < 240; y++)
{
for(int x = 0; x < 320; x++)
{
pixels[y * 320 * 4 + x * 4 + 0] = ... // R
pixels[y * 320 * 4 + x * 4 + 1] = ... // G
pixels[y * 320 * 4 + x * 4 + 2] = ... // B
pixels[y * 320 * 4 + x * 4 + 3] = ... // A
}
}
2. Colour Value
The max intensity of 8bit colour is 255, for example, an opaque red pixel would be (255, 0, 0, 255).
your operating on the texture. better do it on quadrature. it would yield good results

implementing erosion, dilation in C, C++

I have theoretical understanding of how dilation in binary image is done.
AFAIK, If my SE (structuring element) is this
0 1
1 1.
where . represents the centre, and my image(binary is this)
0 0 0 0 0
0 1 1 0 0
0 1 0 0 0
0 1 0 0 0
0 0 0 0 0
so the result of dilation is
0 1 1 0 0
1 1 1 0 0
1 1 0 0 0
1 1 0 0 0
0 0 0 0 0
I got above result by shifting Image in 0, +1 (up) and and -1(left) direction, according to SE, and taking the union of all these three shifts.
Now, I need to figure out how to implement this in C, C++.
I am not sure how to begin and how to take the union of sets.
I thought of representing original image,three shifted images and final image obtained by taking union; all using matrix.
Is there any place where I can get some sample solution to start with or any ideas to proceed ?
Thanks.
There are tons of sample implementations out there.. Google is your friend :)
EDIT
The following is a pseudo-code of the process (very similar to doing a convolution in 2D). Im sure there are more clever way to doing it:
// grayscale image, binary mask
void morph(inImage, outImage, kernel, type) {
// half size of the kernel, kernel size is n*n (easier if n is odd)
sz = (kernel.n - 1 ) / 2;
for X in inImage.rows {
for Y in inImage.cols {
if ( isOnBoundary(X,Y, inImage, sz) ) {
// check if pixel (X,Y) for boundary cases and deal with it (copy pixel as is)
// must consider half size of the kernel
val = inImage(X,Y); // quick fix
}
else {
list = [];
// get the neighborhood of this pixel (X,Y)
for I in kernel.n {
for J in kernel.n {
if ( kernel(I,J) == 1 ) {
list.add( inImage(X+I-sz, Y+J-sz) );
}
}
}
if type == dilation {
// dilation: set to one if any 1 is present, zero otherwise
val = max(list);
} else if type == erosion {
// erosion: set to zero if any 0 is present, one otherwise
val = min(list);
}
}
// set output image pixel
outImage(X,Y) = val;
}
}
}
The above code is based on this tutorial (check the source code at the end of the page).
EDIT2:
list.add( inImage(X+I-sz, Y+J-sz) );
The idea is that we want to superimpose the kernel mask (of size nxn) centered at sz (half size of mask) on the current image pixel located at (X,Y), and then just get the intensities of the pixels where the mask value is one (we are adding them to a list). Once extracted all the neighbors for that pixel, we set the output image pixel to the maximum of that list (max intensity) for dilation, and min for erosion (of course this only work for grayscale images and binary mask)
The indices of both X/Y and I/J in the statement above are assumed to start from 0.
If you prefer, you can always rewrite the indices of I/J in terms of half the size of the mask (from -sz to +sz) with a small change (the way the tutorial I linked to is using)...
Example:
Consider this 3x3 kernel mask placed and centered on pixel (X,Y), and see how we traverse the neighborhood around it:
--------------------
| | | | sz = 1;
-------------------- for (I=0 ; I<3 ; ++I)
| | (X,Y) | | for (J=0 ; J<3 ; ++J)
-------------------- vect.push_back( inImage.getPixel(X+I-sz, Y+J-sz) );
| | | |
--------------------
Perhaps a better way to look at it is how to produce an output pixel of the dilation. For the corresponding pixel in the image, align the structuring element such that the origin of the structuring element is at that image pixel. If there is any overlap, set the dilation output pixel at that location to 1, otherwise set it to 0.
So this can be done by simply looping over each pixel in the image and testing whether or not the properly shifted structuring element overlaps with the image. This means you'll probably have 4 nested loops: x img, y img, x se, y se. So for each image pixel, you loop over the pixels of the structuring element and see if there is any overlap. This may not be the most efficient algorithm, but it is probably the most straightforward.
Also, I think your example is incorrect. The dilation depends on the origin of the structuring element. If the origin is...
at the top left zero: you need to shift the image (-1,-1), (-1,0), and (0,-1) giving:
1 1 1 0 0
1 1 0 0 0
1 1 0 0 0
1 0 0 0 0
0 0 0 0 0
at the bottom right: you need to shift the image (0,0), (1,0), and (0,1) giving:
0 0 0 0 0
0 1 1 1 0
0 1 1 0 0
0 1 1 0 0
0 1 0 0 0
MATLAB uses floor((size(SE)+1)/2) as the origin of the SE so in this case, it will use the top left pixel of the SE. You can verify this using the imdilate MATLAB function.
OpenCV
Example: Erosion and Dilation
/* structure of the image variable
* variable n stores the order of the square matrix */
typedef struct image{
int mat[][];
int n;
}image;
/* function recieves image "to dilate" and returns "dilated"*
* structuring element predefined:
* 0 1 0
* 1 1 1
* 0 1 0
*/
image* dilate(image* to_dilate)
{
int i,j;
int does_order_increase;
image* dilated;
dilated = (image*)malloc(sizeof(image));
does_order_increase = 0;
/* checking whether there are any 1's on d border*/
for( i = 0 ; i<to_dilate->n ; i++ )
{
if( (to_dilate->a[0][i] == 1)||(to_dilate->a[i][0] == 1)||(to_dilate->a[n-1][i] == 1)||(to_dilate->a[i][n-1] == 1) )
{
does_order_increase = 1;
break;
}
}
/* size of dilated image initialized */
if( does_order_increase == 1)
dilated->n = to_dilate->n + 1;
else
dilated->n = to_dilate->n;
/* dilating image by checking every element of to_dilate and filling dilated *
* does_order_increase serves to cope with adjustments if dilated 's order increase */
for( i = 0 ; i<to_dilate->n ; i++ )
{
for( j = 0 ; j<to_dilate->n ; j++ )
{
if( to_dilate->a[i][j] == 1)
{
dilated->a[i + does_order_increase][j + does_order_increase] = 1;
dilated->a[i + does_order_increase -1][j + does_order_increase ] = 1;
dilated->a[i + does_order_increase ][j + does_order_increase -1] = 1;
dilated->a[i + does_order_increase +1][j + does_order_increase ] = 1;
dilated->a[i + does_order_increase ][j + does_order_increase +1] = 1;
}
}
}
/* dilated stores dilated binary image */
return dilated;
}
/* end of dilation */