提问人:Luidéo 提问时间:3/3/2023 更新时间:3/3/2023 访问量:70
JPEG 图像在我的 C 照片查看器中无法正确显示(使用 X11 和 jpeglib)
JPEG image doesn't display properly in my C photo viewer (using X11 and jpeglib)
问:
我正在为 Linux 制作一个简约且轻量级的 C 图片查看器。我使用库 X11 创建窗口,使用 jpeglib 读取 JPEG 文件。
我面临两个问题:
我的程序没有完全显示图像,它只显示它的左下角。此外,它还显示该图像的多个部分,上面没有颜色。
当图像的宽度大于其高度时,程序的显示方式与我描述的相同,但在左侧旋转 90°。
示例(对不起,质量低下,有些图像太大了,完全从我的程序中显示):
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(int argc, char** argv){
// Ouverture du fichier JPEG - Opens the JPEG file
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
if (argc != 2){
fprintf(stderr, "[ERREUR] Mauvais arguments entres, exemple : %s <fichier image>\n", argv[0]);
return -1;
}
FILE* imgFile = fopen(argv[1], "rb");
if(imgFile == NULL){
fprintf(stderr, "[ERREUR] Impossible d'ouvrir le fichier \"%s\".\n", argv[1]);
return -1;
}
printf("Ouverture du fichier \"%s\" reussie.\n", argv[1]);
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, imgFile);
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
printf("Largeur : %d\n", cinfo.output_width);
printf("Hauteur : %d\n", cinfo.output_height);
printf("Nombre de composantes : %d\n", cinfo.output_components);
printf("Lecture de l'image en cours...\n");
// Création de la fenêtre - Creates the window
Display *display = XOpenDisplay(NULL);
XEvent event;
int screen = DefaultScreen(display);
Window root = RootWindow(display, screen);
if (display == NULL){
fprintf(stderr, "[ERREUR] Impossible de créer la fenêtre.\n");
return -1;
}
Window window = XCreateSimpleWindow(display, root, 0, 0, cinfo.output_width, cinfo.output_height, 0, 0, 0);
printf("Creation de la fenetre reussie.\n");
XMapWindow(display, window);
// Boucle parcours de l'image - Image browsing loop
unsigned char *image32 = (unsigned char *)malloc(cinfo.output_width*cinfo.output_height*4);
unsigned char *p = image32;
// Pour chaque ligne - for each line
while (cinfo.output_scanline < cinfo.output_height){
JSAMPROW buffer[1];
int row_stride = cinfo.output_width * cinfo.output_components;
buffer[0] = &image32[cinfo.output_scanline * row_stride];
jpeg_read_scanlines(&cinfo, buffer, 1);
// Pour chaque pixel de la ligne - for each pixel of the line
for(unsigned int i=0; i<cinfo.output_width; i++){
*p++ = buffer[0][i * cinfo.output_components + 2]; // B
*p++ = buffer[0][i * cinfo.output_components + 1]; // G
*p++ = buffer[0][i * cinfo.output_components]; // R
*p++ = 0;
}
}
printf("Lecture de l'image terminee.\n");
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(imgFile);
printf("Fermeture du fichier reussie.\n");
XImage* ximage = XCreateImage(display, DefaultVisual(display, 0), DefaultDepth(display, DefaultScreen(display)), ZPixmap, 0, (char*)image32, cinfo.output_width, cinfo.output_height, 32, 0);
printf("Creation de l'image reussie.\n");
// Affichage de l'image - Shows the image
XPutImage(display, window, DefaultGC(display, 0), ximage, 0, 0, 0, 0, cinfo.output_height, cinfo.output_width);
XFlush(display);
printf("Affichage de l'image reussie.\n");
while(XNextEvent(display, &event) == 0){
}
XDestroyImage(ximage);
XUnmapWindow(display, window);
XDestroyWindow(display, window);
XCloseDisplay(display);
printf("Fermeture de la fenetre reussie.\n");
return 0;
}
这是我第一次使用这些库,所以我有点迷茫,尽管问题在于通道的数量,因为我尝试的所有图像都没有 alpha 通道,但删除像素循环中的线条对我没有帮助。我还认为图像的深度可能会导致这些问题,但我不知道我是否必须声明深度以及在哪里声明。*p++ = 0;
我应该怎么做才能解决这些问题?
感谢您的帮助。
答:
1赞
Mathieu
3/3/2023
#1
您的问题来自jpeg图像读取。
将解码后的行存储在图像缓冲区中,然后尝试写入
图像 () 从哪一点也开始*p++==
buffer[0]
image32
若要正确读取,应创建一个缓冲区来存储正在读取的行。
更正后的读数为:
// memory to store line
unsigned char *linebuffer = malloc(cinfo.output_width * cinfo.output_components);
while (cinfo.output_scanline < cinfo.output_height){
JSAMPROW buffer[1];
buffer[0] = linebuffer;
jpeg_read_scanlines(&cinfo, buffer, 1);
// Pour chaque pixel de la ligne - for each pixel of the line
for(unsigned int i=0; i<cinfo.output_width; i++){
*p++ = linebuffer[i * cinfo.output_components + 2]; // B
*p++ = linebuffer[i * cinfo.output_components + 1]; // G
*p++ = linebuffer[i * cinfo.output_components]; // R
*p++ = 0;
}
}
free(linebuffer);
而且,你混合了宽度和高度XPutImage
// corrected call
XPutImage(display, window, DefaultGC(display, 0), ximage, 0, 0, 0, 0, cinfo.output_width, cinfo.output_height);
评论
0赞
Luidéo
3/3/2023
这很完美,你的解释非常清楚。谢谢Mathieu!
评论