|
- /*
- * libpipi Pathetic image processing interface library
- * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
- * 2008 Jean-Yves Lamoureux <jylam@lnxscene.org>
- * All Rights Reserved
- *
- * $Id$
- *
- * This library is free software. It comes without any warranty, to
- * the extent permitted by applicable law. You can redistribute it
- * and/or modify it under the terms of the Do What The Fuck You Want
- * To Public License, Version 2, as published by Sam Hocevar. See
- * http://sam.zoy.org/wtfpl/COPYING for more details.
- */
-
- /*
- * jpeg.c: libjpeg I/O functions
- */
-
- #include "config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <setjmp.h>
-
- #include <jpeglib.h>
-
- #include "pipi.h"
- #include "pipi_internals.h"
-
- static int pipi_free_jpeg(pipi_image_t *img);
-
- struct my_error_mgr
- {
- struct jpeg_error_mgr pub;
- jmp_buf setjmp_buffer;
- };
-
- typedef struct my_error_mgr * my_error_ptr;
-
- static void format_msg(j_common_ptr cinfo, char *buf)
- {
- }
-
- static void emit_msg(j_common_ptr cinfo, int level)
- {
- }
-
- static void error_msg(j_common_ptr cinfo)
- {
- my_error_ptr myerr = (my_error_ptr) cinfo->err;
- cinfo->client_data = (void*)0x1;
- longjmp(myerr->setjmp_buffer, 1);
- }
-
- static void output_msg(j_common_ptr cinfo)
- {
- }
-
- pipi_image_t *pipi_load_jpeg(const char *name)
- {
- struct jpeg_decompress_struct cinfo;
- struct my_error_mgr jerr;
- unsigned char *image = NULL, *scanline = NULL;
- pipi_image_t *img = NULL;
- unsigned int i, j, k = 0;
- FILE *fp;
-
- fp = fopen(name, "rb");
- if(!fp)
- return NULL;
-
- if(setjmp(jerr.setjmp_buffer))
- goto end;
-
- cinfo.err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = error_msg;
- jerr.pub.emit_message = emit_msg;
- jerr.pub.output_message = output_msg;
- jerr.pub.format_message = format_msg;
-
- /* Initialize libjpeg */
- jpeg_create_decompress(&cinfo);
- cinfo.client_data = 0x0;
- jpeg_stdio_src(&cinfo, fp);
- if(cinfo.client_data == (void *)0x1)
- goto end;
- jpeg_read_header(&cinfo, TRUE);
- if(cinfo.client_data == (void *)0x1)
- goto end;
- jpeg_start_decompress(&cinfo);
- if(cinfo.client_data == (void *)0x1)
- goto end;
-
- /* One scanline */
- image = malloc(cinfo.output_width * cinfo.output_height * 4);
- if(!image)
- goto end;
-
- scanline = malloc(cinfo.output_width * 3);
-
- for(i = 0; i < cinfo.output_height; i++)
- {
- jpeg_read_scanlines(&cinfo, &scanline, 1);
- if(cinfo.client_data == (void *)0x1)
- {
- free(img);
- img = NULL;
- goto end;
- }
- for(j = 0; j < cinfo.output_width * 3; j += 3)
- {
- image[k + 2] = scanline[j];
- image[k + 1] = scanline[j + 1];
- image[k] = scanline[j + 2];
- image[k + 3] = 255;
- k += 4;
- }
- }
-
- img = pipi_new(cinfo.output_width, cinfo.output_height);
-
- img->p[PIPI_PIXELS_RGBA_U8].pixels = image;
- img->p[PIPI_PIXELS_RGBA_U8].w = cinfo.output_width;
- img->p[PIPI_PIXELS_RGBA_U8].h = cinfo.output_height;
- img->p[PIPI_PIXELS_RGBA_U8].pitch = cinfo.output_width * 4;
- img->p[PIPI_PIXELS_RGBA_U8].bpp = 24;
- img->p[PIPI_PIXELS_RGBA_U8].bytes = 4 * img->w * img->h;
- img->last_modified = PIPI_PIXELS_RGBA_U8;
-
- img->codec_priv = (void *)&cinfo;
- img->codec_format = PIPI_PIXELS_RGBA_U8;
- img->codec_free = pipi_free_jpeg;
-
- img->wrap = 0;
- img->u8 = 1;
-
- end:
- if(fp)
- fclose(fp);
- if(scanline)
- free(scanline);
- jpeg_destroy_decompress(&cinfo);
- return img;
- }
-
- int pipi_save_jpeg(pipi_image_t *img, const char *name)
- {
- struct jpeg_compress_struct cinfo;
- struct my_error_mgr jerr;
- unsigned char *data;
- unsigned char *line;
- pipi_pixels_t *pixels;
- JSAMPROW *jbuf;
- uint32_t *ptr;
- FILE *fp;
- int i, j, y = 0;
- size_t len;
-
- int quality = 75; /* FIXME */
-
- len = strlen(name);
- if(len < 4 || name[len - 4] != '.'
- || toupper(name[len - 3]) != 'J'
- || toupper(name[len - 2]) != 'P'
- || toupper(name[len - 1]) != 'G')
- {
- if(len < 5 || name[len - 5] != '.'
- || toupper(name[len - 4]) != 'J'
- || toupper(name[len - 3]) != 'P'
- || toupper(name[len - 2]) != 'E'
- || toupper(name[len - 1]) != 'G')
- return -1;
- }
-
- pixels = pipi_get_pixels(img, PIPI_PIXELS_RGBA_U8);
- if(!pixels)
- return -1;
-
- data = pixels->pixels;
-
- line = malloc(img->w * 3 * sizeof(unsigned char));
- if(!line)
- return -1;
-
- fp = fopen(name, "wb");
- if(!fp)
- {
- free(line);
- return -1;
- }
-
- if(setjmp(jerr.setjmp_buffer))
- goto end;
-
- jerr.pub.error_exit = error_msg;
- jerr.pub.emit_message = emit_msg;
- jerr.pub.output_message = output_msg;
-
- cinfo.err = jpeg_std_error(&(jerr.pub));
-
- jpeg_create_compress(&cinfo);
- jpeg_stdio_dest(&cinfo, fp);
- cinfo.image_width = img->w;
- cinfo.image_height = img->h;
- cinfo.input_components = 3;
- cinfo.in_color_space = JCS_RGB;
-
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, quality, TRUE);
- jpeg_start_compress(&cinfo, TRUE);
-
- ptr = (uint32_t*)data;
-
- while(cinfo.next_scanline < cinfo.image_height)
- {
- for (j = 0, i = 0; i < img->w; i++)
- {
- line[j++] = ((*ptr) >> 16) & 0xff;
- line[j++] = ((*ptr) >> 8) & 0xff;
- line[j++] = ((*ptr)) & 0xff;
- ptr++;
- }
- jbuf = (JSAMPROW *) (&line);
- jpeg_write_scanlines(&cinfo, jbuf, 1);
- y++;
- }
-
- jpeg_finish_compress(&cinfo);
-
- end:
- jpeg_destroy_compress(&cinfo);
- free(line);
- fclose(fp);
-
- pipi_release_pixels(img, pixels);
-
- return 0;
- }
-
- static int pipi_free_jpeg(pipi_image_t *img)
- {
- if(img->p[PIPI_PIXELS_RGBA_U8].pixels)
- free(img->p[PIPI_PIXELS_RGBA_U8].pixels);
- return 0;
- }
|