1 /****************************************************************************
2 jpeg.c - read and write jpeg images using libjpeg routines
3 Copyright (C) 2002 Hari Nair <hari@alumni.caltech.edu>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ****************************************************************************/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <jpeglib.h>
25
26 #define MAX_DIMENSION 21600
27
28 int
read_jpeg(const char * filename,int * width,int * height,unsigned char ** rgb)29 read_jpeg(const char *filename, int *width, int *height, unsigned char **rgb)
30 {
31 struct jpeg_decompress_struct cinfo;
32 struct jpeg_error_mgr jerr;
33 unsigned char *ptr = NULL;
34 unsigned int i, ipos;
35
36 FILE *infile = fopen(filename, "rb");
37
38 cinfo.err = jpeg_std_error(&jerr);
39 jpeg_create_decompress(&cinfo);
40 jpeg_stdio_src(&cinfo, infile);
41 jpeg_read_header(&cinfo, TRUE);
42 jpeg_start_decompress(&cinfo);
43
44 *width = cinfo.output_width;
45 *height = cinfo.output_height;
46
47 /* Prevent against integer overflow - thanks to Niels Heinen */
48 if (cinfo.output_width > MAX_DIMENSION
49 || cinfo.output_height > MAX_DIMENSION)
50 {
51 fprintf(stderr, "Width, height in JPEG header is %d, %d\n",
52 cinfo.output_width, cinfo.output_height);
53 return(0);
54 }
55
56 rgb[0] = malloc(3 * cinfo.output_width * cinfo.output_height);
57 if (rgb[0] == NULL)
58 {
59 fprintf(stderr, "Can't allocate memory for JPEG file.\n");
60 fclose(infile);
61 return(0);
62 }
63
64 if (cinfo.output_components == 3)
65 {
66 ptr = rgb[0];
67 while (cinfo.output_scanline < cinfo.output_height)
68 {
69 jpeg_read_scanlines(&cinfo, &ptr, 1);
70 ptr += 3 * cinfo.output_width;
71 }
72 }
73 else if (cinfo.output_components == 1)
74 {
75 ptr = malloc(cinfo.output_width);
76 if (ptr == NULL)
77 {
78 fprintf(stderr, "Can't allocate memory for JPEG file.\n");
79 fclose(infile);
80 return(0);
81 }
82
83 ipos = 0;
84 while (cinfo.output_scanline < cinfo.output_height)
85 {
86 jpeg_read_scanlines(&cinfo, &ptr, 1);
87
88 for (i = 0; i < cinfo.output_width; i++)
89 {
90 memset(rgb[0] + ipos, ptr[i], 3);
91 ipos += 3;
92 }
93 }
94
95 free(ptr);
96 }
97
98 jpeg_finish_decompress(&cinfo);
99 jpeg_destroy_decompress(&cinfo);
100
101 fclose(infile);
102
103 return(1);
104 }
105
106 int
write_jpeg(FILE * outfile,int width,int height,unsigned char * rgb,int quality)107 write_jpeg(FILE *outfile, int width, int height, unsigned char *rgb,
108 int quality)
109 {
110 struct jpeg_compress_struct cinfo;
111 struct jpeg_error_mgr jerr;
112
113 JSAMPROW scanline[1];
114
115 cinfo.err = jpeg_std_error(&jerr);
116 jpeg_create_compress(&cinfo);
117 jpeg_stdio_dest(&cinfo, outfile);
118
119 cinfo.image_width = width;
120 cinfo.image_height = height;
121 cinfo.input_components = 3;
122 cinfo.in_color_space = JCS_RGB;
123
124 jpeg_set_defaults(&cinfo);
125
126 jpeg_set_quality(&cinfo, quality, TRUE);
127
128 jpeg_start_compress(&cinfo, TRUE);
129
130 while (cinfo.next_scanline < (unsigned int) height)
131 {
132 scanline[0] = rgb + 3 * width * cinfo.next_scanline;
133 jpeg_write_scanlines(&cinfo, scanline, 1);
134 }
135
136 jpeg_finish_compress(&cinfo);
137 jpeg_destroy_compress(&cinfo);
138
139 return(1);
140 }
141