1 /*
2  *  Copyright (C) 2005-2008  Maarten de Boer <maarten@resorama.com>
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU General Public License
6  *  as published by the Free Software Foundation; either version 2
7  *  of the License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  *  02110-1301, USA.
18  *
19  */
20 
21 #include "Loader.hxx"
22 
23 extern "C"
24 {
25 #include <png.h>
26 #include <jpeglib.h>
27 #include <stdlib.h>
28 }
29 
Load(const std::string & filename,RGB & target,int x,int y)30 void JpgLoader::Load(const std::string& filename,RGB& target,int x,int y)
31 {
32 	FILE *infile = fopen(filename.c_str(), "rb");
33 	if (!infile)
34 		throw LoaderException(std::string("failed to open ")+filename);
35 
36 	struct jpeg_decompress_struct cinfo;
37 	struct jpeg_error_mgr jerr;
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 	unsigned char *line =
48 		(unsigned char *) malloc(width *
49 										 cinfo.output_components);
50 	int k = 0;
51 	while (cinfo.output_scanline < height) {
52 		unsigned char* ptr = target.Data() + (y+k)*target.Width()*3 + x*3;
53 		jpeg_read_scanlines(&cinfo, &line, 1);
54 		unsigned char *jpeg_ptr = line;
55 		for (unsigned int i = 0; i < width; i++) {
56 			*ptr++ = *jpeg_ptr++;
57 			*ptr++ = *jpeg_ptr++;
58 			*ptr++ = *jpeg_ptr++;
59 		}
60 		k++;
61 	}
62 	free(line);
63 	jpeg_finish_decompress(&cinfo);
64 	jpeg_destroy_decompress(&cinfo);
65 
66 	fclose(infile);
67 }
68 
Load(const std::string & filename,RGBA & target,int x,int y)69 void JpgLoader::Load(const std::string& filename,RGBA& target,int x,int y)
70 {
71 	FILE *infile = fopen(filename.c_str(), "rb");
72 	if (!infile)
73 		throw LoaderException(std::string("failed to open ")+filename);
74 
75 	struct jpeg_decompress_struct cinfo;
76 	struct jpeg_error_mgr jerr;
77 	cinfo.err = jpeg_std_error(&jerr);
78 	jpeg_create_decompress(&cinfo);
79 	jpeg_stdio_src(&cinfo, infile);
80 	jpeg_read_header(&cinfo, TRUE);
81 	jpeg_start_decompress(&cinfo);
82 
83 	width = cinfo.output_width;
84 	height = cinfo.output_height;
85 
86 	unsigned char *line =
87 		(unsigned char *) malloc(width *
88 										 cinfo.output_components);
89 	int k = 0;
90 	while (cinfo.output_scanline < height) {
91 		unsigned char* ptr = target.Data() + (y+k)*target.Width()*4 + x*4;
92 		jpeg_read_scanlines(&cinfo, &line, 1);
93 		unsigned char *jpeg_ptr = line;
94 		for (unsigned int i = 0; i < width; i++) {
95 			*ptr++ = *jpeg_ptr++;
96 			*ptr++ = *jpeg_ptr++;
97 			*ptr++ = *jpeg_ptr++;
98 			*ptr++ = 255;
99 		}
100 		k++;
101 	}
102 	free(line);
103 	jpeg_finish_decompress(&cinfo);
104 	jpeg_destroy_decompress(&cinfo);
105 
106 	fclose(infile);
107 }
108 
Merge(const std::string & filename,RGBA & target,int x,int y)109 void JpgLoader::Merge(const std::string& filename,RGBA& target,int x,int y)
110 {
111 	FILE* infile = fopen(filename.c_str(), "rb");
112 	if (!infile)
113 		throw LoaderException(std::string("failed to open ")+filename);
114 
115 	struct jpeg_decompress_struct cinfo;
116 	struct jpeg_error_mgr jerr;
117 	cinfo.err = jpeg_std_error(&jerr);
118 	jpeg_create_decompress(&cinfo);
119 	jpeg_stdio_src(&cinfo, infile);
120 	jpeg_read_header(&cinfo, TRUE);
121 	jpeg_start_decompress(&cinfo);
122 
123 	unsigned char *line =
124 		(unsigned char *) malloc(cinfo.output_width *
125 										 cinfo.output_components);
126 	int k = 0;
127 	while (cinfo.output_scanline < cinfo.output_height) {
128 		unsigned char* ptr = target.Data() + (y+k)*target.Width()*4 + x*4;
129 		jpeg_read_scanlines(&cinfo, &line, 1);
130 		unsigned char *jpeg_ptr = line;
131 		for (unsigned int i = 0; i < cinfo.output_width; i++) {
132 			if (ptr[0] == 255 &&
133 					ptr[1] == 255 && ptr[2] == 255 && ptr[3] == 255) {
134 				*ptr++ = *jpeg_ptr++;
135 				*ptr++ = *jpeg_ptr++;
136 				*ptr++ = *jpeg_ptr++;
137 				ptr++;
138 			} else {
139 				ptr += 4;
140 				jpeg_ptr += 3;
141 			}
142 		}
143 		k++;
144 	}
145 	free(line);
146 	jpeg_finish_decompress(&cinfo);
147 	jpeg_destroy_decompress(&cinfo);
148 
149 	fclose(infile);
150 }
Load(const std::string & filename,RGBA & target)151 void PngLoader::Load(const std::string& filename,RGBA& target)
152 {
153 	png_byte header[8];
154 	int number = 8;
155 
156 	FILE *fp = fopen(filename.c_str(), "rb");
157 	if (!fp) {
158 		throw LoaderException(std::string("cannot open "+filename));
159 	}
160 	fread(header, 1, number, fp);
161 	int is_png = !png_sig_cmp(header, 0, number);
162 	if (!is_png) {
163 		fclose(fp);
164 		throw LoaderException(filename+" is not a png");
165 	}
166 
167 	png_structp png_ptr = png_create_read_struct
168 								 (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
169 	if (!png_ptr)
170 	{
171 		fclose(fp);
172 		throw LoaderException("png_create_read_struct failed");
173 	}
174 	png_infop info_ptr = png_create_info_struct(png_ptr);
175 	if (!info_ptr) {
176 		png_destroy_read_struct(&png_ptr,
177 										(png_infopp) NULL, (png_infopp) NULL);
178 		fclose(fp);
179 		throw LoaderException("png_create_info_struct failed");
180 	}
181 
182 	png_infop end_info = png_create_info_struct(png_ptr);
183 	if (!end_info) {
184 		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
185 		throw LoaderException("png_create_info_struct (end_info) failed");
186 	}
187 	if (setjmp(png_jmpbuf(png_ptr))) {
188 		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
189 		fclose(fp);
190 		throw LoaderException("png_create_info_struct (end_info) failed");
191 	}
192 	png_init_io(png_ptr, fp);
193 	png_set_sig_bytes(png_ptr, number);
194 	png_uint_32 width, height;
195 	int bit_depth, color_type, interlace_type;
196 	png_read_info(png_ptr, info_ptr);
197 	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
198 					 &color_type, &interlace_type, NULL, NULL);
199 
200 	int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
201 
202 	png_bytep *row_pointers =
203 		(png_bytep *) png_malloc(png_ptr, height * sizeof(png_bytep));
204 
205 	target.Alloc(width,height);
206 
207 	png_bytep ptr = target.Data();
208 	for (unsigned int i = 0; i < height; i++) {
209 		row_pointers[i] = ptr;
210 		ptr += row_bytes;
211 	}
212 	png_read_image(png_ptr, row_pointers);
213 	png_read_end(png_ptr, NULL);
214 	png_free(png_ptr, row_pointers);
215 	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
216 	fclose(fp);
217 }
218 
219