Converting float to unsigned char causes wrong values - c++

I've created a function that creates a BMP image using RGB values.
The RGB values are stored as floats that range from 0.0 to 1.0.
When writing the values to the BMP file they need to range from 0 to 255.0 so I multiply the floats by 255.0
They also need to be unsigned chars.
EDIT: Unless one of you can think of a better type.
So basically what I do is this
unsigned char pixel[3]
//BMP Expects BGR
pixel[0] = image.b*255.0;
pixel[1] = image.g*255.0;
pixel[2] = image.r*255.0;
fwrite(&pixel, 1, 3, file);
Where image.r is a float.
There seems to be some kind of loss of data in the conversion because some parts of the image are black when they shouldn't be.
The BMP image is set to 24 bits per pixel
I was going to post images but I don't have enough reputation.
edit:
BMP image
http://tinypic.com/r/2qw3cdv/8
Printscreen
http://tinypic.com/r/2q3rm07/8
Basically light blue parts become black.
If I multiply by 128 instead the image is darker but otherwise accurate. It starts getting weird around 180 ish

Related

can't access pixel intensities in image using cimg (returns 0)

I'm tries to access Cimg pixel values to print out the pixel intensity that my mouse is at, as well as calculating a histogram. However, I got all zeros from Cimg object.
The cimg image is initiated from memory buffer and it is 12 bit gray scale image, but padded to 16 bit to save in memory.
The code below is defined in a function that is called multiple times. I want to refresh the images in the current display and not to produce a new one every time the function is called. So the Cimgdisp is defined outside the function.
#include "include\CImg.h"
int main(){
CImg <unsigned short> image(width,height,1,1);
CImgDisplay disp(image);
//showImg() get called multiple times here
}
void showImg(){
unsigned short* imgPtr = (unsigned short*) (getImagePtr());
CImg <unsigned short> img(imgPtr,width,height);
img*=(65535/4095);//Renormalise from 12 bit input to 16bit for better display
//Display
disp->render(img);
disp->paint();
img*=(4095/65535);//Normalise back to get corect intensities
CImg <float> hist(img.histogram(100));
hist.display_graph(0,3);
//find mouse position and disp intensity
mouseX = disp->mouse_x()*width/disp->width();//Rescale the position of the mouse to true position of the image
mouseY = disp->mouse_y()*height/disp->height();
if (mouseX>0&mouseY>0){
PxIntensity = img(mouseX,mouseY,0,0);}
else {
PxIntensity = -1;}
}
All the intensities I retrieve are zero and the histogram is also zero.
img*=(4095/65535);//Normalise back to get corect intensities is incorrect, as (4095/65535)=0 in C/C++ (division of an integer by a larger one).
Maybe img*=(4095/65535.); ?
If you just want to scale between 12-bit and 16-bit and back then just using bit-shifts might be better.
img<<=4;//Renormalise from 12 bit input to 16bit for better display
//Display
disp->render(img);
disp->paint();
img>>=4;//Normalise back to get corect intensities

how to acces colour of individual pixels using SOIL in cpp

I would like to access the RGB valuas from individual pixels. I know I can get an unsigned char array by calling
unsigned char* pixels = SOIL_load_image(picturename.c_str(), &_w, &_h, 0, SOIL_LOAD_RGB);
However I dont understand what these chars mean. The documentation says:
// The return value from an image loader is an 'unsigned char *' which points
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
// with each pixel consisting of N interleaved 8-bit components; the first
// pixel pointed to is top-left-most in the image. There is no padding between
// image scanlines or between pixels, regardless of format. The number of
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
// If req_comp is non-zero, *comp has the number of components that _would_
// have been output otherwise. E.g. if you set req_comp to 4, you will always
// get RGBA output, but you can check *comp to easily see if it's opaque.
However when I load an 10 by 10 pixels image to test it i get an huge ammound of chars in the array (almost 54000) this seems way too much. How do i get the individual pixel colour that I can do something like this:
int colourvalue = pixel[y*width+x];
i cant seem to find this

Rendering pixels from array of RGB values in SDL 1.2?

I'm working on a NES emulator right now and I'm having trouble figuring out how to render the pixels. I am using a 3 dimensional array to hold the RGB value of each pixel. The array definition looks like this for the 256 x 224 screen size:
byte screenData[224][256][3];
For example, [0][0][0] holds the blue value, [0][0][1] holds the green values and [0][0][2] holds the red value of the pixel at screen position [0][0].
When the vblank flag goes high, I need to render the screen. When SDL goes to render the screen, the screenData array will be full of the RGB values for each pixel. I was able to find a function named SDL_CreateRGBSurfaceFrom that looked like it may work for what I want to do. However, all of the examples I have seen use 1 dimensional arrays for the RGB values and not a 3 dimensional array.
What would be the best way for me to render my pixels? It would also be nice if the function allowed me to resize the surface somehow so I didn't have to use a 256 x 224 window size.
You need to store the data as an unidimensional char array:
int channels = 3; // for a RGB image
char* pixels = new char[img_width * img_height * channels];
// populate pixels with real data ...
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)pixels,
img_width,
img_height,
channels * 8, // bits per pixel = 24
img_width * channels, // pitch
0x0000FF, // red mask
0x00FF00, // green mask
0xFF0000, // blue mask
0); // alpha mask (none)
In 2.0, use SDL_Texture + SDL_TEXTUREACCESS_STREAMING + SDL_RenderCopy, it's faster than SDL_RenderPoint.
See:
official example: http://hg.libsdl.org/SDL/file/e12c38730512/test/teststreaming.c
my derived example which does not require blob data and compares both methods: https://github.com/cirosantilli/cpp-cheat/blob/0607da1236030d2e1ec56256a0d12cadb6924a41/sdl/plot2d.c
Related: Why do I get bad performance with SDL2 and SDL_RenderCopy inside a double for loop over all pixels?

converting float to unsigned char in OpenCV

I have designed a filter in the form of a horizontal 1D vector using OpenCV and C++. The vector consists of float data. The original uchar data of the grayscale image is multiplied with this float vector as a 1 dimensional window to obtain the result. However, I am not getting proper results.
When the vector elements are multiplied with the image pixel values, the exceed the range 0-255 and I think this is causing problems.
Is there any way to typecast this float data into uchar to get proper results?
I'm using Img.at<uchar> = (uchar)(floatVector) right now.
Thanks
I will suggest you to type cast after you have multiplied...so convert your uchar image matrix to CV_32FC1 (since you say its grayscale image so channel = 1)....do the convolution of the image with your filter then type cast the values to ucharfor displaying may be..
You want to carry out the multiplication in the float type, and only at the end, convert back to unsigned char. Don't forget to also have your float vector normalized (all values add up to 1)
So basically you want
Data.at(coordinates) = (unsigned char)
(floatVector(0)*(Data.at(coord0) + ... + FloatVector(last)*Data.at(coordLast))

getting Y value[Ycbcr] of one Pixel in opencv

I'm trying to get the Y value of pixel from a frame that's in Ycbcr color mode.
here what I' wrote:
cv::Mat frame, Ycbcrframe, helpframe;
........
cvtColor(frame,yCbCrFrame,CV_RGB2YCrCb); // converting to Ycbcr
Vec3b intensity =yCbCrFrame.at<uchar>(YPoint);
uchar yv = intensity.val[0]; // I thought it's my Y value but its not, coz he gives me I think the Blue channel of RGB color space
any Idea how what the correct way to do that
what about the following code?
Vec3f Y_pix = YCbCrframe.at<Vec3f>(rows, cols);
int pixelval = Y_pix[0];
(P.S. I havent tried it yet)
You need to know both the depth (numerical format and precision of channel sample) as well as the channel count (typically 3, but can also be 1 (monochrome) or 4 (alpha-containing)), ahead of time.
For 3-channel, 8-bit unsigned integer (a.k.a. byte or uchar) pixel format, each pixel can be accessed with
mat8UC3.at<cv::Vec3b>(pt);