Error hit when show a cropped JPEG on LCD (ARGB) display

65 views Asked by At

I am trying to crop a big JPEG photo and show it into LCD display in my Linux.

I am using libjpeg to decode the photo, and convert the RGB to ARGB to show the cropped part onto the LCD.

But the cropped part is NOT correct in color when it is shown in LCD, with following codes to do the decoding, cropping, ARGB converting and showing it in framebuffer.

    unsigned char* output_buffer = (unsigned char*)malloc(sizeof(unsigned char) * varinfo.xres * varinfo.yres * 4);

    int row_stride = cinfo.output_width * cinfo.output_components;

    unsigned long rgb_size;
    unsigned char *rgb_data;
    rgb_size = row_stride * cinfo.output_height;
    rgb_data = (unsigned char *)calloc(1, rgb_size);

    jpeg_skip_scanlines(&cinfo, y_offset);

    int last_line = cinfo.output_scanline + varinfo.yres;
    last_line = (last_line > cinfo.output_height) ? cinfo.output_height : last_line;

    unsigned char* output_ptr = output_buffer;
    int count = 0;
    while (cinfo.output_scanline < last_line) {
        unsigned char *buffer_array[1];
        buffer_array[0] = rgb_data + (count++) * row_stride;
        jpeg_read_scanlines(&cinfo, buffer_array, 1);
    }

    for (int y = 0; y < varinfo.yres; y++) {
        unsigned char* row_ptr = rgb_data + y * row_stride + (3 * x_offset);
        for (int x = 0; x < varinfo.xres; x++) {
            *output_ptr++ = *row_ptr++;  // Red
            *output_ptr++ = *row_ptr++;  // Green
            *output_ptr++ = *row_ptr++;  // Blue
            *output_ptr++ = 0xFF;  // Alpha
        }
    }

    memcpy(fb_mem, output_buffer, (sizeof(uint32_t) * varinfo.xres * varinfo.yres));


    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    free(output_buffer);
    free(rgb_data);

The code can crop the photo, but when the cropped part is shown in LCD (framebuffer) the color is NOT correct.

And the executive also reports following error when it calls jpeg_finish_decompress(&cinfo);

Application transferred too few scanlines

I don't know what is wrong with above codes.

2

There are 2 answers

0
wangt13 On BEST ANSWER

The problem of color comes from the codes.

for (int y = 0; y < varinfo.yres; y++) {
        unsigned char* row_ptr = rgb_data + y * row_stride + (3 * x_offset);
        for (int x = 0; x < varinfo.xres; x++) {
            *output_ptr++ = *row_ptr++;  // Red
            *output_ptr++ = *row_ptr++;  // Green
            *output_ptr++ = *row_ptr++;  // Blue
            *output_ptr++ = 0xFF;  // Alpha
        }
    }

To show picture in ARGB, the 32bit ARGB data should be 0xAARRGGBB, but above codes generate the pixel as 0xAABBGGRR. So the right one should be as follows,

    for (int y = 0; y < varinfo.yres; y++) {
        unsigned char* row_ptr = rgb_data + y * row_stride + (cinfo.output_components * x_offset);
        for (int x = 0; x < varinfo.xres; x++) {
            int r = *row_ptr++;
            int g = *row_ptr++;
            int b = *row_ptr++;
            *output_ptr++ = b;
            *output_ptr++ = g;
            *output_ptr++ = r;
            *output_ptr++ = 0xFF;  // Alpha
        }
    }
1
Bpwnz On

I had a similar problem and it was called when I did not read the whole transferred image, but only part of it. Therefore, the output_scanline field did not take the height of the image, and the jpeg_finish_decompress function caused this error. To decide, it is best to read the entire image, and only then, somewhere on the side, crop it to the desired size. If this option does not suit you, then you can assign the value of the image height to the output_scanline field, but this is a bad option.