24bpp 到 8bpp 转换 C 与原始图像数据
24bpp to 8bpp conversion C with raw image data
我目前正在尝试将原始二进制图像数据 (512 x 512 24bpp) 转换为 512 x 512 8bpp 图像,方法是对 R 通道使用 3 位,对 G 通道使用 3 位,对 B 通道使用 2 位。但是,当使用我的代码时,我的图片是灰度的吗?谁能告诉我我做错了什么?
/*24 bit per pixel - 8 bit per pixel transformation*/
unsigned char buf[512][512][3];
unsigned char in[512][512][3];
unsigned char out[512][512][3];
unsigned char pix[512][512];
int main(){
FILE *fp, *output;
int i, j;
/*open file*/
if((fp = fopen("LennaRGB512.data", "rb")) == NULL){
printf("error opening file\n");
}
/*read file into buffer*/
for (i = 0; i < 512; i++) {
for (j = 0; j < 512; j++) {
buf[i][j][0] = fgetc(fp); /*r*/
buf[i][j][1] = fgetc(fp); /*g*/
buf[i][j][2] = fgetc(fp); /*b*/
in[i][j][0] = buf[i][j][0];
in[i][j][1] = buf[i][j][1];
in[i][j][2] = buf[i][j][2];
}
}
fclose(fp);
output = fopen("lenna_8bpp.data", "wb");
for(i = 0; i < 512; i++){
char pix[512][512];
for(j = 0; j < 512; j++){
out[i][j][0] = (in[i][j][0] * 8) / 256;
out[i][j][1] = (in[i][j][1] * 8) / 256;
out[i][j][2] = (in[i][j][2] * 4) / 256;
pix[i][j] = (out[i][j][0] << 5) | (out[i][j][1] << 2) | out[i][j][2];
fputc(pix[i][j], output);
}
}
fclose(output);
return 0;
}
关于使用 .bmp 文件和其他文件执行此操作有很多问题,但我找不到任何关于逐像素处理原始图像数据的帮助。
我同意评论者的观点。我认为灰度很可能是您的观看者的产物,而不是您的转换。但是,您的转换也可以得到改善。尝试以下输出循环:
unsigned char pix; /* don't need 512*512 of them. */
unsigned char r, g, b;
for(row = 0; row < 512; row++){
for(col = 0; col < 512; col++){
r = in[row][col][0] >> 5; /* keep 3 bits */
g = in[row][col][1] >> 5;
b = in[row][col][2] >> 6; /* keep 2 bits */
pix = (r << 5) | (g << 2) | b;
fputc(pix, output);
}
}
您一次只处理一个像素,因此您只需要一个 pix
值。
对于每个 r
、g
和 b
颜色分量(请记住始终指定 unsigned char
),使用 >>
(对shift) 删除除最高有效位以外的所有位。这比 *8/256
序列更简单明了。另外,我相信 *8/256
之所以有效,是因为算术被提升为 int
— 如果在 char
秒内完成,*8
可能会导致溢出并丢失数据。
编辑 确实是显示器的问题。我已经在 my blog 上发布了一个调色板和说明,因为完整的内容对于 space 来说太长了。是的,我知道 link-only 答案不好 :( 。我只是将它保存到存档中以防 link 腐烂。
您确实需要以索引方式打开图像,然后指定图像的颜色图。
我目前正在尝试将原始二进制图像数据 (512 x 512 24bpp) 转换为 512 x 512 8bpp 图像,方法是对 R 通道使用 3 位,对 G 通道使用 3 位,对 B 通道使用 2 位。但是,当使用我的代码时,我的图片是灰度的吗?谁能告诉我我做错了什么?
/*24 bit per pixel - 8 bit per pixel transformation*/
unsigned char buf[512][512][3];
unsigned char in[512][512][3];
unsigned char out[512][512][3];
unsigned char pix[512][512];
int main(){
FILE *fp, *output;
int i, j;
/*open file*/
if((fp = fopen("LennaRGB512.data", "rb")) == NULL){
printf("error opening file\n");
}
/*read file into buffer*/
for (i = 0; i < 512; i++) {
for (j = 0; j < 512; j++) {
buf[i][j][0] = fgetc(fp); /*r*/
buf[i][j][1] = fgetc(fp); /*g*/
buf[i][j][2] = fgetc(fp); /*b*/
in[i][j][0] = buf[i][j][0];
in[i][j][1] = buf[i][j][1];
in[i][j][2] = buf[i][j][2];
}
}
fclose(fp);
output = fopen("lenna_8bpp.data", "wb");
for(i = 0; i < 512; i++){
char pix[512][512];
for(j = 0; j < 512; j++){
out[i][j][0] = (in[i][j][0] * 8) / 256;
out[i][j][1] = (in[i][j][1] * 8) / 256;
out[i][j][2] = (in[i][j][2] * 4) / 256;
pix[i][j] = (out[i][j][0] << 5) | (out[i][j][1] << 2) | out[i][j][2];
fputc(pix[i][j], output);
}
}
fclose(output);
return 0;
}
关于使用 .bmp 文件和其他文件执行此操作有很多问题,但我找不到任何关于逐像素处理原始图像数据的帮助。
我同意评论者的观点。我认为灰度很可能是您的观看者的产物,而不是您的转换。但是,您的转换也可以得到改善。尝试以下输出循环:
unsigned char pix; /* don't need 512*512 of them. */
unsigned char r, g, b;
for(row = 0; row < 512; row++){
for(col = 0; col < 512; col++){
r = in[row][col][0] >> 5; /* keep 3 bits */
g = in[row][col][1] >> 5;
b = in[row][col][2] >> 6; /* keep 2 bits */
pix = (r << 5) | (g << 2) | b;
fputc(pix, output);
}
}
您一次只处理一个像素,因此您只需要一个 pix
值。
对于每个 r
、g
和 b
颜色分量(请记住始终指定 unsigned char
),使用 >>
(对shift) 删除除最高有效位以外的所有位。这比 *8/256
序列更简单明了。另外,我相信 *8/256
之所以有效,是因为算术被提升为 int
— 如果在 char
秒内完成,*8
可能会导致溢出并丢失数据。
编辑 确实是显示器的问题。我已经在 my blog 上发布了一个调色板和说明,因为完整的内容对于 space 来说太长了。是的,我知道 link-only 答案不好 :( 。我只是将它保存到存档中以防 link 腐烂。
您确实需要以索引方式打开图像,然后指定图像的颜色图。