19862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org/*
29862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * Copyright (C)2011 D. R. Commander.  All Rights Reserved.
3f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org *
49862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * Redistribution and use in source and binary forms, with or without
59862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * modification, are permitted provided that the following conditions are met:
6f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org *
79862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * - Redistributions of source code must retain the above copyright notice,
89862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org *   this list of conditions and the following disclaimer.
99862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * - Redistributions in binary form must reproduce the above copyright notice,
109862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org *   this list of conditions and the following disclaimer in the documentation
119862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org *   and/or other materials provided with the distribution.
129862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * - Neither the name of the libjpeg-turbo Project nor the names of its
139862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org *   contributors may be used to endorse or promote products derived from this
149862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org *   software without specific prior written permission.
159862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org *
169862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
179862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
209862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
219862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
229862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
239862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
249862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
259862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
269862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org * POSSIBILITY OF SUCH DAMAGE.
279862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org */
289862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
29f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org#include <stdio.h>
30f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org#include <string.h>
319862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include <setjmp.h>
329862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include <errno.h>
339862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include "cdjpeg.h"
349862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include <jpeglib.h>
359862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include <jpegint.h>
369862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include "tjutil.h"
379862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#include "bmp.h"
389862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
399862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
409862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org/* This duplicates the functionality of the VirtualGL bitmap library using
419862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org   the components from cjpeg and djpeg */
429862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
439862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
449862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org/* Error handling (based on example in example.c) */
459862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
469862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgstatic char errStr[JMSG_LENGTH_MAX]="No error";
479862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
489862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgstruct my_error_mgr
49f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org{
509862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	struct jpeg_error_mgr pub;
519862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jmp_buf setjmp_buffer;
529862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org};
539862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgtypedef struct my_error_mgr *my_error_ptr;
54f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
559862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgstatic void my_error_exit(j_common_ptr cinfo)
569862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org{
579862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	my_error_ptr myerr=(my_error_ptr)cinfo->err;
589862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*cinfo->err->output_message)(cinfo);
599862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	longjmp(myerr->setjmp_buffer, 1);
60f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org}
61f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
629862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org/* Based on output_message() in jerror.c */
639862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
649862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgstatic void my_output_message(j_common_ptr cinfo)
65f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org{
669862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*cinfo->err->format_message)(cinfo, errStr);
679862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org}
68f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
699862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m);  \
709862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	retval=-1;  goto bailout;}
719862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org#define _throwunix(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m,  \
729862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	strerror(errno));  retval=-1;  goto bailout;}
73f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
749862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
759862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgstatic void pixelconvert(unsigned char *srcbuf, int srcpf, int srcbottomup,
769862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	unsigned char *dstbuf, int dstpf, int dstbottomup, int w, int h)
779862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org{
789862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	unsigned char *srcptr=srcbuf, *srcptr2;
799862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int srcps=tjPixelSize[srcpf];
809862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int srcstride=srcbottomup? -w*srcps:w*srcps;
819862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	unsigned char *dstptr=dstbuf, *dstptr2;
829862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int dstps=tjPixelSize[dstpf];
839862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int dststride=dstbottomup? -w*dstps:w*dstps;
849862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int row, col;
859862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
869862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(srcbottomup) srcptr=&srcbuf[w*srcps*(h-1)];
879862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(dstbottomup) dstptr=&dstbuf[w*dstps*(h-1)];
889862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	for(row=0; row<h; row++, srcptr+=srcstride, dstptr+=dststride)
89f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	{
909862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		for(col=0, srcptr2=srcptr, dstptr2=dstptr; col<w; col++, srcptr2+=srcps,
919862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			dstptr2+=dstps)
92f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org		{
939862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			dstptr2[tjRedOffset[dstpf]]=srcptr2[tjRedOffset[srcpf]];
949862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			dstptr2[tjGreenOffset[dstpf]]=srcptr2[tjGreenOffset[srcpf]];
959862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			dstptr2[tjBlueOffset[dstpf]]=srcptr2[tjBlueOffset[srcpf]];
96f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org		}
97f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	}
98f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org}
99f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
100f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
101f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.orgint loadbmp(char *filename, unsigned char **buf, int *w, int *h,
1029862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int dstpf, int bottomup)
103f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org{
1049862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int retval=0, dstps, srcpf, tempc;
1059862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	struct jpeg_compress_struct cinfo;
1069862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	struct my_error_mgr jerr;
1079862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	cjpeg_source_ptr src;
1089862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	FILE *file=NULL;
1099862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
110c6beb74efd1b43982a5b6c957c57426442359c17hbono@chromium.org	memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
111c6beb74efd1b43982a5b6c957c57426442359c17hbono@chromium.org
1129862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(!filename || !buf || !w || !h || dstpf<0 || dstpf>=TJ_NUMPF)
1139862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		_throw("loadbmp(): Invalid argument");
1149862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1159862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if((file=fopen(filename, "rb"))==NULL)
1169862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		_throwunix("loadbmp(): Cannot open input file");
1179862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1189862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	cinfo.err=jpeg_std_error(&jerr.pub);
1199862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jerr.pub.error_exit=my_error_exit;
1209862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jerr.pub.output_message=my_output_message;
1219862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1229862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(setjmp(jerr.setjmp_buffer))
123f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	{
1249862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		/* If we get here, the JPEG code has signaled an error. */
1259862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		retval=-1;  goto bailout;
126f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	}
1279862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1289862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jpeg_create_compress(&cinfo);
1299862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if((tempc=getc(file))<0 || ungetc(tempc, file)==EOF)
1309862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		_throwunix("loadbmp(): Could not read input file")
1319862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else if(tempc==EOF) _throw("loadbmp(): Input file contains no data");
1329862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1339862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(tempc=='B')
134f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	{
1359862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		if((src=jinit_read_bmp(&cinfo))==NULL)
1369862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			_throw("loadbmp(): Could not initialize bitmap loader");
137f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	}
1389862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else if(tempc=='P')
139f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	{
1409862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		if((src=jinit_read_ppm(&cinfo))==NULL)
1419862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			_throw("loadbmp(): Could not initialize bitmap loader");
142f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	}
1439862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else _throw("loadbmp(): Unsupported file type");
144f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1459862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	src->input_file=file;
1469862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*src->start_input)(&cinfo, src);
1479862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*cinfo.mem->realize_virt_arrays)((j_common_ptr)&cinfo);
148f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1499862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	*w=cinfo.image_width;  *h=cinfo.image_height;
150f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1519862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(cinfo.input_components==1 && cinfo.in_color_space==JCS_RGB)
1529862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		srcpf=TJPF_GRAY;
1539862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else srcpf=TJPF_RGB;
154f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1559862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	dstps=tjPixelSize[dstpf];
1569862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if((*buf=(unsigned char *)malloc((*w)*(*h)*dstps))==NULL)
1579862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		_throw("loadbmp(): Memory allocation failure");
158f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1599862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	while(cinfo.next_scanline<cinfo.image_height)
1609862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	{
1619862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		int i, nlines=(*src->get_pixel_rows)(&cinfo, src);
1629862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		for(i=0; i<nlines; i++)
1639862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		{
1649862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			unsigned char *outbuf;  int row;
1659862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			row=cinfo.next_scanline+i;
1669862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			if(bottomup) outbuf=&(*buf)[((*h)-row-1)*(*w)*dstps];
1679862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			else outbuf=&(*buf)[row*(*w)*dstps];
1689862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			pixelconvert(src->buffer[i], srcpf, 0, outbuf, dstpf, bottomup, *w,
1699862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org				nlines);
1709862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		}
1719862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		cinfo.next_scanline+=nlines;
1723395bcc26e390d2960d15020d4a4d27ae0c122fenoel@chromium.org	}
173f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1749862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*src->finish_input)(&cinfo, src);
175f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1769862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	bailout:
1779862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jpeg_destroy_compress(&cinfo);
1789862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(file) fclose(file);
1799862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(retval<0 && buf && *buf) {free(*buf);  *buf=NULL;}
1809862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	return retval;
181f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org}
182f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
1839862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1849862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.orgint savebmp(char *filename, unsigned char *buf, int w, int h, int srcpf,
1859862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int bottomup)
186f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org{
1879862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	int retval=0, srcps, dstpf;
1889862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	struct jpeg_decompress_struct dinfo;
1899862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	struct my_error_mgr jerr;
1909862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	djpeg_dest_ptr dst;
1919862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	FILE *file=NULL;
1929862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	char *ptr=NULL;
1939862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
194c6beb74efd1b43982a5b6c957c57426442359c17hbono@chromium.org	memset(&dinfo, 0, sizeof(struct jpeg_decompress_struct));
195c6beb74efd1b43982a5b6c957c57426442359c17hbono@chromium.org
1969862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(!filename || !buf || w<1 || h<1 || srcpf<0 || srcpf>=TJ_NUMPF)
1979862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		_throw("savebmp(): Invalid argument");
1989862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
1999862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if((file=fopen(filename, "wb"))==NULL)
2009862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		_throwunix("savebmp(): Cannot open output file");
2019862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2029862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	dinfo.err=jpeg_std_error(&jerr.pub);
2039862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jerr.pub.error_exit=my_error_exit;
2049862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jerr.pub.output_message=my_output_message;
2059862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2069862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(setjmp(jerr.setjmp_buffer))
2079862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	{
2089862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		/* If we get here, the JPEG code has signaled an error. */
2099862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		retval=-1;  goto bailout;
2109862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	}
2119862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2129862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jpeg_create_decompress(&dinfo);
2139862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(srcpf==TJPF_GRAY)
2149862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	{
2159862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		dinfo.out_color_components=dinfo.output_components=1;
2169862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		dinfo.out_color_space=JCS_GRAYSCALE;
2179862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	}
2189862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else
219f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	{
2209862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		dinfo.out_color_components=dinfo.output_components=3;
2219862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		dinfo.out_color_space=JCS_RGB;
222f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	}
2239862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	dinfo.image_width=w;  dinfo.image_height=h;
2249862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	dinfo.global_state=DSTATE_READY;
2259862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	dinfo.scale_num=dinfo.scale_denom=1;
226f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
2279862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	ptr=strrchr(filename, '.');
2289862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(ptr && !strcasecmp(ptr, ".bmp"))
2299862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	{
2309862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		if((dst=jinit_write_bmp(&dinfo, 0))==NULL)
2319862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			_throw("savebmp(): Could not initialize bitmap writer");
2329862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	}
2339862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else
234f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	{
2359862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		if((dst=jinit_write_ppm(&dinfo))==NULL)
2369862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			_throw("savebmp(): Could not initialize PPM writer");
237f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org	}
238f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
2393395bcc26e390d2960d15020d4a4d27ae0c122fenoel@chromium.org	dst->output_file=file;
2409862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*dst->start_output)(&dinfo, dst);
2419862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*dinfo.mem->realize_virt_arrays)((j_common_ptr)&dinfo);
2429862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2439862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(srcpf==TJPF_GRAY) dstpf=srcpf;
2449862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	else dstpf=TJPF_RGB;
2459862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	srcps=tjPixelSize[srcpf];
2469862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2479862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	while(dinfo.output_scanline<dinfo.output_height)
2489862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	{
2499862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		int i, nlines=dst->buffer_height;
2509862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		for(i=0; i<nlines; i++)
2519862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		{
2529862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			unsigned char *inbuf;  int row;
2539862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			row=dinfo.output_scanline+i;
2549862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			if(bottomup) inbuf=&buf[(h-row-1)*w*srcps];
2559862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			else inbuf=&buf[row*w*srcps];
2569862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org			pixelconvert(inbuf, srcpf, bottomup, dst->buffer[i], dstpf, 0, w,
2579862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org				nlines);
2589862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		}
2599862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		(*dst->put_pixel_rows)(&dinfo, dst, nlines);
2609862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org		dinfo.output_scanline+=nlines;
2613395bcc26e390d2960d15020d4a4d27ae0c122fenoel@chromium.org	}
2629862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2639862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	(*dst->finish_output)(&dinfo, dst);
2649862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org
2659862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	bailout:
2669862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	jpeg_destroy_decompress(&dinfo);
2679862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	if(file) fclose(file);
2689862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	return retval;
269f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org}
270f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org
271f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.orgconst char *bmpgeterr(void)
272f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org{
2739862697206250265c6bb37a4186b0a411c78de3bhbono@chromium.org	return errStr;
274f0c4f33a4aa0760ba0e12a254b69d996442c9c5hbono@chromium.org}
275