2 * psychlops_g_PNG_bridge.cpp
3 * Psychlops Standard Library (Universal)
5 * Last Modified 2006/08/22 by Kenchi HOSOKAWA
6 * (C) 2006- Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
13 #include "../../../core/ApplicationInterfaces/psychlops_code_exception.h"
14 #include "../../../core/graphic/psychlops_g_image.h"
15 #include "psychlops_g_PNG_bridge.h"
19 namespace IMAGE_FORMATS {
22 PNG_BRIDGE::PNG_BRIDGE() {
25 PNG_BRIDGE::~PNG_BRIDGE() {
30 void PNG_BRIDGE::load(const char *file_name, Image * target) {
31 open(file_name, "rb");
36 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
38 void PNG_BRIDGE::save(const char *file_name, Image * target) {
39 open(file_name, "wb");
41 prepare_before_write();
45 png_destroy_write_struct(&png_ptr, &info_ptr);
47 void PNG_BRIDGE::open(const char *file_name, const char *mode) {
49 if ((fp = fopen(file_name, mode)) == NULL)
50 throw Exception(typeid(*this), "FILE ACCESS ERROR", "Failed to open the requested file.");
53 void PNG_BRIDGE::close() {
54 if(is_opened_) fclose(fp);
59 void PNG_BRIDGE::check_before_read() {
60 png_byte sig[PNG_BYTES_TO_CHECK];
62 if (fread(sig, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) {
64 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested file is not PNG.");
66 if (!png_check_sig(sig, PNG_BYTES_TO_CHECK)) {
68 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested file is not PNG.");
70 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
73 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested file is not PNG.");
75 info_ptr = png_create_info_struct(png_ptr);
77 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
79 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested file is not PNG.");
81 end_info_ptr = png_create_info_struct(png_ptr);
83 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
85 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested file is not PNG.");
87 if (setjmp(png_jmpbuf(png_ptr))) {
88 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
90 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested file is not PNG.");
92 png_init_io(png_ptr, fp);
93 png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
94 png_read_info(png_ptr, info_ptr);
97 void PNG_BRIDGE::read(Image * target) {
98 unsigned int width = png_get_image_width(png_ptr, info_ptr);
99 unsigned int height = png_get_image_height(png_ptr, info_ptr);
100 Image::PixelComponentsCnt pix_component;
101 switch (png_get_color_type(png_ptr, info_ptr)) {
102 case PNG_COLOR_TYPE_GRAY:
103 pix_component = Image::GRAY;
105 case PNG_COLOR_TYPE_RGB:
106 pix_component = Image::RGB;
108 case PNG_COLOR_TYPE_RGB_ALPHA:
109 pix_component = Image::RGBA;
112 pix_component = Image::RGBA;
115 png_bytep *row_pointers = new png_bytep[height];
117 target->set(width, height, pix_component);
118 readTargetMemoryAlignment(target);
119 for(unsigned int i=0; i<height; i++) row_pointers[i] = target_bitmap_ub_ + (height-i-1)*(target_bytes_per_line_);
121 png_read_image(png_ptr, row_pointers);
122 png_read_end(png_ptr, end_info_ptr);
123 delete [] row_pointers;
129 void PNG_BRIDGE::prepare_before_write() {
130 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
133 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested data is not able to be put as a PNG file.");
135 info_ptr = png_create_info_struct(png_ptr);
137 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
139 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested data is not able to be put as a PNG file.");
141 if (setjmp(png_jmpbuf(png_ptr))) {
142 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
144 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested data is not able to be put as a PNG file.");
146 png_init_io(png_ptr, fp);
147 png_set_write_status_fn(png_ptr, NULL); //callback_function_per_row(png_ptr, png_uint_32 row, int pass)
150 void PNG_BRIDGE::write(Image * target) {
151 readTargetMemoryAlignment(target);
153 unsigned int width = (unsigned int)target->getWidth();
154 unsigned int height = (unsigned int)target->getHeight();
157 switch (pix_components_) {
159 color_type = PNG_COLOR_TYPE_GRAY;
162 color_type = PNG_COLOR_TYPE_RGB;
165 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
168 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
172 unsigned int bit_depth;
173 switch(pix_precision_) {
175 throw Exception(typeid(*this), "FILE FORMAT ERROR", "The requested data is not able to be put as a PNG file.");
185 int interlace_type = PNG_INTERLACE_NONE;
186 int compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
187 int filter_method = PNG_FILTER_TYPE_DEFAULT;
189 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type, compression_type, filter_method);
192 png_write_info(png_ptr, info_ptr);
194 png_bytep *row_pointers = new png_bytep[height];
195 for(unsigned int i=0; i<height; i++) row_pointers[i] = target_bitmap_ub_ + (height-i-1)*(target_bytes_per_line_);
196 png_write_image(png_ptr, row_pointers);
198 png_write_end(png_ptr, NULL);
199 delete [] row_pointers;