Reputation: 129
i have an issue when using Cairo to draw image in linux system. the output image color not similar to original image if using cairo_image_surface_create method. like code below:
int width, height, channels;
unsigned char* data = stbi_load(imagePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
this->imageSource = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
unsigned char * surface_data = cairo_image_surface_get_data(this->imageSource);
memcpy(surface_data, data, width * height * 4 * sizeof(unsigned char));
cairo_surface_mark_dirty(this->imageSource);
free(data);
But the color will the same when using cairo_image_surface_create_from_png (this api only support png format). see my code as below:
this->imageSource = cairo_image_surface_create_from_png(imagePath.c_str());
Also have a look on attach image to for clearly.
Upvotes: 0
Views: 451
Reputation: 129
Image now drawn with correct channel, but it spend more time to re-order pixel data channel. Can you all suggest other way to save processing time on this case. Please see my code below:
int width, height, channels;
//imagePath: [string] is input path of image on disk
unsigned char* data = stbi_load(imagePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
int size = width * height * 4;
uint32_t * dest_data = ( uint32_t * ) malloc(sizeof( uint32_t ) * width * height);
int i;
int dest_index = 0;
uint8_t *pixel, alpha, red, green, blue;
uint32_t p;
//***important: re-order pixel data after receive from stbi_load
for (i = 0; i < size; i += 4) {
pixel = &data [ i ];
alpha = pixel [ 3 ];
if (alpha == 0) {
p = 0;
} else {
red = pixel [ 0 ];
green = pixel [ 1 ];
blue = pixel [ 2 ];
if (alpha != 0xff) {
red = multiply_alpha(alpha, red);
green = multiply_alpha(alpha, green);
blue = multiply_alpha(alpha, blue);
}
p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
}
dest_data [ dest_index ] = p;
dest_index++;
}
//create new surface instance
this->imageSource = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
unsigned char * surface_data = cairo_image_surface_get_data(this->imageSource);
//map image data to surface
memcpy(surface_data, dest_data, width * height * 4 * sizeof(unsigned char));
//mark dirty to call reload surface
cairo_surface_mark_dirty(this->imageSource);
//free memory
free(dest_data);
free(data);
as i read the library of stb_image, in function stbi_load there are no param call ORDER. can anyone suggest me the other solution?
Upvotes: 0
Reputation: 9867
I am pretty sure that the red and blue channels are swapped on that right image. Sadly, I have no idea what STBI_rgb_alpha
is and Google does not find anything that looks like helpful docs, so:
uint32_t
with alpha in the high byte and blue in the low byte, i.e. uint32_t pixel_value = alpha << 24 | red << 16 | green << 8 | blue;
.STBI_rgb_alpha
means that the values are saved byte-wise, independent of the system endian.I also find the link by user @Bob__ in the comments really helpful:
Are you sure that the channels are stored in the expected order? See e.g. http://en.m.wikipedia.org/wiki/RGBA_color_model#Representation
Upvotes: 1