Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

ReadPng.h

Go to the documentation of this file.
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     //longjmp(png_ptr->jmpbuf, 1);
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     //if (setjmp(png->jmpbuf)) {
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; // This should have been done by png_set_read_fn ?!?
00114 
00115     png_set_sig_bytes(png, HEADER_SIZE);
00116 
00117     //Image info
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); //ignore alpha & backround
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         //if (setjmp(png->jmpbuf)) {
00158         /*
00159         if (setjmp(gReadPngJmpbuf))
00160         {
00161             std::cout << "setjmp" << std::endl;
00162             return;
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     // This produces "Read errors" on some files and is not needed anyway
00181     //png_read_end(png, pngInfo);
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 // TODO : not really a template function since ArrayT has to be UInt8 based.
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 // TODO : not really a template function since ArrayT has to be UInt8 based.
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 // TODO : not really a template function since ArrayT has to be UInt8 based.
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 } // namespace Array
00247 } // namespace Core
00248 } // namespace Impala
00249 
00250 #endif

Generated on Fri Mar 19 09:30:53 2010 for ImpalaSrc by  doxygen 1.5.1