00001 #ifndef Impala_Core_Array_ReadJpg_h
00002 #define Impala_Core_Array_ReadJpg_h
00003
00004 #include <string>
00005 #include "Basis/Timer.h"
00006 #include "Persistency/File.h"
00007 #include "Core/Array/Arrays.h"
00008 #ifdef JPG_USED
00009 #include "Link/Jpeg/CxJpegLink.h"
00010 #endif
00011
00012 namespace Impala
00013 {
00014 namespace Core
00015 {
00016 namespace Array
00017 {
00018
00019
00020 inline void
00021 ReadJpgFromMemory(Array2dScalarInt32*& dst, char *buf, int bufsize)
00022 {
00023 ILOG_VAR(Impala.Core.Array.ReadJpgFromMemory);
00024 ILOG_ERROR("ReadJpgFromMemory: array type not supported");
00025 }
00026
00027 inline void
00028 ReadJpgFromMemory(Array2dScalarReal64*& dst, char *buf, int bufsize)
00029 {
00030 ILOG_VAR(Impala.Core.Array.ReadJpgFromMemory);
00031 ILOG_ERROR("ReadJpgFromMemory: array type not supported");
00032 }
00033
00034 inline void
00035 ReadJpgFromMemory(Array2dVec3Real64*& dst, char *buf, int bufsize)
00036 {
00037 ILOG_VAR(Impala.Core.Array.ReadJpgFromMemory);
00038 ILOG_ERROR("ReadJpgFromMemory: array type not supported");
00039 }
00040
00041 #ifdef JPG_USED
00042
00043 static jmp_buf gReadJpgJmpbuf;
00044 static char gJpgErrorBuffer[JMSG_LENGTH_MAX];
00045
00046 static inline void
00047 JpgLinkErrorFunc(j_common_ptr cinfo)
00048 {
00049
00050 (*cinfo->err->format_message) (cinfo, gJpgErrorBuffer);
00051 longjmp(gReadJpgJmpbuf, 1);
00052 }
00053
00054 String
00055 JpgColorSpace2String(J_COLOR_SPACE cSpace)
00056 {
00057 switch (cSpace)
00058 {
00059 case JCS_UNKNOWN: return "JCS_UNKNOWN";
00060 case JCS_GRAYSCALE: return "JCS_GRAYSCALE";
00061 case JCS_RGB: return "JCS_RGB";
00062 case JCS_YCbCr: return "JCS_YCbCr";
00063 case JCS_CMYK: return "JCS_CMYK";
00064 case JCS_YCCK: return "JCS_YCCK";
00065 }
00066 return "NO_JCS_VALUE";
00067 }
00068
00069 template <class ArrayT>
00070 inline void
00071 ReadJpgFromMemory(ArrayT*& dst, char *buf, int bufsize)
00072 {
00073 ILOG_VAR(Impala.Core.Array.ReadJpgFromMemory);
00074 struct jpeg_decompress_struct cinfo;
00075 struct jpeg_error_mgr pub;
00076 cinfo.err = jpeg_std_error(&pub);
00077 pub.error_exit = JpgLinkErrorFunc;
00078 sprintf(gJpgErrorBuffer, "Something is wrong");
00079 if (setjmp(gReadJpgJmpbuf))
00080 {
00081
00082 ILOG_WARN("jmp: " << String(gJpgErrorBuffer));
00083 jpeg_destroy_decompress(&cinfo);
00084 return;
00085 }
00086 jpeg_create_decompress(&cinfo);
00087 jpeg_memory_src(&cinfo, (const JOCTET *)buf, bufsize);
00088 jpeg_read_header(&cinfo, TRUE);
00089
00090 if (cinfo.num_components == 4)
00091 cinfo.out_color_space = JCS_CMYK;
00092 jpeg_calc_output_dimensions(&cinfo);
00093 jpeg_start_decompress(&cinfo);
00094
00095 ILOG_DEBUG("color_space = " << JpgColorSpace2String(cinfo.jpeg_color_space));
00096 ILOG_DEBUG("MAXJSAMPLE = " << MAXJSAMPLE);
00097 ILOG_DEBUG("CENTERJSAMPLE = " << CENTERJSAMPLE);
00098
00099 if ((cinfo.num_components == 4) && (!cinfo.saw_Adobe_marker))
00100 ILOG_WARN("Never tested non-inverted CMYK format");
00101
00102 int width = cinfo.output_width;
00103 int height = cinfo.output_height;
00104 int row_stride = cinfo.output_width * cinfo.output_components;
00105 bool gray = (cinfo.output_components == 1) ? true : false;
00106 UInt8* c4Buf = (cinfo.output_components == 4) ? new UInt8[row_stride] : 0;
00107 if (dst == 0)
00108 dst = ArrayCreate<ArrayT>(width, height);
00109
00110 while (cinfo.output_scanline < cinfo.output_height)
00111 {
00112 UInt8* dataPtr = dst->CPB(0, cinfo.output_scanline);
00113 UInt8* bufPtr = (c4Buf) ? c4Buf : dataPtr;
00114 int nrRead = jpeg_read_scanlines(&cinfo, &bufPtr, 1);
00115 if (nrRead != 1)
00116 ILOG_ERROR("jpeg_read_scanlines couldn't read line");
00117 if (c4Buf)
00118 {
00119 if (cinfo.saw_Adobe_marker)
00120 {
00121 for (int i=0 ; i<width ; i++)
00122 {
00123 int k = 255 - bufPtr[3];
00124
00125 int val = bufPtr[0] - k;
00126 dataPtr[0] = (val < 0) ? 0 : val;
00127 val = bufPtr[1] - k;
00128 dataPtr[1] = (val < 0) ? 0 : val;
00129 val = bufPtr[2] - k;
00130 dataPtr[2] = (val < 0) ? 0 : val;
00131
00132 dataPtr += 3;
00133 bufPtr += 4;
00134 }
00135 }
00136 else
00137 {
00138 for (int i=0 ; i<width ; i++)
00139 {
00140 int k = 255 - bufPtr[3];
00141
00142 int val = k - bufPtr[0];
00143 dataPtr[0] = (val < 0) ? 0 : val;
00144 val = k - bufPtr[1];
00145 dataPtr[1] = (val < 0) ? 0 : val;
00146 val = k - bufPtr[2];
00147 dataPtr[2] = (val < 0) ? 0 : val;
00148
00149 dataPtr += 3;
00150 bufPtr += 4;
00151 }
00152 }
00153 }
00154 if (gray)
00155 {
00156 UInt8* endLine = dataPtr + width * 3 - 1;
00157 UInt8* endData = dataPtr + width - 1;
00158 for (int i=0 ; i<width ; i++)
00159 {
00160 *endLine-- = *endData;
00161 *endLine-- = *endData;
00162 *endLine-- = *endData--;
00163 }
00164 }
00165 }
00166 if (c4Buf)
00167 delete c4Buf;
00168 jpeg_finish_decompress(&cinfo);
00169 jpeg_destroy_decompress(&cinfo);
00170 }
00171
00172 #else
00173
00174 template <class ArrayT>
00175 inline void
00176 ReadJpgFromMemory(ArrayT*& dst, char *buf, int bufsize)
00177 {
00178 ILOG_VAR(Impala.Core.Array.ReadJpgFromMemory);
00179 ILOG_ERROR("ReadJpg is not available");
00180 }
00181
00182 #endif // JPG_USED
00183
00184 template <class ArrayT>
00185 inline void
00186 ReadJpg(ArrayT*& dst, Util::IOBuffer* buffer)
00187 {
00188 ILOG_VAR(Impala.Core.Array.ReadJpg);
00189 size_t memBufSize = buffer->Size();
00190 char* buf = new char[memBufSize];
00191 size_t nrRead = buffer->Read(buf, memBufSize);
00192 if (nrRead != memBufSize)
00193 {
00194 ILOG_ERROR("Buffer read failed");
00195 delete buf;
00196 return;
00197 }
00198 ReadJpgFromMemory(dst, buf, memBufSize);
00199 delete buf;
00200 }
00201
00202 #ifndef REPOSITORY_USED // Here comes the deprecated stuff
00203
00204 template <class ArrayT>
00205 inline void
00206 ReadJpg(ArrayT*& dst, String fileName, Util::Database* db)
00207 {
00208 Util::IOBuffer* buf = db->GetIOBuffer(fileName, true, false, "");
00209 if (buf)
00210 {
00211 ReadJpg(dst, buf);
00212 delete buf;
00213 }
00214 }
00215 #endif // REPOSITORY_USED
00216
00217
00218 template <class ArrayT>
00219 inline void
00220 ReadJpg(ArrayT*& dst, Persistency::File file)
00221 {
00222 Util::IOBuffer* buf = file.GetReadBuffer();
00223 if (buf)
00224 {
00225 ReadJpg(dst, buf);
00226 delete buf;
00227 }
00228 }
00229
00230 }
00231 }
00232 }
00233
00234 #endif