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