themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_PNG_Image.cxx
blobaaadc217b288d361163c205ed276770ea37f4de7
1 //
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.
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.
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.
24 // Please report all bugs and problems on the following page:
26 // http://www.fltk.org/str.php
28 // Contents:
31 // Fl_PNG_Image::Fl_PNG_Image() - Load a PNG image file.
35 // Include necessary header files...
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>
46 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
47 extern "C"
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
57 typedef struct {
58 png_structp pp;
59 const unsigned char *current;
60 const unsigned char *last;
61 } fl_png_memory;
63 static 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
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;
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;
77 #endif // HAVE_LIBPNG && HAVE_LIBZ
80 /**
81 The constructor loads the named PNG image from the given png filename.
83 The destructor frees all memory and server resources that are used by
84 the image.
86 \param[in] filename Name of PNG file to read
88 Fl_PNG_Image::Fl_PNG_Image (const char *filename): Fl_RGB_Image(0,0,0)
90 load_png_(filename, NULL, 0);
93 /**
94 \brief Constructor that reads a PNG image from memory.
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.
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
105 Fl_PNG_Image::Fl_PNG_Image (
106 const char *name_png, const unsigned char *buffer, int maxsize): Fl_RGB_Image(0,0,0)
108 load_png_(name_png, buffer, maxsize);
111 void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_png, int maxsize)
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
123 if (!from_memory) {
124 if ((fp = fl_fopen(name_png, "rb")) == NULL) return;
126 else name_png = "In-memory PNG data";
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;
138 if (setjmp(png_jmpbuf(pp)))
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;
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"...
156 // Get the image dimensions and convert to grayscale or RGB...
157 png_read_info(pp, info);
159 int color_type;
161 color_type = png_get_color_type(pp, info);
162 if ( color_type == PNG_COLOR_TYPE_PALETTE)
164 png_set_palette_to_rgb(pp);
165 png_set_expand(pp);
168 if (color_type == PNG_COLOR_TYPE_GRAY )
170 png_set_expand_gray_1_2_4_to_8 (pp);
173 if (color_type == PNG_COLOR_TYPE_GRAY ||
174 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
176 png_set_gray_to_rgb (pp);
179 if (png_get_color_type(pp, info) & PNG_COLOR_MASK_COLOR)
180 channels = 3;
181 else
182 channels = 1;
184 int num_trans = 0;
185 png_get_tRNS(pp, info, 0, &num_trans, 0);
186 if ((png_get_color_type(pp, info) & PNG_COLOR_MASK_ALPHA) || (num_trans != 0))
187 channels ++;
190 if (png_get_bit_depth(pp, info) < 8)
192 png_set_packing(pp);
193 png_set_expand(pp);
195 else if (png_get_bit_depth(pp, info) == 16)
196 png_set_strip_16(pp);
198 /* # if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA) */
199 // Handle transparency...
200 if (png_get_valid(pp, info, PNG_INFO_tRNS))
201 png_set_tRNS_to_alpha(pp);
202 /* # endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA */
204 /* png_set_swap_alpha(pp); */
205 png_set_bgr(pp);
207 png_set_filler (pp, 0xff, PNG_FILLER_AFTER);
209 png_read_update_info( pp, info );
211 w((int)(png_get_image_width(pp, info)));
212 h((int)(png_get_image_height(pp, info)));
213 d(4);
214 channels = 4;
216 array = new uchar[w() * h() * d()];
217 alloc_array = 1;
219 // Allocate pointers...
220 rows = new png_bytep[h()];
222 for (i = 0; i < h(); i ++)
223 rows[i] = (png_bytep)(array + i * w() * d());
225 // Read the image, handling interlacing as needed...
226 for (i = png_set_interlace_handling(pp); i > 0; i --)
227 png_read_rows(pp, rows, NULL, h());
229 if (channels == 4) {
230 // Convert RGB to 0 when alpha == 0...
231 uchar *ptr = (uchar *)array;
232 for (i = w() * h(); i > 0; i --, ptr += 4)
233 if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
236 // Free memory and return...
237 delete[] rows;
239 png_read_end(pp, info);
240 png_destroy_read_struct(&pp, &info, NULL);
242 if (from_memory) {
243 if (w() && h() && name_png) {
244 Fl_Shared_Image *si = new Fl_Shared_Image(name_png, this);
245 si->add();
247 } else {
248 fclose(fp);
250 #endif // HAVE_LIBPNG && HAVE_LIBZ
255 // End of "$Id: Fl_PNG_Image.cxx 8656 2011-05-12 08:07:27Z manolo $".