source: libpipi/trunk/pipi/codec/modular/jpeg.c @ 3165

Last change on this file since 3165 was 3165, checked in by Jean-Yves Lamoureux, 12 years ago
  • Added setjmp/longjmp support to jpeg loader.
File size: 5.2 KB
Line 
1/*
2 *  libpipi       Pathetic image processing interface library
3 *  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
4 *                2008 Jean-Yves Lamoureux <jylam@lnxscene.org>
5 *                All Rights Reserved
6 *
7 *  $Id$
8 *
9 *  This library is free software. It comes without any warranty, to
10 *  the extent permitted by applicable law. You can redistribute it
11 *  and/or modify it under the terms of the Do What The Fuck You Want
12 *  To Public License, Version 2, as published by Sam Hocevar. See
13 *  http://sam.zoy.org/wtfpl/COPYING for more details.
14 */
15
16/*
17 * jpeg.c: libjpeg I/O functions
18 */
19
20#include "../modular.h"
21#include <setjmp.h>
22
23static int pipi_free_jpeg(pipi_image_t *img);
24
25
26
27
28struct my_error_mgr {
29    struct jpeg_error_mgr pub;
30    jmp_buf setjmp_buffer;
31};
32
33typedef struct my_error_mgr * my_error_ptr;
34
35static void format_msg(j_common_ptr cinfo, char *buf)
36{
37}
38static void emit_msg(j_common_ptr cinfo, int level)
39{
40}
41static void error_msg(j_common_ptr cinfo)
42{
43    my_error_ptr myerr = (my_error_ptr) cinfo->err;
44    cinfo->client_data = (void*)0x1;
45    longjmp(myerr->setjmp_buffer, 1);
46}
47static void output_msg(j_common_ptr cinfo)
48{
49}
50
51pipi_image_t *pipi_load_jpeg(const char *name)
52{
53    struct jpeg_decompress_struct cinfo;
54    struct my_error_mgr jerr;
55    unsigned char *image = NULL, *scanline = NULL;
56    pipi_image_t *img = NULL;
57    unsigned int i, j, k = 0;
58
59    FILE *fp = fopen(name, "rb");
60    if(!fp) goto end;
61
62
63    if (setjmp(jerr.setjmp_buffer)) {
64        goto end;
65    }
66    cinfo.err = jpeg_std_error(&jerr.pub);
67    jerr.pub.error_exit = error_msg;
68    jerr.pub.emit_message = emit_msg;
69    jerr.pub.output_message = output_msg;
70    jerr.pub.format_message = format_msg;
71
72    /* Initialize libjpeg */
73    jpeg_create_decompress(&cinfo);
74    cinfo.client_data = 0x0;
75    jpeg_stdio_src(&cinfo, fp);
76    if(cinfo.client_data == (void *)0x1) {
77        goto end;
78    }
79    jpeg_read_header(&cinfo, TRUE);
80    if(cinfo.client_data == (void *)0x1) {
81        goto end;
82    }
83    jpeg_start_decompress(&cinfo);
84    if(cinfo.client_data == (void *)0x1) {
85        goto end;
86    }
87
88    /* One scanline */
89    image = malloc(cinfo.output_width * cinfo.output_height * 4);
90    if(!image) goto end;
91
92    scanline = malloc(cinfo.output_width * 3);
93
94
95    for(i=0; i < cinfo.output_height; i++)
96    {
97        jpeg_read_scanlines(&cinfo, &scanline, 1);
98        if(cinfo.client_data == (void *)0x1) {
99            free(img);
100            img = NULL;
101            goto end;
102        }
103        for(j=0 ; j<cinfo.output_width*3; j+=3)
104        {
105            image[k+2] = scanline[j];
106            image[k+1] = scanline[j+1];
107            image[k]   = scanline[j+2];
108            image[k+3] = 255;
109            k+=4;
110        }
111    }
112
113    img = pipi_new(cinfo.output_width, cinfo.output_height);
114
115    img->p[PIPI_PIXELS_RGBA_C].pixels = image;
116    img->p[PIPI_PIXELS_RGBA_C].w = cinfo.output_width;
117    img->p[PIPI_PIXELS_RGBA_C].h = cinfo.output_height;
118    img->p[PIPI_PIXELS_RGBA_C].pitch = cinfo.output_width*4;
119    img->p[PIPI_PIXELS_RGBA_C].bpp = 24;
120    img->p[PIPI_PIXELS_RGBA_C].bytes = 4 * img->w * img->h;
121    img->last_modified = PIPI_PIXELS_RGBA_C;
122
123    img->codec_priv = (void *)&cinfo;
124    img->codec_format = PIPI_PIXELS_RGBA_C;
125    img->codec_free = pipi_free_jpeg;
126
127    img->wrap = 0;
128    img->u8 = 1;
129
130end:
131    if(fp) fclose(fp);
132    if(scanline) free(scanline);
133    jpeg_destroy_decompress(&cinfo);
134    return img;
135}
136
137int pipi_save_jpeg(pipi_image_t *img, const char *name)
138{
139    int quality = 75; /* FIXME */
140
141    struct jpeg_compress_struct cinfo;
142    struct my_error_mgr jerr;
143    unsigned char *data = NULL;
144    unsigned char *line = NULL;
145
146    pipi_pixels_t *pixels = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
147
148    if (!pixels)
149        return 0;
150
151    data = pixels->pixels;
152
153    line = malloc(img->w * 3 * sizeof(unsigned char));
154    if (!line)
155        return 0;
156
157    FILE *fp = fopen(name, "wb");
158    if (!fp) {
159        free(line);
160        return 0;
161    }
162   
163    if (setjmp(jerr.setjmp_buffer)) {
164        goto end;
165    }
166   
167    jerr.pub.error_exit = error_msg;
168    jerr.pub.emit_message = emit_msg;
169    jerr.pub.output_message = output_msg;
170
171    cinfo.err = jpeg_std_error(&(jerr.pub));
172
173    jpeg_create_compress(&cinfo);
174    jpeg_stdio_dest(&cinfo, fp);
175    cinfo.image_width = img->w;
176    cinfo.image_height = img->h;
177    cinfo.input_components = 3;
178    cinfo.in_color_space = JCS_RGB;
179
180    jpeg_set_defaults(&cinfo);
181    jpeg_set_quality(&cinfo, quality, TRUE);
182    jpeg_start_compress(&cinfo, TRUE);
183
184    int j, i, y = 0;
185    uint32_t *ptr = (uint32_t*)data;
186    JSAMPROW           *jbuf;
187
188    while (cinfo.next_scanline < cinfo.image_height)
189    {
190        for (j = 0, i = 0; i < img->w; i++)
191        {
192            line[j++] = ((*ptr) >> 16) & 0xff;
193            line[j++] = ((*ptr) >> 8) & 0xff;
194            line[j++] = ((*ptr)) & 0xff;
195            ptr++;
196        }
197        jbuf = (JSAMPROW *) (&line);
198        jpeg_write_scanlines(&cinfo, jbuf, 1);
199        y++;
200    }
201
202    jpeg_finish_compress(&cinfo);
203end:
204    jpeg_destroy_compress(&cinfo);
205    free(line);
206    fclose(fp);
207
208    return 1;
209}
210
211static int pipi_free_jpeg(pipi_image_t *img)
212{
213    if(img->p[PIPI_PIXELS_RGBA_C].pixels)
214        free(img->p[PIPI_PIXELS_RGBA_C].pixels);
215    return 0;
216}
217
218
219
220
Note: See TracBrowser for help on using the repository browser.