在开罗绘制图像时的不同颜色
Difference color when drawing image in Cairo
我在 linux 系统中使用 Cairo 绘制图像时遇到问题。如果使用 cairo_image_surface_create 方法,输出图像颜色与原始图像不相似。像下面的代码:
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);
但是使用cairo_image_surface_create_from_png时颜色会一样(这个api只支持png格式)。看我的代码如下:
this->imageSource = cairo_image_surface_create_from_png(imagePath.c_str());
也可以在附加图片上查看清楚。
enter image description here
我很确定右图的红色和蓝色通道互换了。遗憾的是,我不知道 STBI_rgb_alpha
是什么,而且 Google 也没有找到任何看起来有用的文档,所以:
- Cairo 将每个像素存储为
uint32_t
,高字节为 alpha,低字节为蓝色,即 uint32_t pixel_value = alpha << 24 | red << 16 | green << 8 | blue;
.
- 这意味着内存中字节的实际顺序取决于系统字节序。
- 我猜想
STBI_rgb_alpha
意味着值是按字节保存的,与系统字节序无关。
- 因此,cairo 期望字节顺序为 b、g、r、a,而 stbi 使用 r、g、b、a。
- 如果现在将字节向右循环一个位置,最终将交换红色和蓝色。
我还发现评论中用户@Bob__ 的link 非常有帮助:
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
图像现在使用正确的通道绘制,但它花费更多时间重新排序像素数据通道。你们能否建议其他方法来节省这种情况下的处理时间。请在下面查看我的代码:
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);
当我阅读 stb_image 的库时,在函数 stbi_load 中没有参数调用 ORDER。谁能建议我其他解决方案?
我在 linux 系统中使用 Cairo 绘制图像时遇到问题。如果使用 cairo_image_surface_create 方法,输出图像颜色与原始图像不相似。像下面的代码:
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);
但是使用cairo_image_surface_create_from_png时颜色会一样(这个api只支持png格式)。看我的代码如下:
this->imageSource = cairo_image_surface_create_from_png(imagePath.c_str());
也可以在附加图片上查看清楚。
enter image description here
我很确定右图的红色和蓝色通道互换了。遗憾的是,我不知道 STBI_rgb_alpha
是什么,而且 Google 也没有找到任何看起来有用的文档,所以:
- Cairo 将每个像素存储为
uint32_t
,高字节为 alpha,低字节为蓝色,即uint32_t pixel_value = alpha << 24 | red << 16 | green << 8 | blue;
. - 这意味着内存中字节的实际顺序取决于系统字节序。
- 我猜想
STBI_rgb_alpha
意味着值是按字节保存的,与系统字节序无关。 - 因此,cairo 期望字节顺序为 b、g、r、a,而 stbi 使用 r、g、b、a。
- 如果现在将字节向右循环一个位置,最终将交换红色和蓝色。
我还发现评论中用户@Bob__ 的link 非常有帮助:
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
图像现在使用正确的通道绘制,但它花费更多时间重新排序像素数据通道。你们能否建议其他方法来节省这种情况下的处理时间。请在下面查看我的代码:
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);
当我阅读 stb_image 的库时,在函数 stbi_load 中没有参数调用 ORDER。谁能建议我其他解决方案?