/* * jpeg.c -- enfle JPEG handler * (C)Copyright 1998, 99 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Mon Sep 20 20:06:47 1999. * $Id: jpeg.c,v 1.9 1999/09/20 12:55: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 #include "jpegsrc.h" #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; int #ifdef PIC get_plugininfo(PluginInfo *p) #else loader_jpeg_get_plugininfo(PluginInfo *p) #endif { p->version = 1; p->type = _Loader; p->pluginname = "JPEG Format Loader Plugin version 0.1.1"; p->pluginshortname = FORMAT_NAME; p->author = "Hiroshi Takekawa"; p->dlhandle = NULL; /* set by plugin_load */ p->functions.loader.load_image = jpeg_load_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); } /* read JPEG file */ LOCAL(int) jpeg_decode_image(Info *info, Image *p) { struct jpeg_decompress_struct *cinfo = malloc(sizeof(struct jpeg_decompress_struct)); struct my_error_mgr jerr; JSAMPROW buffer[1]; /* output row buffer */ int i, j, width, height; if (cinfo == NULL) return 0; #ifdef DEBUG fprintf(stderr, "jpeg_decode_image() called\n"); #endif 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_decompress(cinfo); free(cinfo); return 0; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(cinfo); jpeg_archive_src(cinfo, info->ar); (void)jpeg_read_header(cinfo, TRUE); jpeg_calc_output_dimensions(cinfo); p->width = width = cinfo->output_width; p->height = height = cinfo->output_height; info->format = FORMAT_NAME; if (info->if_quantize) cinfo->quantize_colors = TRUE; jpeg_calc_output_dimensions(cinfo); if (cinfo->output_components != 1 && cinfo->output_components != 3) { fprintf(stderr, "Can't read %d components-jpeg file\n", cinfo->output_components); jpeg_destroy_decompress(cinfo); free(cinfo); return 0; } (void)jpeg_start_decompress(cinfo); /* JSAMPLEs per row in output buffer */ p->bytes_per_line = width * cinfo->output_components; p->image_size = p->bytes_per_line * height; /* allocate memory for image */ #ifdef DEBUG fprintf(stderr, "Attempt to allocate memory %d bytes... ", p->image_size); #endif if ((p->image = malloc(p->image_size)) == NULL) { fprintf(stderr, "Can't allocate memory for image\n"); jpeg_destroy_decompress(cinfo); free(cinfo); return 0; } #ifdef DEBUG fprintf(stderr, " ok.\n"); #endif /* loading... */ while (cinfo->output_scanline < height) { buffer[0] = (JSAMPROW)&p->image[cinfo->output_scanline * p->bytes_per_line]; (void)jpeg_read_scanlines(cinfo, buffer, 1); } if (cinfo->out_color_space == JCS_GRAYSCALE) { p->ncolors = 256; p->type = _GRAY; } else { /* Copy colormap. Because jpeg_finish_decompress will release colormap memory */ if (cinfo->quantize_colors == TRUE) { if (cinfo->out_color_components == 1) for (j = 0; j < cinfo->actual_number_of_colors; j++) p->colormap[j][0] = p->colormap[j][1] = p->colormap[j][2] = cinfo->colormap[0][j]; else for (j = 0; j < cinfo->actual_number_of_colors; j++) for (i = 0; i < 3; i++) p->colormap[j][i] = cinfo->colormap[i][j]; p->ncolors = cinfo->actual_number_of_colors; p->type = _INDEX; } else { p->ncolors = 1 << 24; p->type = _RGB24; } } #ifdef DEBUG fprintf(stderr, "%d colors\n", p->ncolors); #endif (void)jpeg_finish_decompress(cinfo); jpeg_destroy_decompress(cinfo); free(cinfo); return 1; } GLOBAL(int) jpeg_load_image(Info *info, Image *p) { if (!jpeg_decode_image(info, p)) return info->format == NULL ? PROC_NOT : PROC_ERROR; info->npics = 1; /* set handler */ info->handler.destroy = NULL; info->handler.alarmset = NULL; info->handler.alarm = NULL; info->handler.alarmoff = NULL; return PROC_OK; }