How to composite argb image data on top of xrgb image data - c++

I have a pointer to an 32bit argb image's pixel data and a 32bit xrgb image's pixel data. How can I composite the argb on top of xrgb image while making use of the alpha component?
Visual Studio 2008 C++
Edit:
Is there a quicker (faster processing) way to do the compositing than this:
float alpha = (float)Overlay[3] / 255;
float oneLessAlpha = 1 - alpha;
Destination[2] = (Overlay[2] * alpha + Background[2] * oneLessAlpha);
Destination[1] = (Overlay[1] * alpha + Background[1] * oneLessAlpha);
Destination[0] = (Overlay[0] * alpha + Background[0] * oneLessAlpha);

This depends on what you are trying to achieve. You can assume your second image to have an alpha of 255 everywhere, then compose each pixel by linear interpolation / alpha blending (assuming float values in [0,1], adjust accordingly):
out(x,y) = argb(x,y).rgb * argb(x,y).a + xrgb(x,y).rgb * (1.-argb(x.y).a)
This way, all pixel with no transparency from your argb image will be always displayed "atop", while pixels with full transparency are invisible and replaced by those from the xrgb pixels. All pixels inbetween are linearly blended.

Presumably by XRGB you mean a bitmap with four bytes per pixel, but what would be the alpha channel left at some constant value.
An obvious starting point would be to draw the XRGB bitmap first, and the RGBA bitmap second. When you draw the second, enable blending (glEnable(GL_BLEND);) and set your blend function with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);. This way the blending depends only on the alpha channel in the source (the RGBA) and ignores any in the destination (the XRGB bitmap that's already been drawn).
Edit: Oops -- somehow I thought I saw some reference to OpenGL, but rereading (and noting the comment) no such thing is there. Doing the job without OpenGL isn't terribly difficult, just generally slower. Let's call the pixels from the two input bitmaps S and D, and the corresponding pixel in the result C. In this case we can compute each pixel in C as:
Cr = Sr * Sa + Dr * (1-Sa)
Cg = Sg * Sa + Dg * (1-Sa)
Cb = Sb * Sa + Db * (1-Sa)
This assumes that you normalize (at least) the A channel to the range of 0..1, and that the ARGB bitmap is S and the XRGB is D.

Here's some code that should work more or less (didn't test it, no compiler on this machine...).
DWORD* pSrc; // Pointer to current row of ARGB bitmap
DWORD* pDst; // Pointer to current row of XRGB bitmap
...
BYTE* src_r = GetRValue(*pSrc);
BYTE* src_g = GetGValue(*pSrc);
BYTE* src_b = GetBvalue(*pSrc);
BYTE* src_a = *pSrc >> 24;
BYTE* dst_r = GetRValue(*pDst);
BYTE* dst_g = GetGValue(*pDst);
BYTE* dst_b = GetBvalue(*pDst);
BYTE* dst_a = 255 - src_a;
*pDst = RGB(((src_r * src_a) + (dst_r * dst_a)) >> 8,
((src_g * src_a) + (dst_g * dst_a)) >> 8,
((src_b * src_a) + (dst_b * dst_a)) >> 8);

Related

no suitable conversion function from "Magick::Color" to "MagickCore::Quantum" exists

I know already why it gives that error code-wise.
Problem is, I started using the library itself today and following the tutorial I found this.
I installed the "ImageMagick-7.0.9-1-Q16-x64-dll" version of the library, and tried to find the shortest code that gave that error, which is:
#include <Magick++.h>
int main(){
Magick::Quantum result = Magick::Color("black");
}
Given the tutorial(following one), a method that converts from Magick::Color to Magic::Quantum should exist
// Example of using an image pixel cache
Image my_image("640x480", "white"); // we'll use the 'my_image' object in this example
my_image.modifyImage(); // Ensure that there is only one reference to
// underlying image; if this is not done, then the
// image pixels *may* remain unmodified. [???]
Pixels my_pixel_cache(my_image); // allocate an image pixel cache associated with my_image
Quantum* pixels; // 'pixels' is a pointer to a Quantum array
// define the view area that will be accessed via the image pixel cache
int start_x = 10, start_y = 20, size_x = 200, size_y = 100;
// return a pointer to the pixels of the defined pixel cache
pixels = my_pixel_cache.get(start_x, start_y, size_x, size_y);
// set the color of the first pixel from the pixel cache to black (x=10, y=20 on my_image)
*pixels = Color("black");
// set to green the pixel 200 from the pixel cache:
// this pixel is located at x=0, y=1 in the pixel cache (x=10, y=21 on my_image)
*(pixels+200) = Color("green");
// now that the operations on my_pixel_cache have been finalized
// ensure that the pixel cache is transferred back to my_image
my_pixel_cache.sync();
which gives that error ( no suitable conversion function from "Magick::Color" to "MagickCore::Quantum" exists ) at the following lines
*pixels = Color("black");
*(pixels+200) = Color("green");
I believe you are confusing a data-type with a structure. The pixels represents a continuous list of Quantum parts.
Assuming that we're working with RGB colorspace. You would need to set each color part.
Color black("black");
*(pixels + 0) = black.quantumRed();
*(pixels + 1) = black.quantumGreen();
*(pixels + 2) = black.quantumBlue();
To set the 200th pixel, you would need to multiply the offset by the parts-per-pixel count.
Color green("green");
int offset = 199 * 3; // First pixel starts at 0, and 3 parts (Red, Green, Blue)
*(pixels + offset + 0) = green.quantumRed();
*(pixels + offset + 1) = green.quantumGreen();
*(pixels + offset + 2) = green.quantumBlue();

How to use a .raw file in opengl

I'm trying to read a .raw image format and do some modifications on it in OpenGL. I can read the image like this:
int width, height;
BYTE * data;
FILE * file;
file = fopen( filename, "rb" );
if ( file == NULL ) return 0;
width = 256;
height = 256;
data = malloc( width * height * 3 );
fread( data, width * height * 3, 1, file );
fclose( file );
But i dont know how to use glDrawPixels to draw the picture.
My second problem is that I dont know how can I access each pixel. I mean in a .raw image format, each pixel should have 3 integers for storing RGB values(Am I right?). How can I access these RGB values directly?
There's no such thing as a .raw in the hard and fast sense. The name implies image data with no header but doesn't specify the format of the data. RGB is likely but so is RGBA and it's trivial to think of almost endless other possibilities.
Assuming RGB ordering, one byte per channel, then: each pixel is three bytes wide. So the nth pixel is:
r = data[n*3 + 0]
g = data[n*3 + 1]
b = data[n*3 + 2]
Assuming the data is set out so that the pixels are stored in left-to-right order, line by line, then on the first line the pixel at x=3 is at n=3, on the second it's at n=(width of first line)+3, on the third it's at n=(combined width of first two lines)+3, etc.
So:
r = data[(x + y*width)*3 + 0]
g = data[(x + y*width)*3 + 1]
b = data[(x + y*width)*3 + 2]
To use glDrawPixels just follow what the manual tells you to specify as the parameters. It says:
void glDrawPixels( GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid * data);
You say that width and height are 256. You've said that the format is RGB. Scan down the documentation and you'll see that the corresponding GLenum is GL_RGB. You're saying each channel is a single byte in size. So that's GL_UNSIGNED_BYTE. You've loaded the data to data. So:
glDrawPixels(256, 256, GL_RGB, GL_UNSIGNED_BYTE, data);
Further comments: obviously get this working first so you've something to build on but glDrawPixels is almost unused in practice. As a result it isn't even part of OpenGL ES or, correspondingly, WebGL. Look at the semantics of the thing. You supply your buffer every time you call. OpenGL can't know whether it has been modified since the last call. So every call transfers your data from CPU to GPU. Look into submitting your data once as a texture and drawing using geometry. That'll save the per-call transfer cost and therefore be a lot more efficient.

Kinect SDK: align depth and color frames

I'm working with Kinect sensor and I'm trying to align depth and color frames so that I can save them as images which "fit" into each other. I've spent a lot of time going through msdn forums and modest documentation of Kinect SDK and I'm getting absolutely nowhere.
Based on this answer: Kinect: Converting from RGB Coordinates to Depth Coordinates
I have the following function, where depthData and colorData are obtained from NUI_LOCKED_RECT.pBits and mappedData is the output containing new color frame, mapped to depth coordinates:
bool mapColorFrameToDepthFrame(unsigned char *depthData, unsigned char* colorData, unsigned char* mappedData)
{
INuiCoordinateMapper* coordMapper;
// Get coordinate mapper
m_pSensor->NuiGetCoordinateMapper(&coordMapper);
NUI_DEPTH_IMAGE_POINT* depthPoints = new NUI_DEPTH_IMAGE_POINT[640 * 480];
HRESULT result = coordMapper->MapColorFrameToDepthFrame(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, 640 * 480, reinterpret_cast<NUI_DEPTH_IMAGE_PIXEL*>(depthData), 640 * 480, depthPoints);
if (FAILED(result))
{
return false;
}
int pos = 0;
int* colorRun = reinterpret_cast<int*>(colorData);
int* mappedRun = reinterpret_cast<int*>(mappedData);
// For each pixel of new color frame
for (int i = 0; i < 640 * 480; ++i)
{
// Find the corresponding pixel in original color frame from depthPoints
pos = (depthPoints[i].y * 640) + depthPoints[i].x;
// Set pixel value if it's within frame boundaries
if (pos < 640 * 480)
{
mappedRun[i] = colorRun[pos];
}
}
return true;
}
All I get when running this code is an unchanged color frame with removed (white) all pixels where depthFrame had no information.
With the OpenNI framework there an option call registration.
IMAGE_REGISTRATION_DEPTH_TO_IMAGE – The depth image is transformed to have the same apparent vantage point as the RGB image.
OpenNI 2.0 and Nite 2.0 works very well to capture Kinect information and there a lot of tutorials.
You can have a look to this :
Kinect with OpenNI
And OpenNi have a example in SimplerViewer that merge Depth and Color maybe you can just look on that and try it.
This might not be the quick answer you're hoping for, but this transformation is done successfully within the ofxKinectNui addon for openFrameworks (see here).
It looks like ofxKinectNui delegates to the GetColorPixelCoordinatesFromDepthPixel function defined here.
I think the problem is that you're calling MapColorFrameToDepthFrame, when you should actually call MapDepthFrameToColorFrame.
The smoking gun is this line of code:
mappedRun[i] = colorRun[pos];
Reading from pos and writing to i is backwards, since pos = depthPoints[i] represents the depth coordinates corresponding to the color coordinates at i. You actually want to iterate over writing all depth coordinates and read from the input color image at the corresponding color coordinates.
I think that in your code there are different not correct lines.
First of all, which kind of depth map are you passing to your function?
Depth data is storred using two bytes for each value, that means that the correct type of the pointer that you should use for your depth data
is unsigned short.
Second point is that from what i have understood, you want to map depth frame to color frame, so the correct function that you have
to call from kinect sdk is MapDepthFrameToColorFrame instead of MapColorFrameToDepthFrame.
Finally the function will return a map of point where for each depth data at position [i], you have the position x and position y where that point should
be mapped.
To do this you don't need for colorData pointer.
So your function should be modified as follow:
/** Method used to build a depth map aligned to color frame
#param [in] depthData : pointer to your data;
#param [out] mappedData : pointer to your aligned depth map;
#return true if is all ok : false whene something wrong
*/
bool DeviceManager::mapColorFrameToDepthFrame(unsigned short *depthData, unsigned short* mappedData){
INuiCoordinateMapper* coordMapper;
NUI_COLOR_IMAGE_POINT* colorPoints = new NUI_COLOR_IMAGE_POINT[640 * 480]; //color points
NUI_DEPTH_IMAGE_PIXEL* depthPoints = new NUI_DEPTH_IMAGE_PIXEL[640 * 480]; // depth pixel
/** BE sURE THAT YOU ARE WORKING WITH THE RIGHT HEIGHT AND WIDTH*/
unsigned long refWidth = 0;
unsigned long refHeight = 0;
NuiImageResolutionToSize( NUI_IMAGE_RESOLUTION_640x480, refWidth, refHeight );
int width = static_cast<int>( refWidth ); //get the image width in a right way
int height = static_cast<int>( refHeight ); //get the image height in a right way
m_pSensor>NuiGetCoordinateMapper(&coordMapper); // get the coord mapper
//Map your frame;
HRESULT result = coordMapper->MapDepthFrameToColorFrame( NUI_IMAGE_RESOLUTION_640x480, width * height, depthPoints, NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, width * height, colorPoints );
if (FAILED(result))
return false;
// apply map in terms of x and y (image coordinates);
for (int i = 0; i < width * height; i++)
if (colorPoints[i].x >0 && colorPoints[i].x < width && colorPoints[i].y>0 && colorPoints[i].y < height)
*(mappedData + colorPoints[i].x + colorPoints[i].y*width) = *(depthData + i );
// free your memory!!!
delete colorPoints;
delete depthPoints;
return true;
}
Make sure that your mappedData has been initialized in correct way, for example as follow.
mappedData = (USHORT*)calloc(width*height, sizeof(ushort));
Remember that kinect sdk does not provide an accurate align function between color and depth data.
If you want an accurate alignment between two images you should use a calibration model.
In that case i suggest you to use the Kinect Calibration Toolbox, based on Heikkilä calibration model.
You can find it in the follow link:
http://www.ee.oulu.fi/~dherrera/kinect/.
First of all, you must calibrate your device.
That means, you should calibrate the RGB and the IR sensor and then find the transformation between RGB and IR.
Once you know this information, you can apply the function:
RGBPoint = RotationMatrix * DepthPoint + TranslationVector
Check OpenCV or ROS projects for further details on it.
Extrinsic Calibration
Intrinsic Calibration

How to treat alpha transparency from PNG directly in memory?

I would appreciate the help of you low level programmers... My problem is this:
I want to print a bitmap of format ARGB8888 directly into video memory. The form of the bitmap is alright, the problem is the alpha channel that I can't figure out how to use. I've seen code in wikipedia that overlays the pixels like this:
CompositedPixelColor = Alpha * ForegroundPixelColor + (1 - Alpha) * BackgroundPixelColor
Where a color varies from 0 - 1. This is done for each channel R G B.
What I'm doing is copy each byte for each color of each pixel of my bitmap directly to the video memory using the formula above, but I'm missing something because the colors don't present theirselves alright.
I'm trying to do something like the code posted in this thread:
http://www.badadev.com/create-a-photo-editing-app/
But here they don't treat transparency, and that is my problem. Thanxs!
In the code you posted alpha is treated as a value between 0 and 1, which of course doesn't work if you use you alpha channel as an unsigned char, use the following if you want to do it in integer space:
unsigned short background = 0x40;
unsigned short foreground = 0xe0;
unsigned short alpha = 0xc0;
unsigned short compositedcolor = (alpha * foreground + (0xff - alpha) * background) >> 8;
note that while these are shorts the values should all be 0 - 255, the short is just needed as computational space for the char * char products, you could also use intermediate casts, but I just used unsigned short types for all to make it more readable.

adjust bitmap image brightness/contrast using c++

adjust image brightness/contrast using c++ without using any other 3rd party library or dependancy
Image brightness is here - use the mean of the RGB values and shift them.
Contrast is here with other languages solutions available as well.
Edit in case the above links die:
The answer given by Jerry Coffin below covers the same topic and has links that still live.
But, to adjust brightness, you add a constant value to each for the R,G,B fields of an image. Make sure to use saturated math - don't allow values to go below 0 or above the maximum allowed in your bit-depth (8-bits for 24-bit color)
RGB_struct color = GetPixelColor(x, y);
size_t newRed = truncate(color.red + brightAdjust);
size_t newGreen = truncate(color.green + brightAdjust);
size_t newBlue = truncate(color.blue + brightAdjust);
For contrast, I have taken and slightly modified code from this website:
float factor = (259.0 * (contrast + 255.0)) / (255.0 * (259.0 - contrast));
RGB_struct color = GetPixelColor(x, y);
size_t newRed = truncate((size_t)(factor * (color.red - 128) + 128));
size_t newGreen = truncate((size_t)(factor * (color.green - 128) + 128));
size_t newBlue = truncate((size_t)(factor * (color.blue - 128) + 128));
Where truncate(int value) makes sure the value stays between 0 and 255 for 8-bit color. Note that many CPUs have intrinsic functions to do this in a single cycle.
size_t truncate(size_t value)
{
if(value < 0) return 0;
if(value > 255) return 255;
return value;
}
Read in the image with a library just as the Independent JPEG library. When you have raw data, you can convert it from RGB to HSL or (preferably) CIE Lab*. Both contrast and brightness will basically just involve adjustments to the L channel -- to adjust brightness, just adjust all the L values up or down by an appropriate amount. To adjust contrast, you basically adjust the difference between a particular value and the center value. You'll generally want to do this non-linearly, so values near the middle of the range are adjusted quite a bit, but values close to the ends or the range aren't affected nearly as much (and any that are at the very ends, aren't changed at all).
Once you've done that, you can convert back to RGB, and then back to a normal format such as JPEG.