blob: 07e912120ce947d1d8a5718688ed83054f8326a9 [file] [log] [blame]
DRCae600162012-06-02 18:45:26 +00001//
2// "$Id: Fl_PNG_Image.cxx 8656 2011-05-12 08:07:27Z manolo $"
3//
4// Fl_PNG_Image routines.
5//
6// Copyright 1997-2011 by Easy Software Products.
7// Image support by Matthias Melcher, Copyright 2000-2009.
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Library General Public
11// License as published by the Free Software Foundation; either
12// version 2 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Library General Public License for more details.
18//
19// You should have received a copy of the GNU Library General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22// USA.
23//
24// Please report all bugs and problems on the following page:
25//
26// http://www.fltk.org/str.php
27//
28// Contents:
29
30//
31// Fl_PNG_Image::Fl_PNG_Image() - Load a PNG image file.
32//
33
34//
35// Include necessary header files...
36//
37
38#include <FL/Fl.H>
39#include <FL/Fl_PNG_Image.H>
40#include <FL/Fl_Shared_Image.H>
41#include <config.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <FL/fl_utf8.h>
45
46#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
47extern "C"
48{
49# include <zlib.h>
50# ifdef HAVE_PNG_H
51# include <png.h>
52# else
53# include <libpng/png.h>
54# endif // HAVE_PNG_H
55}
56
57typedef struct {
58 png_structp pp;
59 const unsigned char *current;
60 const unsigned char *last;
61} fl_png_memory;
62
63static void png_read_data_from_mem( png_structp png_ptr, //pointer to our data
64 png_bytep data, // where to copy the image data for libpng computing
65 png_size_t length) // length of data to copy
66{
67 fl_png_memory *png_mem_data = (fl_png_memory*)png_get_io_ptr(png_ptr); // get the pointer to our struct
68 if (png_mem_data->current + length > png_mem_data->last) {
69 png_error(png_mem_data->pp, "Invalid attempt to read row data");
70 return;
71 }
72 /* copy data from image buffer */
73 memcpy (data, png_mem_data->current, length);
74 /* advance in the memory data */
75 png_mem_data->current += length;
76}
77#endif // HAVE_LIBPNG && HAVE_LIBZ
78
79
80/**
81 The constructor loads the named PNG image from the given png filename.
82
83 The destructor frees all memory and server resources that are used by
84 the image.
85
86 \param[in] filename Name of PNG file to read
87*/
88Fl_PNG_Image::Fl_PNG_Image (const char *filename): Fl_RGB_Image(0,0,0)
89{
90 load_png_(filename, NULL, 0);
91}
92
93/**
94 \brief Constructor that reads a PNG image from memory.
95
96 Construct an image from a block of memory inside the application. Fluid offers
97 "binary Data" chunks as a great way to add image data into the C++ source code.
98 name_png can be NULL. If a name is given, the image is added to the list of
99 shared images (see: Fl_Shared_Image) and will be available by that name.
100
101 \param name_png A name given to this image or NULL
102 \param buffer Pointer to the start of the PNG image in memory
103 \param maxsize Size in bytes of the memory buffer containing the PNG image
104 */
105Fl_PNG_Image::Fl_PNG_Image (
106 const char *name_png, const unsigned char *buffer, int maxsize): Fl_RGB_Image(0,0,0)
107{
108 load_png_(name_png, buffer, maxsize);
109}
110
111void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_png, int maxsize)
112{
113#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
114 int i; // Looping var
115 FILE *fp = NULL; // File pointer
116 int channels; // Number of color channels
117 png_structp pp; // PNG read pointer
118 png_infop info; // PNG info pointers
119 png_bytep *rows;// PNG row pointers
120 fl_png_memory png_mem_data;
121 int from_memory = (buffer_png != NULL); // true if reading image from memory
122
123 if (!from_memory) {
124 if ((fp = fl_fopen(name_png, "rb")) == NULL) return;
125 }
126 else name_png = "In-memory PNG data";
127
128 // Setup the PNG data structures...
129 pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
130 if (pp) info = png_create_info_struct(pp);
131 if (!pp || !info) {
132 if (pp) png_destroy_read_struct(&pp, NULL, NULL);
133 if (!from_memory) fclose(fp);
134 Fl::warning("Cannot allocate memory to read PNG file or data \"%s\".\n", name_png);
135 return;
136 }
137
138 if (setjmp(png_jmpbuf(pp)))
139 {
140 png_destroy_read_struct(&pp, &info, NULL);
141 if (!from_memory) fclose(fp);
142 Fl::warning("PNG file or data \"%s\" contains errors!\n", name_png);
143 return;
144 }
145
146 if (from_memory) {
147 png_mem_data.current = buffer_png;
148 png_mem_data.last = buffer_png + maxsize;
149 png_mem_data.pp = pp;
150 // Initialize the function pointer to the PNG read "engine"...
151 png_set_read_fn (pp, (png_voidp) &png_mem_data, png_read_data_from_mem);
152 } else {
153 png_init_io(pp, fp); // Initialize the PNG file read "engine"...
154 }
155
156 // Get the image dimensions and convert to grayscale or RGB...
157 png_read_info(pp, info);
158
159 if (png_get_color_type(pp, info) == PNG_COLOR_TYPE_PALETTE)
160 png_set_expand(pp);
161
162 if (png_get_color_type(pp, info) & PNG_COLOR_MASK_COLOR)
163 channels = 3;
164 else
165 channels = 1;
166
167 int num_trans = 0;
168 png_get_tRNS(pp, info, 0, &num_trans, 0);
169 if ((png_get_color_type(pp, info) & PNG_COLOR_MASK_ALPHA) || (num_trans != 0))
170 channels ++;
171
172 w((int)(png_get_image_width(pp, info)));
173 h((int)(png_get_image_height(pp, info)));
174 d(channels);
175
176 if (png_get_bit_depth(pp, info) < 8)
177 {
178 png_set_packing(pp);
179 png_set_expand(pp);
180 }
181 else if (png_get_bit_depth(pp, info) == 16)
182 png_set_strip_16(pp);
183
184# if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA)
185 // Handle transparency...
186 if (png_get_valid(pp, info, PNG_INFO_tRNS))
187 png_set_tRNS_to_alpha(pp);
188# endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA
189
190 array = new uchar[w() * h() * d()];
191 alloc_array = 1;
192
193 // Allocate pointers...
194 rows = new png_bytep[h()];
195
196 for (i = 0; i < h(); i ++)
197 rows[i] = (png_bytep)(array + i * w() * d());
198
199 // Read the image, handling interlacing as needed...
200 for (i = png_set_interlace_handling(pp); i > 0; i --)
201 png_read_rows(pp, rows, NULL, h());
202
203#ifdef WIN32
204 // Some Windows graphics drivers don't honor transparency when RGB == white
205 if (channels == 4) {
206 // Convert RGB to 0 when alpha == 0...
207 uchar *ptr = (uchar *)array;
208 for (i = w() * h(); i > 0; i --, ptr += 4)
209 if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
210 }
211#endif // WIN32
212
213 // Free memory and return...
214 delete[] rows;
215
216 png_read_end(pp, info);
217 png_destroy_read_struct(&pp, &info, NULL);
218
219 if (from_memory) {
220 if (w() && h() && name_png) {
221 Fl_Shared_Image *si = new Fl_Shared_Image(name_png, this);
222 si->add();
223 }
224 } else {
225 fclose(fp);
226 }
227#endif // HAVE_LIBPNG && HAVE_LIBZ
228}
229
230
231//
232// End of "$Id: Fl_PNG_Image.cxx 8656 2011-05-12 08:07:27Z manolo $".
233//