00001 #ifndef Impala_Core_Array_ImageArchiveFileFset_h
00002 #define Impala_Core_Array_ImageArchiveFileFset_h
00003
00004 #include "Persistency/File.h"
00005 #include "Core/Array/ImageArchive.h"
00006 #include "Core/Array/ReadImage.h"
00007
00008 namespace Impala
00009 {
00010 namespace Core
00011 {
00012 namespace Array
00013 {
00014
00015
00016 class ImageArchiveFileFset : public ImageArchive
00017 {
00018 public:
00019
00020 ImageArchiveFileFset(Persistency::File file)
00021 {
00022 mIOBuffer = 0;
00023 mFirstSegment = 0;
00024
00025 if (!file.Valid())
00026 {
00027 ILOG_ERROR("Invalid file");
00028 return;
00029 }
00030
00031 mIOBuffer = file.GetReadBuffer();
00032 if (!mIOBuffer)
00033 return;
00034
00035 int bufSize = mIOBuffer->Size();
00036 int headerPos = bufSize - 16;
00037 char header[16];
00038 mIOBuffer->SetPosition(headerPos);
00039 mIOBuffer->Read(header, 16);
00040 if ((header[0] != 'M') || (header[1] != 'A') || (header[2] != 'S')
00041 || (header[3] != 'S') || (header[8] != 'S') || (header[9] != 'T')
00042 || (header[10] != 'R') || (header[11] != 'E'))
00043 {
00044 ILOG_ERROR("no magic header");
00045 }
00046 int nrEntries = GetIntFromChars(header, 4);
00047 int tabPos = bufSize - 16 - (12 * nrEntries);
00048 char* segmentTab = new char[12 * nrEntries];
00049 mIOBuffer->SetPosition(tabPos);
00050 mIOBuffer->Read(segmentTab, 12 * nrEntries);
00051
00052 int offset = 0;
00053 for (int i=0 ; i<nrEntries ; i++)
00054 {
00055 int segId = GetIntFromChars(segmentTab, i*12);
00056 mSegmentId.push_back(segId);
00057
00058 int segLen = GetIntFromChars(segmentTab, i*12 + 4);
00059 mSegmentLength.push_back(segLen);
00060
00061 int compressed = GetIntFromChars(segmentTab, i*12 + 8);
00062 mCompressed.push_back(compressed);
00063
00064 mFileOffset.push_back(offset);
00065 offset += segLen - compressed;
00066 }
00067
00068 mFirstSegment = GetSegmentBuf(0);
00069
00070 delete segmentTab;
00071 }
00072
00073 virtual
00074 ~ImageArchiveFileFset()
00075 {
00076 if (mIOBuffer)
00077 delete mIOBuffer;
00078 if (mFirstSegment)
00079 delete mFirstSegment;
00080 }
00081
00082 bool
00083 Valid()
00084 {
00085 return (mIOBuffer != 0) && (mFileOffset.size() != 0);
00086 }
00087
00088 int
00089 NrImages()
00090 {
00091 return mFileOffset.size();
00092 }
00093
00094 Array2dVec3UInt8*
00095 ReadImage(int idx)
00096 {
00097 if (!Valid())
00098 {
00099 ILOG_ERROR("Cannot ReadImage: archive not valid");
00100 return 0;
00101 }
00102
00103 Array2dVec3UInt8* im = 0;
00104 char* data = GetSegmentBuf(idx);
00105 ReadImageFromMemory(im, data, mSegmentLength[idx]);
00106 delete data;
00107
00108 return im;
00109 }
00110
00111 private:
00112
00113 int
00114 GetIntFromChars(char* buf, int pos)
00115 {
00116 int a0 = buf[pos + 0] & 0xff;
00117 int a1 = buf[pos + 1] & 0xff;
00118 int a2 = buf[pos + 2] & 0xff;
00119 int a3 = buf[pos + 3] & 0xff;
00120 int res = a0 << 24 | a1 << 16 | a2 << 8 | a3;
00121 return res;
00122 }
00123
00124 char*
00125 GetSegmentBuf(int idx)
00126 {
00127 int segLen = mSegmentLength[idx];
00128 char* res = new char[segLen];
00129 int compressed = mCompressed[idx];
00130 if (compressed > 0)
00131 memcpy(res, mFirstSegment, compressed);
00132 int remainder = segLen - compressed;
00133 if (remainder > 0)
00134 {
00135 int off = mFileOffset[idx];
00136 mIOBuffer->SetPosition(off);
00137 mIOBuffer->Read(res + compressed, remainder);
00138 }
00139 return res;
00140 }
00141
00142
00143 Util::IOBuffer* mIOBuffer;
00144 std::vector<int> mSegmentId;
00145 std::vector<int> mSegmentLength;
00146 std::vector<int> mCompressed;
00147 std::vector<int> mFileOffset;
00148 char* mFirstSegment;
00149
00150 ILOG_VAR_DEC;
00151 };
00152
00153 ILOG_VAR_INIT(ImageArchiveFileFset, Impala.Core.Array);
00154
00155 }
00156 }
00157 }
00158
00159 #endif