Simple Image Loading LibrarY  0.1.0
SILLYPNGImageLoader.cpp
1 /***********************************************************************
2  filename: SILLYPNGImageLoader.cpp
3  created: 11 Jun 2006
4  author: Olivier Delannoy
5 
6  purpose: Definition of the PNGImageLoader methods
7 *************************************************************************/
8 /***************************************************************************
9  * Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files (the
13  * "Software"), to deal in the Software without restriction, including
14  * without limitation the rights to use, copy, modify, merge, publish,
15  * distribute, sublicense, and/or sell copies of the Software, and to
16  * permit persons to whom the Software is furnished to do so, subject to
17  * the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #include <string.h>
33 #endif
34 
35 #include "loaders/SILLYPNGImageLoader.h"
36 
37 #ifndef SILLY_OPT_INLINE
38 #define inline
39 #include "loaders/SILLYPNGImageLoader.icpp"
40 #undef inline
41 #endif
42 
43 #include "loaders/SILLYPNGImageContext.h"
44 #include <png.h>
45 // Start section of namespace SILLY
46 namespace SILLY
47 {
48 void PNG_read_function(png_structp png_ptr, png_bytep data, png_size_t length)
49 {
50  PNGImageContext* png = reinterpret_cast<PNGImageContext*>(png_get_io_ptr(png_ptr));
51  int readed = png->read(data, length);
52  if (readed != (int)length)
53  {
54  png_error(png_ptr, "PNG_read_function error");
55  }
56 }
57 
58 void PNG_warning_function(png_structp png_ptr,
59  png_const_charp error)
60 {
61 // printf("PNG Warning: %s\n", error);
62 }
63 
64 void PNG_error_function(png_structp png_ptr,
65  png_const_charp error)
66 {
67  // printf("PNG Error: %s\n", error);
68  // copied from libpng's pngerror.cpp
69  jmp_buf buf;
70 #if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 4
71  memcpy(buf, png_jmpbuf((png_ptr)), sizeof(jmp_buf));
72 #else
73  memcpy(buf, png_ptr->jmpbuf, sizeof(jmp_buf));
74 #endif
75  longjmp(buf, 1);
76 }
77 
78 
79 PNGImageLoader::PNGImageLoader()
80  : ImageLoader("PNG Image Loader based on libpng")
81 {
82 }
83 PNGImageLoader::~PNGImageLoader()
84 {
85 }
86 
87 
89 {
90  PNGImageContext* png = new PNGImageContext(data);
91  if (!png)
92  {
93  return 0;
94 
95  }
96  // Prepare png loading
97  png->d_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
98  if (png->d_png_ptr == 0)
99  {
100  delete png;
101  return 0;
102  }
103  png->d_info_ptr = png_create_info_struct(png->d_png_ptr);
104  if (png->d_info_ptr == 0)
105  {
106  delete png;
107  return 0;
108  }
109  if (setjmp(png_jmpbuf(png->d_png_ptr)))
110  {
111  delete png;
112  return 0;
113  }
114  png_set_error_fn(png->d_png_ptr, 0, PNG_error_function, PNG_warning_function);
115  png_set_read_fn(png->d_png_ptr, png, PNG_read_function);
116  //png_set_sig_bytes(png->d_png_ptr, 8);
117 
118 
119 
120  // Read header Check whether PNG can depaletize transparently or not
121  int png_transform = PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND;
122  //printf("Start reading png\n");
123  png_read_png(png->d_png_ptr, png->d_info_ptr, png_transform, 0);
124  png->setImageSize();
125  png->d_bit_depth = png_get_bit_depth(png->d_png_ptr, png->d_info_ptr);
126  png->d_num_channels = png_get_channels(png->d_png_ptr, png->d_info_ptr);
127  //printf("PNG Info: width: %d height: %d bpp: %d channels: %d\n", png->getWidth(), png->getHeight(), png->d_bit_depth, png->d_num_channels);
128  if (png->d_bit_depth == 8)
129  {
130  if (png->d_num_channels == 4)
131  {
132  formatSource = PF_RGBA;
133  }
134  else if (png->d_num_channels == 3)
135  {
136  formatSource = PF_RGB;
137  }
138  else
139  {
140  delete png;
141  return 0;
142  }
143  }
144  // Paletized or grayscale not yet handled
145  else
146  {
147  delete png;
148  return 0;
149  }
150  return png;
151 }
152 
153 
155  DataSource* data,
156  ImageContext* context)
157 {
158  PNGImageContext* png = static_cast<PNGImageContext*>(context);
159  byte red;
160  byte green;
161  byte blue;
162  byte alpha;
163  size_t width = png->getWidth();
164  size_t height = png->getHeight();
165  png_bytepp row_pointers = png_get_rows(png->d_png_ptr, png->d_info_ptr);
166  if (png->d_bit_depth == 8)
167  {
168  // Read RGBA
169  if (png->d_num_channels == 4)
170  {
171  for (size_t j = 0 ; j < height ; ++j)
172  {
173  for(size_t i = 0 ; i < width ; ++i)
174  {
175  size_t pixel_offset = 4 * i;
176  red = *(row_pointers[j] + pixel_offset);
177  green = *(row_pointers[j] + pixel_offset + 1);
178  blue = *(row_pointers[j] + pixel_offset + 2);
179  alpha = *(row_pointers[j] + pixel_offset + 3);
180  png->setNextPixel(red, green, blue, alpha);
181  }
182  }
183  }
184  else if (png->d_num_channels == 3)
185  {
186  alpha = 0xff;
187  for (size_t j = 0 ; j < height ; ++j)
188  {
189  for(size_t i = 0 ; i < width ; ++i)
190  {
191  size_t pixel_offset = 3 * i;
192  red = *(row_pointers[j] + pixel_offset);
193  green = *(row_pointers[j] + pixel_offset + 1);
194  blue = *(row_pointers[j] + pixel_offset + 2);
195  png->setNextPixel(red, green, blue, alpha);
196  }
197  }
198 
199  }
200  }
201  if (origin == PO_BOTTOM_LEFT)
202  return png->flipVertically();
203 
204  return true;
205 }
206 
207 } // End section of namespace SILLY
SILLY::PNGImageLoader::loadHeader
ImageContext * loadHeader(PixelFormat &formatSource, DataSource *data)
Parse the header of the image and fill the header struct.
Definition: SILLYPNGImageLoader.cpp:88
SILLY
Simple Image Loading LibrarY namespace.
Definition: SILLYJPGImageContext.cpp:45
SILLY::PNGImageLoader::loadImageData
bool loadImageData(PixelOrigin origin, DataSource *data, ImageContext *context)
Parse the pixels data of the image and fill the header struct.
Definition: SILLYPNGImageLoader.cpp:154
SILLY::PixelFormat
PixelFormat
List all pixel format supported.
Definition: SILLYBase.h:59
SILLY::ImageContext
Store the data needed by an ImageLoader object during the parsing of an image.
Definition: SILLYImageContext.h:70
SILLY::PixelOrigin
PixelOrigin
List all pixel origin supported.
Definition: SILLYBase.h:70
SILLY::DataSource
This is an abstract class used to provide data to the loader.
Definition: SILLYDataSource.h:73
SILLY::ImageContext::flipVertically
bool flipVertically()
Flip pixel ordering.
Definition: SILLYImageContext.cpp:45
SILLY::ImageContext::setNextPixel
void setNextPixel(byte red, byte green, byte bleu, byte alpha)
Set the next pixel of the image.
SILLY::PNGImageContext
Image Context for PNG Image Loader.
Definition: SILLYPNGImageContext.h:72