Search code examples
linuxjpegframebufferlibjpeg

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


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.


Solution

  • 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
            }
        }