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

Last change on this file since 3081 was 3081, checked in by Jean-Yves Lamoureux, 12 years ago
  • Added hability to save jpeg using modular codec
File size: 4.8 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
22static int pipi_free_jpeg(pipi_image_t *img);
23
24
25static void format_msg(j_common_ptr cinfo, char *buf)
26{
27}
28static void emit_msg(j_common_ptr cinfo, int level)
29{
30}
31static void error_msg(j_common_ptr cinfo)
32{
33    cinfo->client_data = (void*)0x1;
34}
35static void output_msg(j_common_ptr cinfo)
36{
37}
38
39pipi_image_t *pipi_load_jpeg(const char *name)
40{
41    struct jpeg_decompress_struct cinfo;
42    struct jpeg_error_mgr jerr;
43    unsigned char *image = NULL, *scanline = NULL;
44    pipi_image_t *img = NULL;
45    unsigned int i, j, k = 0;
46
47    FILE *fp = fopen(name, "rb");
48    if(!fp) goto end;
49
50
51    cinfo.err = jpeg_std_error(&jerr);
52    jerr.error_exit = error_msg;
53    jerr.emit_message = emit_msg;
54    jerr.output_message = output_msg;
55    jerr.format_message = format_msg;
56
57    jpeg_create_decompress(&cinfo);
58    cinfo.client_data = 0x0;
59    jpeg_stdio_src(&cinfo, fp);
60    if((int)cinfo.client_data == 0x1) {
61        goto end;
62    }
63    jpeg_read_header(&cinfo, TRUE);
64    if((int)cinfo.client_data == 0x1) {
65        goto end;
66    }
67    jpeg_start_decompress(&cinfo);
68    if((int)cinfo.client_data == 0x1) {
69        goto end;
70    }
71
72    image = malloc(cinfo.output_width * cinfo.output_height * 4);
73    if(!image) goto end;
74
75    scanline = malloc(cinfo.output_width * 3);
76
77    /* Read scanlines, converting them to RGBA */
78    for(i=0; i < cinfo.output_height; i++)
79    {
80        jpeg_read_scanlines(&cinfo, &scanline, 1);
81        if((int)cinfo.client_data == 0x1) {
82            free(img);
83            img = NULL;
84            goto end;
85        }
86        for(j=0 ; j<cinfo.output_width*3; j+=3)
87        {
88            image[k+2] = scanline[j];
89            image[k+1] = scanline[j+1];
90            image[k]   = scanline[j+2];
91            image[k+3] = 255;
92            k+=4;
93        }
94    }
95
96    img = pipi_new(cinfo.output_width, cinfo.output_height);
97
98    img->p[PIPI_PIXELS_RGBA_C].pixels = image;
99    img->p[PIPI_PIXELS_RGBA_C].w = cinfo.output_width;
100    img->p[PIPI_PIXELS_RGBA_C].h = cinfo.output_height;
101    img->p[PIPI_PIXELS_RGBA_C].pitch = cinfo.output_width*4;
102    img->p[PIPI_PIXELS_RGBA_C].bpp = 24;
103    img->p[PIPI_PIXELS_RGBA_C].bytes = 4 * img->w * img->h;
104    img->last_modified = PIPI_PIXELS_RGBA_C;
105
106    img->codec_priv = (void *)&cinfo;
107    img->codec_format = PIPI_PIXELS_RGBA_C;
108    img->codec_free = pipi_free_jpeg;
109
110    img->wrap = 0;
111    img->u8 = 1;
112
113end:
114    if(fp) fclose(fp);
115    if(scanline) free(scanline);
116    jpeg_destroy_decompress(&cinfo);
117    return img;
118}
119
120int pipi_save_jpeg(pipi_image_t *img, const char *name)
121{
122    int quality = 75; /* FIXME */
123
124    struct jpeg_compress_struct cinfo;
125    struct jpeg_error_mgr jerr;
126    unsigned char *data = NULL;
127    unsigned char *line = NULL;
128
129    pipi_pixels_t *pixels = pipi_getpixels(img, PIPI_PIXELS_RGBA_C);
130
131    if (!pixels)
132        return 0;
133
134    data = pixels->pixels;
135
136
137    line = malloc(img->w * 3 * sizeof(unsigned char));
138    if (!line)
139        return 0;
140
141    FILE *fp = fopen(name, "wb");
142    if (!fp) {
143        free(line);
144        return 0;
145    }
146
147    jerr.error_exit = error_msg;
148    jerr.emit_message = emit_msg;
149    jerr.output_message = output_msg;
150
151    cinfo.err = jpeg_std_error(&(jerr));
152
153    jpeg_create_compress(&cinfo);
154    jpeg_stdio_dest(&cinfo, fp);
155    cinfo.image_width = img->w;
156    cinfo.image_height = img->h;
157    cinfo.input_components = 3;
158    cinfo.in_color_space = JCS_RGB;
159
160    jpeg_set_defaults(&cinfo);
161    jpeg_set_quality(&cinfo, quality, TRUE);
162    jpeg_start_compress(&cinfo, TRUE);
163
164    int j, i, y = 0;
165    uint32_t *ptr = (uint32_t*)data;
166    JSAMPROW           *jbuf;
167
168    while (cinfo.next_scanline < cinfo.image_height)
169    {
170        for (j = 0, i = 0; i < img->w; i++)
171        {
172            line[j++] = ((*ptr) >> 16) & 0xff;
173            line[j++] = ((*ptr) >> 8) & 0xff;
174            line[j++] = ((*ptr)) & 0xff;
175            ptr++;
176        }
177        /* write scanline */
178        jbuf = (JSAMPROW *) (&line);
179        jpeg_write_scanlines(&cinfo, jbuf, 1);
180        y++;
181    }
182
183    jpeg_finish_compress(&cinfo);
184    jpeg_destroy_compress(&cinfo);
185    free(line);
186    fclose(fp);
187
188    return 1;
189}
190
191static int pipi_free_jpeg(pipi_image_t *img)
192{
193    if(img->p[PIPI_PIXELS_RGBA_C].pixels)
194        free(img->p[PIPI_PIXELS_RGBA_C].pixels);
195    return 0;
196}
197
198
199
200
Note: See TracBrowser for help on using the repository browser.