Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / libjpeg_turbo / bmp.c
1 /*
2  * Copyright (C)2011 D. R. Commander.  All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * - Redistributions of source code must retain the above copyright notice,
8  *   this list of conditions and the following disclaimer.
9  * - Redistributions in binary form must reproduce the above copyright notice,
10  *   this list of conditions and the following disclaimer in the documentation
11  *   and/or other materials provided with the distribution.
12  * - Neither the name of the libjpeg-turbo Project nor the names of its
13  *   contributors may be used to endorse or promote products derived from this
14  *   software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <setjmp.h>
32 #include <errno.h>
33 #include "cdjpeg.h"
34 #include <jpeglib.h>
35 #include <jpegint.h>
36 #include "tjutil.h"
37 #include "bmp.h"
38
39
40 /* This duplicates the functionality of the VirtualGL bitmap library using
41    the components from cjpeg and djpeg */
42
43
44 /* Error handling (based on example in example.c) */
45
46 static char errStr[JMSG_LENGTH_MAX]="No error";
47
48 struct my_error_mgr
49 {
50         struct jpeg_error_mgr pub;
51         jmp_buf setjmp_buffer;
52 };
53 typedef struct my_error_mgr *my_error_ptr;
54
55 static void my_error_exit(j_common_ptr cinfo)
56 {
57         my_error_ptr myerr=(my_error_ptr)cinfo->err;
58         (*cinfo->err->output_message)(cinfo);
59         longjmp(myerr->setjmp_buffer, 1);
60 }
61
62 /* Based on output_message() in jerror.c */
63
64 static void my_output_message(j_common_ptr cinfo)
65 {
66         (*cinfo->err->format_message)(cinfo, errStr);
67 }
68
69 #define _throw(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s", m);  \
70         retval=-1;  goto bailout;}
71 #define _throwunix(m) {snprintf(errStr, JMSG_LENGTH_MAX, "%s\n%s", m,  \
72         strerror(errno));  retval=-1;  goto bailout;}
73
74
75 static void pixelconvert(unsigned char *srcbuf, int srcpf, int srcbottomup,
76         unsigned char *dstbuf, int dstpf, int dstbottomup, int w, int h)
77 {
78         unsigned char *srcptr=srcbuf, *srcptr2;
79         int srcps=tjPixelSize[srcpf];
80         int srcstride=srcbottomup? -w*srcps:w*srcps;
81         unsigned char *dstptr=dstbuf, *dstptr2;
82         int dstps=tjPixelSize[dstpf];
83         int dststride=dstbottomup? -w*dstps:w*dstps;
84         int row, col;
85
86         if(srcbottomup) srcptr=&srcbuf[w*srcps*(h-1)];
87         if(dstbottomup) dstptr=&dstbuf[w*dstps*(h-1)];
88         for(row=0; row<h; row++, srcptr+=srcstride, dstptr+=dststride)
89         {
90                 for(col=0, srcptr2=srcptr, dstptr2=dstptr; col<w; col++, srcptr2+=srcps,
91                         dstptr2+=dstps)
92                 {
93                         dstptr2[tjRedOffset[dstpf]]=srcptr2[tjRedOffset[srcpf]];
94                         dstptr2[tjGreenOffset[dstpf]]=srcptr2[tjGreenOffset[srcpf]];
95                         dstptr2[tjBlueOffset[dstpf]]=srcptr2[tjBlueOffset[srcpf]];
96                 }
97         }
98 }
99
100
101 int loadbmp(char *filename, unsigned char **buf, int *w, int *h, 
102         int dstpf, int bottomup)
103 {
104         int retval=0, dstps, srcpf, tempc;
105         struct jpeg_compress_struct cinfo;
106         struct my_error_mgr jerr;
107         cjpeg_source_ptr src;
108         FILE *file=NULL;
109
110         memset(&cinfo, 0, sizeof(struct jpeg_compress_struct));
111
112         if(!filename || !buf || !w || !h || dstpf<0 || dstpf>=TJ_NUMPF)
113                 _throw("loadbmp(): Invalid argument");
114
115         if((file=fopen(filename, "rb"))==NULL)
116                 _throwunix("loadbmp(): Cannot open input file");
117
118         cinfo.err=jpeg_std_error(&jerr.pub);
119         jerr.pub.error_exit=my_error_exit;
120         jerr.pub.output_message=my_output_message;
121
122         if(setjmp(jerr.setjmp_buffer))
123         {
124                 /* If we get here, the JPEG code has signaled an error. */
125                 retval=-1;  goto bailout;
126         }
127
128         jpeg_create_compress(&cinfo);
129         if((tempc=getc(file))<0 || ungetc(tempc, file)==EOF)
130                 _throwunix("loadbmp(): Could not read input file")
131         else if(tempc==EOF) _throw("loadbmp(): Input file contains no data");
132
133         if(tempc=='B')
134         {
135                 if((src=jinit_read_bmp(&cinfo))==NULL)
136                         _throw("loadbmp(): Could not initialize bitmap loader");
137         }
138         else if(tempc=='P')
139         {
140                 if((src=jinit_read_ppm(&cinfo))==NULL)
141                         _throw("loadbmp(): Could not initialize bitmap loader");
142         }
143         else _throw("loadbmp(): Unsupported file type");
144
145         src->input_file=file;
146         (*src->start_input)(&cinfo, src);
147         (*cinfo.mem->realize_virt_arrays)((j_common_ptr)&cinfo);
148
149         *w=cinfo.image_width;  *h=cinfo.image_height;
150
151         if(cinfo.input_components==1 && cinfo.in_color_space==JCS_RGB)
152                 srcpf=TJPF_GRAY;
153         else srcpf=TJPF_RGB;
154
155         dstps=tjPixelSize[dstpf];
156         if((*buf=(unsigned char *)malloc((*w)*(*h)*dstps))==NULL)
157                 _throw("loadbmp(): Memory allocation failure");
158
159         while(cinfo.next_scanline<cinfo.image_height)
160         {
161                 int i, nlines=(*src->get_pixel_rows)(&cinfo, src);
162                 for(i=0; i<nlines; i++)
163                 {
164                         unsigned char *outbuf;  int row;
165                         row=cinfo.next_scanline+i;
166                         if(bottomup) outbuf=&(*buf)[((*h)-row-1)*(*w)*dstps];
167                         else outbuf=&(*buf)[row*(*w)*dstps];
168                         pixelconvert(src->buffer[i], srcpf, 0, outbuf, dstpf, bottomup, *w,
169                                 nlines);
170                 }
171                 cinfo.next_scanline+=nlines;
172         }
173
174         (*src->finish_input)(&cinfo, src);
175
176         bailout:
177         jpeg_destroy_compress(&cinfo);
178         if(file) fclose(file);
179         if(retval<0 && buf && *buf) {free(*buf);  *buf=NULL;}
180         return retval;
181 }
182
183
184 int savebmp(char *filename, unsigned char *buf, int w, int h, int srcpf,
185         int bottomup)
186 {
187         int retval=0, srcps, dstpf;
188         struct jpeg_decompress_struct dinfo;
189         struct my_error_mgr jerr;
190         djpeg_dest_ptr dst;
191         FILE *file=NULL;
192         char *ptr=NULL;
193
194         memset(&dinfo, 0, sizeof(struct jpeg_decompress_struct));
195
196         if(!filename || !buf || w<1 || h<1 || srcpf<0 || srcpf>=TJ_NUMPF)
197                 _throw("savebmp(): Invalid argument");
198
199         if((file=fopen(filename, "wb"))==NULL)
200                 _throwunix("savebmp(): Cannot open output file");
201
202         dinfo.err=jpeg_std_error(&jerr.pub);
203         jerr.pub.error_exit=my_error_exit;
204         jerr.pub.output_message=my_output_message;
205
206         if(setjmp(jerr.setjmp_buffer))
207         {
208                 /* If we get here, the JPEG code has signaled an error. */
209                 retval=-1;  goto bailout;
210         }
211
212         jpeg_create_decompress(&dinfo);
213         if(srcpf==TJPF_GRAY)
214         {
215                 dinfo.out_color_components=dinfo.output_components=1;
216                 dinfo.out_color_space=JCS_GRAYSCALE;
217         }
218         else
219         {
220                 dinfo.out_color_components=dinfo.output_components=3;
221                 dinfo.out_color_space=JCS_RGB;
222         }
223         dinfo.image_width=w;  dinfo.image_height=h;
224         dinfo.global_state=DSTATE_READY;
225         dinfo.scale_num=dinfo.scale_denom=1;
226
227         ptr=strrchr(filename, '.');
228         if(ptr && !strcasecmp(ptr, ".bmp"))
229         {
230                 if((dst=jinit_write_bmp(&dinfo, 0))==NULL)
231                         _throw("savebmp(): Could not initialize bitmap writer");
232         }
233         else
234         {
235                 if((dst=jinit_write_ppm(&dinfo))==NULL)
236                         _throw("savebmp(): Could not initialize PPM writer");
237         }
238
239         dst->output_file=file;
240         (*dst->start_output)(&dinfo, dst);
241         (*dinfo.mem->realize_virt_arrays)((j_common_ptr)&dinfo);
242
243         if(srcpf==TJPF_GRAY) dstpf=srcpf;
244         else dstpf=TJPF_RGB;
245         srcps=tjPixelSize[srcpf];
246
247         while(dinfo.output_scanline<dinfo.output_height)
248         {
249                 int i, nlines=dst->buffer_height;
250                 for(i=0; i<nlines; i++)
251                 {
252                         unsigned char *inbuf;  int row;
253                         row=dinfo.output_scanline+i;
254                         if(bottomup) inbuf=&buf[(h-row-1)*w*srcps];
255                         else inbuf=&buf[row*w*srcps];
256                         pixelconvert(inbuf, srcpf, bottomup, dst->buffer[i], dstpf, 0, w,
257                                 nlines);
258                 }
259                 (*dst->put_pixel_rows)(&dinfo, dst, nlines);
260                 dinfo.output_scanline+=nlines;
261         }
262
263         (*dst->finish_output)(&dinfo, dst);
264
265         bailout:
266         jpeg_destroy_decompress(&dinfo);
267         if(file) fclose(file);
268         return retval;
269 }
270
271 const char *bmpgeterr(void)
272 {
273         return errStr;
274 }