00001 #ifndef Impala_Core_Array_ReadPng_h
00002 #define Impala_Core_Array_ReadPng_h
00003
00004 #include <string>
00005 #include "Basis/ILog.h"
00006 #include "Persistency/File.h"
00007 #include "Util/Database.h"
00008 #include "Core/Array/Arrays.h"
00009 #ifdef PNG_USED
00010 #include "Link/Png/CxPngLink.h"
00011 #endif
00012
00013 namespace Impala
00014 {
00015 namespace Core
00016 {
00017 namespace Array
00018 {
00019
00020
00021 #ifdef PNG_USED
00022 static jmp_buf gReadPngJmpbuf;
00023
00024 static inline void
00025 ReadPngErrorFunc(png_structp png_ptr, png_const_charp msg)
00026 {
00027 std::cerr << "PNG Error: " << msg << std::endl;
00028
00029 longjmp(gReadPngJmpbuf, 1);
00030 }
00031
00032 static inline void
00033 ReadPngWarnFunc(png_structp png_ptr, png_const_charp msg)
00034 {
00035 std::cerr << "PNG Warning: " << msg << std::endl;
00036 }
00037
00038 static inline void
00039 ReadPngDataFunc(png_structp png_ptr, png_bytep data, png_size_t length)
00040 {
00041 char* buf = (char*) png_ptr->io_ptr;
00042 memcpy(data, png_ptr->io_ptr, length);
00043 buf += length;
00044 png_ptr->io_ptr = buf;
00045 }
00046 #endif
00047
00048
00049 inline void
00050 ReadPngFromMemory(Array2dScalarInt32*& dst, char *buf, int bufsize)
00051 {
00052 ILOG_VAR(Impala.Core.Array.ReadPngFromMemory);
00053 ILOG_ERROR("array type not supported");
00054 }
00055
00056 inline void
00057 ReadPngFromMemory(Array2dScalarReal64*& dst, char *buf, int bufsize)
00058 {
00059 ILOG_VAR(Impala.Core.Array.ReadPngFromMemory);
00060 ILOG_ERROR("array type not supported");
00061 }
00062
00063 inline void
00064 ReadPngFromMemory(Array2dVec3Real64*& dst, char *buf, int bufsize)
00065 {
00066 ILOG_VAR(Impala.Core.Array.ReadPngFromMemory);
00067 ILOG_ERROR("array type not supported");
00068 }
00069
00070 #ifdef PNG_USED
00071
00072 template <class ArrayT>
00073 inline void
00074 ReadPngFromMemory(ArrayT*& dst, char *buf, int bufsize)
00075 {
00076 ILOG_VAR(Impala.Core.Array.ReadPng);
00077 png_structp png;
00078 png_infop pngInfo;
00079 const int HEADER_SIZE = 8;
00080
00081 int is_png = (png_sig_cmp((png_bytep)buf, 0, HEADER_SIZE) == 0);
00082 buf += HEADER_SIZE;
00083 if (!is_png)
00084 {
00085 ILOG_ERROR("Not in PNG format");
00086 return;
00087 }
00088
00089 png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, ReadPngErrorFunc,
00090 ReadPngWarnFunc);
00091 if (!png)
00092 {
00093 ILOG_ERROR("png_create_read_struct error");
00094 return;
00095 }
00096
00097 pngInfo = png_create_info_struct(png);
00098 if (!pngInfo)
00099 {
00100 ILOG_ERROR("png_create_info_struct error");
00101 png_destroy_read_struct(&png, NULL, NULL);
00102 return;
00103 }
00104
00105 if (setjmp(gReadPngJmpbuf))
00106 {
00107 ILOG_INFO("setjmp");
00108 png_destroy_read_struct(&png, &pngInfo, NULL);
00109 return;
00110 }
00111
00112 png_set_read_fn(png, buf, ReadPngDataFunc);
00113 png->io_ptr = buf;
00114
00115 png_set_sig_bytes(png, HEADER_SIZE);
00116
00117
00118
00119 png_read_info(png, pngInfo);
00120
00121 png_uint_32 width;
00122 png_uint_32 height;
00123 int bit_depth, color_type;
00124 int interlace_type, compression_type, filter_type;
00125 png_get_IHDR(png, pngInfo, &width, &height, &bit_depth, &color_type,
00126 &interlace_type, &compression_type, &filter_type);
00127
00128 if (interlace_type == PNG_INTERLACE_ADAM7)
00129 {
00130 ILOG_ERROR("Interlaced PNG's not supported yet.");
00131 png_destroy_read_struct(&png, &pngInfo, NULL);
00132 return;
00133 }
00134 if (bit_depth > 8)
00135 {
00136 ILOG_ERROR("Bit depths bigger than 8 not supported yet.");
00137 png_destroy_read_struct(&png, &pngInfo, NULL);
00138 return;
00139 }
00140 if (color_type == PNG_COLOR_TYPE_PALETTE)
00141 png_set_palette_to_rgb(png);
00142 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00143 png_set_gray_1_2_4_to_8(png);
00144 if (color_type & PNG_COLOR_MASK_ALPHA)
00145 png_set_strip_alpha(png);
00146 bool gray = !(color_type & PNG_COLOR_MASK_COLOR);
00147 png_read_update_info(png, pngInfo);
00148
00149 if (dst == 0)
00150 dst = ArrayCreate<ArrayT>(width, height);
00151
00152 UInt8* dataPtr;
00153 png_uint_32 row = 0;
00154 while (row < height)
00155 {
00156 dataPtr = dst->CPB(0, row);
00157
00158
00159
00160
00161
00162
00163
00164
00165 png_read_row(png, dataPtr, NULL);
00166 row++;
00167 if (gray && (ArrayT::ElemSize() == 3))
00168 {
00169 UInt8* endLine = dataPtr + width * 3 - 1;
00170 UInt8* endData = dataPtr + width - 1;
00171 for (png_uint_32 i=0 ; i<width ; i++)
00172 {
00173 *endLine-- = *endData;
00174 *endLine-- = *endData;
00175 *endLine-- = *endData--;
00176 }
00177 }
00178 }
00179
00180
00181
00182
00183 png_destroy_read_struct(&png, &pngInfo, NULL);
00184 }
00185
00186 #else
00187
00188 template <class ArrayT>
00189 inline void
00190 ReadPngFromMemory(ArrayT*& dst, char *buf, int bufsize)
00191 {
00192 ILOG_VAR(Impala.Core.Array.ReadPngFromMemory);
00193 ILOG_ERROR("ReadPng not available");
00194 }
00195
00196 #endif // PNG_USED
00197
00198
00199
00200 template <class ArrayT>
00201 inline void
00202 ReadPng(ArrayT*& dst, Util::IOBuffer* buffer, size_t memBufSize = 10000000)
00203 {
00204 ILOG_VAR(Impala.Core.Array.ReadPng);
00205 char* buf = new char[memBufSize];
00206 size_t nrRead = buffer->Read(buf, memBufSize);
00207 if (nrRead >= memBufSize)
00208 {
00209 ILOG_WARN("ReadPng: buffer to small");
00210 delete buf;
00211 return;
00212 }
00213 ReadPngFromMemory(dst, buf, memBufSize);
00214 delete buf;
00215 }
00216
00217 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00218
00219 template <class ArrayT>
00220 inline void
00221 ReadPng(ArrayT*& dst, String fileName, Util::Database* db,
00222 int memBufSize = 10000000)
00223 {
00224 Util::IOBuffer* buf = db->GetIOBuffer(fileName, true, false, "");
00225 if (buf)
00226 {
00227 ReadPng(dst, buf, memBufSize);
00228 delete buf;
00229 }
00230 }
00231 #endif // REPOSITORY_USED
00232
00233
00234 template <class ArrayT>
00235 inline void
00236 ReadPng(ArrayT*& dst, Persistency::File file, int memBufSize = 10000000)
00237 {
00238 Util::IOBuffer* buf = file.GetReadBuffer();
00239 if (buf)
00240 {
00241 ReadPng(dst, buf, memBufSize);
00242 delete buf;
00243 }
00244 }
00245
00246 }
00247 }
00248 }
00249
00250 #endif