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

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

Minor reorg in the JPEG codec.

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