source: libpipi/trunk/pipi/codec/jpeg.c @ 3343

Last change on this file since 3343 was 3343, checked in by Sam Hocevar, 11 years ago

Got rid of the modular codec stuff. All codecs should work the same way.

File size: 5.8 KB
RevLine 
[3075]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
[3343]20#include "config.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
[3165]26#include <setjmp.h>
[3075]27
[3343]28#include <jpeglib.h>
[3075]29
[3343]30#include "pipi.h"
31#include "pipi_internals.h"
[3075]32
[3343]33static int pipi_free_jpeg(pipi_image_t *img);
[3165]34
35struct my_error_mgr {
36    struct jpeg_error_mgr pub;
37    jmp_buf setjmp_buffer;
38};
39
40typedef struct my_error_mgr * my_error_ptr;
41
[3075]42static void format_msg(j_common_ptr cinfo, char *buf)
43{
44}
45static void emit_msg(j_common_ptr cinfo, int level)
46{
47}
48static void error_msg(j_common_ptr cinfo)
49{
[3165]50    my_error_ptr myerr = (my_error_ptr) cinfo->err;
[3075]51    cinfo->client_data = (void*)0x1;
[3165]52    longjmp(myerr->setjmp_buffer, 1);
[3075]53}
54static void output_msg(j_common_ptr cinfo)
55{
56}
57
58pipi_image_t *pipi_load_jpeg(const char *name)
59{
60    struct jpeg_decompress_struct cinfo;
[3165]61    struct my_error_mgr jerr;
[3075]62    unsigned char *image = NULL, *scanline = NULL;
63    pipi_image_t *img = NULL;
64    unsigned int i, j, k = 0;
[3343]65    FILE *fp;
[3075]66
[3343]67    fp = fopen(name, "rb");
[3075]68    if(!fp) goto end;
69
70
[3165]71    if (setjmp(jerr.setjmp_buffer)) {
72        goto end;
73    }
74    cinfo.err = jpeg_std_error(&jerr.pub);
75    jerr.pub.error_exit = error_msg;
76    jerr.pub.emit_message = emit_msg;
77    jerr.pub.output_message = output_msg;
78    jerr.pub.format_message = format_msg;
79
[3083]80    /* Initialize libjpeg */
[3075]81    jpeg_create_decompress(&cinfo);
82    cinfo.client_data = 0x0;
83    jpeg_stdio_src(&cinfo, fp);
[3088]84    if(cinfo.client_data == (void *)0x1) {
[3075]85        goto end;
86    }
87    jpeg_read_header(&cinfo, TRUE);
[3088]88    if(cinfo.client_data == (void *)0x1) {
[3075]89        goto end;
90    }
91    jpeg_start_decompress(&cinfo);
[3088]92    if(cinfo.client_data == (void *)0x1) {
[3075]93        goto end;
94    }
95
[3083]96    /* One scanline */
[3075]97    image = malloc(cinfo.output_width * cinfo.output_height * 4);
98    if(!image) goto end;
99
100    scanline = malloc(cinfo.output_width * 3);
101
[3083]102
[3075]103    for(i=0; i < cinfo.output_height; i++)
104    {
105        jpeg_read_scanlines(&cinfo, &scanline, 1);
[3088]106        if(cinfo.client_data == (void *)0x1) {
[3075]107            free(img);
108            img = NULL;
109            goto end;
110        }
111        for(j=0 ; j<cinfo.output_width*3; j+=3)
112        {
113            image[k+2] = scanline[j];
114            image[k+1] = scanline[j+1];
115            image[k]   = scanline[j+2];
116            image[k+3] = 255;
117            k+=4;
118        }
119    }
120
121    img = pipi_new(cinfo.output_width, cinfo.output_height);
122
[3342]123    img->p[PIPI_PIXELS_RGBA_U8].pixels = image;
124    img->p[PIPI_PIXELS_RGBA_U8].w = cinfo.output_width;
125    img->p[PIPI_PIXELS_RGBA_U8].h = cinfo.output_height;
126    img->p[PIPI_PIXELS_RGBA_U8].pitch = cinfo.output_width*4;
127    img->p[PIPI_PIXELS_RGBA_U8].bpp = 24;
128    img->p[PIPI_PIXELS_RGBA_U8].bytes = 4 * img->w * img->h;
129    img->last_modified = PIPI_PIXELS_RGBA_U8;
[3075]130
131    img->codec_priv = (void *)&cinfo;
[3342]132    img->codec_format = PIPI_PIXELS_RGBA_U8;
[3075]133    img->codec_free = pipi_free_jpeg;
134
135    img->wrap = 0;
136    img->u8 = 1;
137
138end:
139    if(fp) fclose(fp);
140    if(scanline) free(scanline);
141    jpeg_destroy_decompress(&cinfo);
142    return img;
143}
144
145int pipi_save_jpeg(pipi_image_t *img, const char *name)
146{
[3081]147    int quality = 75; /* FIXME */
148
149    struct jpeg_compress_struct cinfo;
[3165]150    struct my_error_mgr jerr;
[3081]151    unsigned char *data = NULL;
152    unsigned char *line = NULL;
[3343]153    size_t len;
[3081]154
[3343]155    len = strlen(name);
156    if(len < 4 || name[len - 4] != '.'
157        || toupper(name[len - 3]) != 'J'
158        || toupper(name[len - 2]) != 'P'
159        || toupper(name[len - 1]) != 'G')
160    {
161        if(len < 5 || name[len - 5] != '.'
162            || toupper(name[len - 4]) != 'J'
163            || toupper(name[len - 3]) != 'P'
164            || toupper(name[len - 2]) != 'E'
165            || toupper(name[len - 1]) != 'G')
166            return -1;
167    }
168
[3342]169    pipi_pixels_t *pixels = pipi_get_pixels(img, PIPI_PIXELS_RGBA_U8);
[3081]170
171    if (!pixels)
172        return 0;
173
174    data = pixels->pixels;
175
176    line = malloc(img->w * 3 * sizeof(unsigned char));
177    if (!line)
178        return 0;
179
180    FILE *fp = fopen(name, "wb");
181    if (!fp) {
182        free(line);
183        return 0;
184    }
[3165]185   
186    if (setjmp(jerr.setjmp_buffer)) {
187        goto end;
188    }
189   
190    jerr.pub.error_exit = error_msg;
191    jerr.pub.emit_message = emit_msg;
192    jerr.pub.output_message = output_msg;
[3081]193
[3165]194    cinfo.err = jpeg_std_error(&(jerr.pub));
[3081]195
196    jpeg_create_compress(&cinfo);
197    jpeg_stdio_dest(&cinfo, fp);
198    cinfo.image_width = img->w;
199    cinfo.image_height = img->h;
200    cinfo.input_components = 3;
201    cinfo.in_color_space = JCS_RGB;
202
203    jpeg_set_defaults(&cinfo);
204    jpeg_set_quality(&cinfo, quality, TRUE);
205    jpeg_start_compress(&cinfo, TRUE);
206
207    int j, i, y = 0;
208    uint32_t *ptr = (uint32_t*)data;
209    JSAMPROW           *jbuf;
210
211    while (cinfo.next_scanline < cinfo.image_height)
212    {
213        for (j = 0, i = 0; i < img->w; i++)
214        {
215            line[j++] = ((*ptr) >> 16) & 0xff;
216            line[j++] = ((*ptr) >> 8) & 0xff;
217            line[j++] = ((*ptr)) & 0xff;
218            ptr++;
219        }
220        jbuf = (JSAMPROW *) (&line);
221        jpeg_write_scanlines(&cinfo, jbuf, 1);
222        y++;
223    }
224
225    jpeg_finish_compress(&cinfo);
[3165]226end:
[3081]227    jpeg_destroy_compress(&cinfo);
228    free(line);
229    fclose(fp);
230
[3341]231    pipi_release_pixels(img, pixels);
232
[3081]233    return 1;
[3075]234}
235
236static int pipi_free_jpeg(pipi_image_t *img)
237{
[3342]238    if(img->p[PIPI_PIXELS_RGBA_U8].pixels)
239        free(img->p[PIPI_PIXELS_RGBA_U8].pixels);
[3075]240    return 0;
241}
242
243
244
245
Note: See TracBrowser for help on using the repository browser.