/* * jpeg.c -- enfle JPEG saver * (C)Copyright 1998, 99 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Sun Sep 19 02:00:11 1999. * $Id: jpeg.c,v 1.2 1999/09/18 18:29:59 sian Exp $ * * NOTE: This code needs libjpeg version 6 or later. * * This software is based in part on the work of the Independent JPEG Group * * Enfle is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Enfle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "enfle.h" #include "jpeg.h" #include "plugin.h" #include #include #include #include #include #define JPEG_SAVE_QUALITY 100 #if BITS_IN_JSAMPLE != 8 # error BITS_IN_JSAMPLE must be 8 #endif struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr *my_error_ptr; #ifdef PIC int get_plugininfo(PluginInfo *p) #else int saver_jpeg_get_plugininfo(PluginInfo *p) #endif { p->version = 1; p->type = _Saver; p->pluginname = "JPEG Format Saver Plugin version 0.1.1"; p->pluginshortname = FORMAT_NAME; p->author = "Hiroshi Takekawa"; p->dlhandle = NULL; /* set by plugin_load */ p->functions.saver.save_image = jpeg_save_image; return 1; } /* my error handler */ METHODDEF(void) my_error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ my_error_ptr myerr = (my_error_ptr)cinfo->err; if (cinfo->err->msg_code != JERR_NO_SOI) (*cinfo->err->output_message)(cinfo); /* Return control to the setjmp point */ longjmp(myerr->setjmp_buffer, 1); } /* write JPEG file */ GLOBAL(int) jpeg_save_image(Info *info, Image *p, char *outfile) { FILE *fp = NULL; struct jpeg_compress_struct *cinfo = malloc(sizeof(struct jpeg_compress_struct)); struct my_error_mgr jerr; JSAMPROW buffer[1]; /* output row buffer */ if (cinfo == NULL) return 0; switch (p->type) { case _INDEX: case _RGB16: if (!image_expand(p, _RGB24)) return 0; break; case _MONO: fprintf(stderr, "binary image save support not yet implemented\n"); return 0; case _GRAY: case _RGB24: break; default: fprintf(stderr, "Unknown image type: %d (maybe bug)\n", p->type); return 0; } if ((fp = fopen(outfile, "wb")) == NULL) return 0; cinfo->err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(cinfo); free(cinfo); return 0; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_compress(cinfo); jpeg_stdio_dest(cinfo, fp); cinfo->image_width = p->width; cinfo->image_height = p->height; if (p->type == _GRAY) { cinfo->input_components = 1; cinfo->in_color_space = JCS_GRAYSCALE; } else { cinfo->input_components = 3; cinfo->in_color_space = JCS_RGB; } jpeg_set_defaults(cinfo); jpeg_set_quality(cinfo, JPEG_SAVE_QUALITY, TRUE); jpeg_start_compress(cinfo, TRUE); while (cinfo->next_scanline < cinfo->image_height) { buffer[0] = (JSAMPROW)(p->image + p->bytes_per_line * cinfo->next_scanline); (void)jpeg_write_scanlines(cinfo, buffer, 1); } (void)jpeg_finish_compress(cinfo); fclose(fp); jpeg_destroy_compress(cinfo); free(cinfo); return 1; }