/* * libpipi Pathetic image processing interface library * Copyright (c) 2004-2008 Sam Hocevar * 2008 Jean-Yves Lamoureux * 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 "../modular.h" static int pipi_free_jpeg(pipi_image_t *img); 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) { cinfo->client_data = (void*)0x1; } static void output_msg(j_common_ptr cinfo) { } pipi_image_t *pipi_load_jpeg(const char *name) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; unsigned char *image = NULL, *scanline = NULL; pipi_image_t *img = NULL; unsigned int i, j, k = 0; FILE *fp = fopen(name, "rb"); if(!fp) goto end; /* Set callbacks */ cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = error_msg; jerr.emit_message = emit_msg; jerr.output_message = output_msg; jerr.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 ; jp[PIPI_PIXELS_RGBA_C].pixels = image; img->p[PIPI_PIXELS_RGBA_C].w = cinfo.output_width; img->p[PIPI_PIXELS_RGBA_C].h = cinfo.output_height; img->p[PIPI_PIXELS_RGBA_C].pitch = cinfo.output_width*4; img->p[PIPI_PIXELS_RGBA_C].bpp = 24; img->p[PIPI_PIXELS_RGBA_C].bytes = 4 * img->w * img->h; img->last_modified = PIPI_PIXELS_RGBA_C; img->codec_priv = (void *)&cinfo; img->codec_format = PIPI_PIXELS_RGBA_C; 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) { int quality = 75; /* FIXME */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; unsigned char *data = NULL; unsigned char *line = NULL; pipi_pixels_t *pixels = pipi_getpixels(img, PIPI_PIXELS_RGBA_C); if (!pixels) return 0; data = pixels->pixels; line = malloc(img->w * 3 * sizeof(unsigned char)); if (!line) return 0; FILE *fp = fopen(name, "wb"); if (!fp) { free(line); return 0; } jerr.error_exit = error_msg; jerr.emit_message = emit_msg; jerr.output_message = output_msg; cinfo.err = jpeg_std_error(&(jerr)); 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); int j, i, y = 0; uint32_t *ptr = (uint32_t*)data; JSAMPROW *jbuf; 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); jpeg_destroy_compress(&cinfo); free(line); fclose(fp); return 1; } static int pipi_free_jpeg(pipi_image_t *img) { if(img->p[PIPI_PIXELS_RGBA_C].pixels) free(img->p[PIPI_PIXELS_RGBA_C].pixels); return 0; }