SDL + libjpeg 实现 jpg 图片查看
SDL + libjpeg 实现 jpg 图片查看, 开发环境 ubuntu 其它环境也是一样可以的,编译 gcc SDL_view_jpg.c -ljpeg -lSDL2 -gSDL 是一种新型的多平台支持的,图形开发简单程序,很多软件都使用它开发。下面结合 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;
}
- 上一篇:使用 gpg 验证 php
- 下一篇:没有了