专注于高品质PHP技术等信息服务于一体 [STIEMAP] [RSS]

百度提供的广告:
Linux
当前位置:首页 > 技术文档 > Linux >  > 
SDL + libjpeg 实现 jpg 图片查看
 SDL + libjpeg 实现 jpg 图片查看, 开发环境 ubuntu 其它环境也是一样可以的,编译 gcc SDL_view_jpg.c -ljpeg -lSDL2 -g

SDL 是一种新型的多平台支持的,图形开发简单程序,很多软件都使用它开发。下面结合 libjpeg 读取文件 解码后,通过 SDL 绘制显示。
/**
 * author: qingruxu.com
 * date: 2020-03-12 18:27
 */
#include <stdio.h>
#include <SDL2/SDL.h>
#include <jpeglib.h>
#include <setjmp.h>
 
struct my_error_mgr {
    struct jpeg_error_mgr pub; /* "public" fields */
    jmp_buf setjmp_buffer;     /* for return to caller */
};
 
typedef struct my_error_mgr *my_error_ptr;
 
/*
 * Here's the routine that will replace the standard error_exit method:
 */
void my_error_exit(j_common_ptr cinfo)
{
    /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
    my_error_ptr myerr = (my_error_ptr) cinfo->err;
 
    /* Always display the message. */
    /* We could postpone this until after returning, if we chose. */
    (*cinfo->err->output_message) (cinfo);
 
    /* Return control to the setjmp point */
    longjmp(myerr->setjmp_buffer, 1);
}
 
int read_jpeg(char *filename, int *out_width, int *out_height, char **out_rgb_buff)
{
    struct jpeg_decompress_struct cinfo;
    struct my_error_mgr jerr;
    FILE *infile;  /* source file */
    char *buffer;  /* Output row buffer */
    char *p;
    int row_stride; /* physical row width in output buffer */
 
    if(NULL == (infile = fopen(filename, "rb")))
    {
        fprintf(stderr, "can't open %s\n", filename);
        return 0;
    }
 
    /* Step 1: allocate and initialize JPEG decompression object */
    /* We set up the normal JPEG error routines, then override error_exit. */
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    /* Establish the setjmp return context for my_error_exit to use. */
    if(setjmp(jerr.setjmp_buffer))
    {
        /* If we get here, the JPEG code has signaled an error.
         * We need to clean up the JPEG object, close the input file, and return.
         */
        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return 0;
    }
    /* Now we can initialize the JPEG decompression object. */
    jpeg_create_decompress(&cinfo);
 
    /* Step 2: specify data source (eg, a file) */
    jpeg_stdio_src(&cinfo, infile);
 
    /* Step 3: read file parameters with jpeg_read_header() */
    (void)jpeg_read_header(&cinfo, TRUE);
 
    /* Step 4: set parameters for decompression */
    /* In this example, we don't need to change any of the defaults set by
     * jpeg_read_header(), so we do nothing here.
     */
    /* Step 5: Start decompressor */
 
    (void) jpeg_start_decompress(&cinfo);
    /* We can ignore the return value since suspension is not possible
     * with the stdio data source.
     */
 
    /* We may need to do some setup of our own at this point before reading
     * the data.  After jpeg_start_decompress() we have the correct scaled
     * output image dimensions available, as well as the output colormap
     * if we asked for color quantization.
     * In this example, we need to make an output work buffer of the right size.
    */
    /* JSAMPLEs per row in output buffer */
    row_stride = cinfo.output_width * cinfo.output_components;
    /* Make a one-row-high sample array that will go away when done with image */
    buffer = (char *)malloc(row_stride * cinfo.output_height);
    memset(buffer, 0, row_stride * cinfo.output_height);
    *out_rgb_buff = buffer;
 
    printf("width:%d height:%d components:%d size:%ld", cinfo.output_width,
                cinfo.output_height, cinfo.output_components, sizeof(*buffer));
 
    *out_width  = cinfo.output_width;
    *out_height = cinfo.output_height;
    /* Step 6: while (scan lines remain to be read) */
    /*           jpeg_read_scanlines(...); */
 
    /* Here we use the library's state variable cinfo.output_scanline as the
     * loop counter, so that we don't have to keep track ourselves.
     */
    while(cinfo.output_scanline < cinfo.output_height)
    {
        /* jpeg_read_scanlines expects an array of pointers to scanlines.
         * Here the array is only one element long, but you could ask for
         * more than one scanline at a time if that's more convenient.
         */
        //printf("cinfo.output_scanline:%d\n", cinfo.output_scanline);
        p = buffer + cinfo.output_scanline * row_stride;
        (void) jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&p, 1);
    }
 
    /* Step 7: Finish decompression */
    (void) jpeg_finish_decompress(&cinfo);
    /* We can ignore the return value since suspension is not possible
     * with the stdio data source.
     */
 
    /* Step 8: Release JPEG decompression object */
 
    /* This is an important step since it will release a good deal of memory. */
    jpeg_destroy_decompress(&cinfo);
 
    /* After finish_decompress, we can close the input file.
     * Here we postpone it until after no more JPEG errors are possible,
     * so as to simplify the setjmp error logic above.  (Actually, I don't
     * think that jpeg_destroy can do an error exit, but why assume anything...)
     */
    fclose(infile);
 
    /* At this point you may want to check to see whether any corrupt-data
     * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
     */
 
    /* And we're done! */
    return 1;
}
 
int main(int argc, char **argv)
{
    SDL_Surface *screen;
    SDL_Window *window;
    SDL_Surface *image;
    SDL_Renderer *renderer;
 
    int image_width;
    int image_height;
    char *image_buffer = NULL;
    char *image_color;
 
    int i;
    int j;
 
    read_jpeg("xin.jpg", &image_width, &image_height, &image_buffer);
  
    SDL_Init(SDL_INIT_VIDEO);
    window = SDL_CreateWindow("SDL2 JPEG View", SDL_WINDOWPOS_UNDEFINED,
                        SDL_WINDOWPOS_UNDEFINED, image_width, image_height, 0);
    renderer = SDL_CreateRenderer(window, -1, 0);
    
    //draw image RGB
    image_color = image_buffer;
    for(i = 0; i < image_height; i++)
    {
        for(j = 0; j < image_width; j++)
        {
            SDL_SetRenderDrawColor(renderer, *image_color, image_color[1], image_color[2], 0);
            SDL_RenderDrawPoint(renderer, j, i);
            image_color += 3;
        }
    }
    free(image_buffer);
    SDL_RenderPresent(renderer);
 
    SDL_Event event;
    while(1)
    {
        SDL_WaitEvent(&event);
        if(SDL_QUIT == event.type) break;
    }
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}