00001 #ifndef Impala_Core_Array_WritePng_h
00002 #define Impala_Core_Array_WritePng_h
00003
00004 #include "Core/Array/Arrays.h"
00005 #include "Core/Array/MakeFromData.h"
00006 #include "Persistency/File.h"
00007
00008 #ifdef PNG_USED
00009 #include "Link/Png/CxPngLink.h"
00010 #endif
00011
00012 namespace Impala
00013 {
00014 namespace Core
00015 {
00016 namespace Array
00017 {
00018
00019
00020 #ifdef PNG_USED
00021 static jmp_buf gWritePngJmpbuf;
00022
00023 static inline void
00024 errorFuncWritePng(png_structp png_ptr, png_const_charp msg)
00025 {
00026 ILOG_VAR(Impala.Core.Array.WritePng);
00027 ILOG_ERROR("PNG Error: " << msg);
00028
00029 longjmp(gWritePngJmpbuf, 1);
00030 }
00031
00032 static inline void
00033 warnFuncWritePng(png_structp png_ptr, png_const_charp msg)
00034 {
00035 ILOG_VAR(Impala.Core.Array.WritePng);
00036 ILOG_WARN("PNG Warning: " << msg);
00037 }
00038
00039 static inline void
00040 WritePngDataFunc(png_structp png_ptr, png_bytep data, png_size_t length)
00041 {
00042 char* buf = (char*) png_ptr->io_ptr;
00043 memcpy(png_ptr->io_ptr, data, length);
00044 buf += length;
00045 png_ptr->io_ptr = buf;
00046 }
00047
00048 static inline void
00049 FlushPngDataFunc(png_structp png_ptr)
00050 {
00051 }
00052
00053
00054 template <class ArrayT>
00055 inline bool
00056 WritePngToMemory(ArrayT* src, char* buf, size_t memBufSize, size_t* outSize)
00057 {
00058 ILOG_VAR(Impala.Core.Array.WritePngToMemory);
00059 png_structp png;
00060 png_infop pngInfo;
00061 png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
00062 errorFuncWritePng, warnFuncWritePng);
00063 if (!png)
00064 {
00065 ILOG_ERROR("png_create_write_struct error");
00066 return false;
00067 }
00068
00069 pngInfo = png_create_info_struct(png);
00070 if (!pngInfo)
00071 {
00072 ILOG_ERROR("png_create_info_struct error");
00073 png_destroy_write_struct(&png, NULL);
00074 return false;
00075 }
00076
00077 if (setjmp(gWritePngJmpbuf))
00078 {
00079 ILOG_ERROR("setjmp");
00080 png_destroy_write_struct(&png, &pngInfo);
00081 return false;
00082 }
00083
00084 png_set_write_fn(png, buf, WritePngDataFunc, FlushPngDataFunc);
00085 png->io_ptr = buf;
00086
00087 int colorType;
00088 if (ArrayT::ElemSize() == 1)
00089 colorType = PNG_COLOR_TYPE_GRAY;
00090 else
00091 colorType = PNG_COLOR_TYPE_RGB;
00092 int bitDepth = 8;
00093 png_uint_32 width = src->CW();
00094 png_uint_32 height = src->CH();
00095
00096 png_set_IHDR(png, pngInfo, width, height, bitDepth, colorType,
00097 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
00098 PNG_FILTER_TYPE_BASE);
00099 png_write_info(png, pngInfo);
00100
00101 for (int row=0 ; row<src->CH() ; row++)
00102 {
00103 UInt8* dataPtr = src->CPB(0, row);
00104
00105 if (setjmp(gWritePngJmpbuf))
00106 {
00107 ILOG_ERROR("Error writing png data");
00108 return false;
00109 }
00110 png_write_row(png, dataPtr);
00111 }
00112 png_write_end(png, pngInfo);
00113 char* endBuf = (char*) png->io_ptr;
00114 *outSize = (endBuf - buf);
00115 png_destroy_write_struct(&png, &pngInfo);
00116 return true;
00117 }
00118
00119 #else
00120
00121 template <class ArrayT>
00122 inline bool
00123 WritePngToMemory(ArrayT* src, char* buf, size_t memBufSize, size_t* outSize)
00124 {
00125 ILOG_VAR(Impala.Core.Array.WritePngToMemory);
00126 ILOG_ERROR("WritePng not available.");
00127 return false;
00128 }
00129
00130 #endif // PNG_USED
00131
00132 template <class ArrayT>
00133 inline Array2dScalarUInt8*
00134 WritePng(ArrayT* src)
00135 {
00136 Array2dScalarUInt8* res = 0;
00137 size_t bufSize = src->CW() * src->CH() * 3 + 1024;
00138 char* buf = new char[bufSize];
00139 size_t outSize;
00140 if (!WritePngToMemory(src, buf, bufSize, &outSize))
00141 {
00142 delete buf;
00143 return res;
00144 }
00145 res = MakeFromData<Array2dScalarUInt8>((UInt8*) buf, bufSize, 1);
00146 delete buf;
00147 return res;
00148 }
00149
00150 template <class ArrayT>
00151 inline bool
00152 WritePng(ArrayT* src, Util::IOBuffer* buffer)
00153 {
00154 size_t memBufSize = src->CW() * src->CH() * 3 + 1024;
00155 char* buf = new char[memBufSize];
00156 size_t outSize;
00157 if (!WritePngToMemory(src, buf, memBufSize, &outSize))
00158 {
00159 delete buf;
00160 return false;
00161 }
00162 buffer->Write(buf, outSize);
00163 delete buf;
00164 return true;
00165 }
00166
00167 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00168 template <class ArrayT>
00169 inline bool
00170 WritePng(ArrayT* src, String fileName, Util::Database* db)
00171 {
00172 Util::IOBuffer* buf = db->GetIOBuffer(fileName, false, false, "tmp");
00173 if (!buf)
00174 return false;
00175 bool res = WritePng(src, buf);
00176 delete buf;
00177 return res;
00178 }
00179 #endif // REPOSITORY_USED
00180
00181
00182
00183 template <class ArrayT>
00184 inline bool
00185 WritePng(ArrayT* src, Persistency::File file)
00186 {
00187 Util::IOBuffer* buf = file.GetWriteBuffer();
00188 if (!buf)
00189 return false;
00190 bool res = WritePng(src, buf);
00191 delete buf;
00192 return res;
00193 }
00194
00195 }
00196 }
00197 }
00198
00199 #endif