00001
00054 #ifndef INC_MI32_IMAGECACHE_H
00055 #define INC_MI32_IMAGECACHE_H
00056
00057 #ifndef INC_RVC_IMAGE_H
00058 #include <rvc/image.h>
00059 #endif
00060
00061 #ifndef INC_MI32_ERRHANDLER_H
00062 #include <mi32/errhandler.h>
00063 #endif
00064
00065
00068 template <typename _TT> class IMAGECACHE_T {
00069 public:
00070
00072 IMAGECACHE_T (
00073 RVC::IMAGE& image,
00074 const _TT outofbound = 0
00075 ) :
00076 m_Image(image),
00077 m_Band(((image.GetCellType() & (RVC::IMAGE::CELLTYPE_Color)) != 0) ? RVC::IMAGE::GetCompositeBandNum() : 0),
00078 m_OutOfBound(outofbound)
00079 { }
00080
00082 virtual ~IMAGECACHE_T (
00083 ) {}
00084
00086 bool IsOpen (
00087 ) {return m_Image.IsOpen(); }
00088
00089
00091 ERRVALUE Get (
00092 const INT32 line,
00093 const INT32 column,
00094 _TT& value
00095 ) const { return v_Get(line, column, value); }
00096
00098 ERRVALUE Put (
00099 const INT32 line,
00100 const INT32 column,
00101 _TT value
00102 ) { return v_Put(line, column, value); }
00103
00105 ERRVALUE Flush (
00106 ) { return v_Flush(); }
00107
00109 bool IsInside (
00110 const INT32 line,
00111 const INT32 column
00112 ) const {
00113 if (line < 0) return false;
00114 if (column < 0) return false;
00115 if (line >= m_Image.GetNumLines()) return false;
00116 if (column >= m_Image.GetNumColumns()) return false;
00117 return true;
00118 }
00119
00120 protected:
00121
00122 const _TT m_OutOfBound;
00123 const INT32 m_Band;
00124 RVC::IMAGE& m_Image;
00125
00126 private:
00127 #ifndef GENERATING_DOXYGEN_OUTPUT
00128 virtual ERRVALUE v_Get (const INT32 line, const INT32 column, _TT& value) const = 0;
00129 virtual ERRVALUE v_Put (const INT32 line, const INT32 column, _TT value) = 0;
00130 virtual ERRVALUE v_Flush () = 0;
00131 #endif // GENERATING_DOXYGEN_OUTPUT
00132 };
00133
00134
00135
00137 template <typename _TT> class ROLLTILE_T : public IMAGECACHE_T<_TT> {
00138 public:
00139
00141 ROLLTILE_T (
00142 RVC::IMAGE& image,
00143 const _TT outofbound = 0,
00144 const INT32 numLines = 64,
00145 const INT32 numColumns = 64,
00146 const INT32 numTileLines = 3,
00147 const INT32 numTileColumns = 3
00148 ) :
00149 IMAGECACHE_T<_TT>(image, outofbound),
00150 m_NumLines(numLines),
00151 m_NumColumns(numColumns),
00152 m_TileSize(numLines * numColumns),
00153 m_NumTileLines(numTileLines),
00154 m_NumTileColumns(numTileColumns),
00155 m_NumTiles(numTileLines * numTileColumns)
00156 {
00157 if (!Init()) Done();
00158 }
00159
00161 ~ROLLTILE_T (
00162 ) { Done(); }
00163
00164 INT32 GetNumColumnsPerTile (
00165 ) {return m_NumColumns; }
00166
00167 INT32 GetNumLinesPerTile (
00168 ) {return m_NumLines; }
00169
00170 private:
00171 #ifndef GENERATING_DOXYGEN_OUTPUT
00172 template <typename _TTT> struct TILE {
00173
00174 TILE (
00175 ) :
00176 m_Buffer(0),
00177 m_NumColumns(-1),
00178 m_NumLines(-1),
00179 m_Dirty(false),
00180 m_TileColumn(-1),
00181 m_TileLine(-1)
00182 { }
00183
00184 ~TILE (
00185 ) {
00186 }
00187
00188 void Init (
00189 _TTT* buffer,
00190 INT32 numColumns,
00191 INT32 numLines
00192 ) {
00193 m_Buffer = buffer;
00194 m_NumColumns = numColumns;
00195 m_NumLines = numLines;
00196 m_Dirty = false;;
00197 m_TileColumn = -1;
00198 m_TileLine = -1;
00199 return;
00200 }
00201
00202 bool IsDirty (
00203 ) { return m_Dirty; }
00204
00205 ERRVALUE Read (
00206 RVC::IMAGE& image,
00207 const INT32 band,
00208 const INT32 tileLine,
00209 const INT32 tileColumn
00210 ) {
00211 const INT32 line = tileLine * m_NumLines;
00212 const INT32 numlines = MIN(m_NumLines, image.GetNumLines() - line);
00213 const INT32 column = tileColumn * m_NumColumns;
00214 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00215 _TTT *p = m_Buffer;
00216 for (INT32 i = 0, cline = line; i < numlines; ++i, p += m_NumColumns, ++cline) {
00217 ERRVALUE err = image.ReadBand(band, cline, column, p, numcolumns);
00218 if (err < 0) return SetErrPosn(err);
00219 }
00220 m_TileColumn = tileColumn;
00221 m_TileLine = tileLine;
00222 return 0;
00223 }
00224
00225 ERRVALUE Write (
00226 RVC::IMAGE& image,
00227 const INT32 band
00228 ) {
00229 if (!m_Dirty) return 0;
00230 const INT32 line = m_TileLine * m_NumLines;
00231 const INT32 numlines = MIN(m_NumLines, image.GetNumLines() - line);
00232 const INT32 column = m_TileColumn * m_NumColumns;
00233 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00234 _TTT *p = m_Buffer;
00235 for (INT32 i = 0, cline = line; i < numlines; ++i, p += m_NumColumns, ++cline) {
00236 ERRVALUE err = image.WriteBand(band, cline, column, p, numcolumns);
00237 if (err < 0) return SetErrPosn(err);
00238 }
00239 m_Dirty = false;
00240 return 0;
00241 }
00242
00243 _TTT Get (
00244 const INT32 line,
00245 const INT32 column
00246 ) {
00247 return m_Buffer[line * m_NumColumns + column];
00248 }
00249
00250 void Put (
00251 const INT32 line,
00252 const INT32 column,
00253 _TTT value
00254 ) {
00255 m_Buffer[line * m_NumColumns + column] = value;
00256 m_Dirty = true;
00257 }
00258
00259 INT32 GetTileColumn (
00260 ) { return m_TileColumn; }
00261 INT32 GetTileLine (
00262 ) { return m_TileLine; }
00263
00264 _TTT* m_Buffer;
00265 INT32 m_NumColumns;
00266 INT32 m_NumLines;
00267 bool m_Dirty;
00268 INT32 m_TileColumn;
00269 INT32 m_TileLine;
00270
00271 };
00272
00273 ERRVALUE v_Get (
00274 const INT32 line,
00275 const INT32 column,
00276 _TT& value
00277 ) const {
00278 if (!IMAGECACHE_T<_TT>::IsInside(line, column)) { value = IMAGECACHE_T<_TT>::m_OutOfBound; return 0; }
00279 const INT32 lt = line / m_NumLines;
00280 const INT32 ct = column / m_NumColumns;
00281 const INT32 lti = lt % m_NumTileLines;
00282 const INT32 cti = ct % m_NumTileColumns;
00283 TILE<_TT>& tile = m_Tiles[lti * m_NumTileColumns + cti];
00284 if ((tile.GetTileColumn() != ct) || (tile.GetTileLine() != lt)) {
00285 ERRVALUE err = 0;
00286 if (tile.IsDirty()) {
00287 err = tile.Write(IMAGECACHE_T<_TT>::m_Image);
00288 if (err < 0) return SetErrPosn(err);
00289 }
00290 err = tile.Read(IMAGECACHE_T<_TT>::m_Image, lt, ct);
00291 if (err < 0) return SetErrPosn(err);
00292 }
00293 value = tile.Get(line % m_NumLines, column % m_NumColumns);
00294 return 1;
00295 }
00296
00297 ERRVALUE v_Put (
00298 const INT32 line,
00299 const INT32 column,
00300 _TT value
00301 ) {
00302 if (!IMAGECACHE_T<_TT>::IsInside(line, column)) return 0;
00303 const INT32 lt = line / m_NumLines;
00304 const INT32 ct = column / m_NumColumns;
00305 const INT32 lti = lt % m_NumTileLines;
00306 const INT32 cti = ct % m_NumTileColumns;
00307 TILE<_TT>& tile = m_Tiles[lti * m_NumTileColumns + cti];
00308 if ((tile.GetTileColumn() != ct) || (tile.GetTileLine() != lt)) {
00309 ERRVALUE err = 0;
00310 if (tile.IsDirty()) {
00311 err = tile.Write(IMAGECACHE_T<_TT>::m_Image);
00312 if (err < 0) return SetErrPosn(err);
00313 }
00314 err = tile.Read(IMAGECACHE_T<_TT>::m_Image, lt, ct);
00315 if (err < 0) return SetErrPosn(err);
00316 }
00317 tile.Put(line % m_NumLines, column % m_NumColumns, value);
00318 return 1;
00319 }
00320
00321 ERRVALUE v_Flush (
00322 ) {
00323 for (INT32 i = 0; i < m_NumTiles; ++i) {
00324 ERRVALUE err = m_Tiles[i].Write(IMAGECACHE_T<_TT>::m_Image);
00325 if (err < 0) return SetErrPosn(err);
00326 }
00327 return 0;
00328 }
00329
00330 bool Init (
00331 ) {
00332 m_Buffer = new _TT[m_NumTiles * m_TileSize];
00333
00334 ERRVALUE err = m_Tiles.Resize(m_NumTiles);
00335 if (err < 0) return false;
00336
00337 _TT* p = m_Buffer;
00338 for (INT32 i = 0; i < m_NumTiles; ++i, p += m_TileSize) {
00339 m_Tiles[i].Init(p, m_NumColumns, m_NumLines);
00340 }
00341 return true;
00342 }
00343
00344 void Done (
00345 ) {
00346 IMAGECACHE_T<_TT>::Flush();
00347 delete[] m_Buffer;
00348 return;
00349 }
00350
00351 const INT32 m_NumColumns;
00352 const INT32 m_NumLines;
00353 const INT32 m_NumTileColumns;
00354 const INT32 m_NumTileLines;
00355 const INT32 m_NumTiles;
00356 const INT32 m_TileSize;
00357
00358 _TT* m_Buffer;
00359 SIMPLE_ARRAY<TILE<_TT> > m_Tiles;
00360 #endif // GENERATING_DOXYGEN_OUTPUT
00361 };
00362
00363
00364
00366 template <typename _TT> class ROLLSPAN_T : public IMAGECACHE_T<_TT> {
00367 public:
00368
00370 ROLLSPAN_T (
00371 RVC::IMAGE& image,
00372 const _TT outofbound = 0,
00373 const INT32 numColumns = 64,
00374 const INT32 numSpanLines = 192,
00375 const INT32 numSpanColumns = 3
00376 ) :
00377 IMAGECACHE_T<_TT>(image, outofbound),
00378 m_NumColumns(numColumns),
00379 m_SpanSize(numColumns),
00380 m_NumSpanLines(numSpanLines),
00381 m_NumSpanColumns(numSpanColumns),
00382 m_NumSpans(numSpanLines * numSpanColumns)
00383 {
00384 if (!Init()) Done();
00385 }
00386
00388 ~ROLLSPAN_T (
00389 ) { Done(); }
00390
00391 INT32 GetNumColumnsPerSpan (
00392 ) { return m_NumColumns; }
00393
00394 private:
00395 #ifndef GENERATING_DOXYGEN_OUTPUT
00396 template <typename _TTT> struct SPAN {
00397
00398 SPAN (
00399 ) :
00400 m_Buffer(0),
00401 m_NumColumns(-1),
00402 m_Dirty(false),
00403 m_SpanColumn(-1),
00404 m_Line(-1)
00405 { }
00406
00407 ~SPAN (
00408 ) {
00409 }
00410
00411 void Init (
00412 _TTT* buffer,
00413 INT32 numColumns
00414 ) {
00415 m_Buffer = buffer;
00416 m_NumColumns = numColumns;
00417 m_Dirty = false;
00418 m_SpanColumn = -1;
00419 m_Line = -1;
00420 return;
00421 }
00422
00423 bool IsDirty (
00424 ) { return m_Dirty; }
00425
00426 ERRVALUE Read (
00427 RVC::IMAGE& image,
00428 const INT32 band,
00429 const INT32 line,
00430 const INT32 spanColumn
00431 ) {
00432 const INT32 column = spanColumn * m_NumColumns;
00433 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00434 ERRVALUE err = image.ReadBand(band, line, column, m_Buffer, numcolumns);
00435 if (err < 0) return SetErrPosn(err);
00436 m_SpanColumn = spanColumn;
00437 m_Line = line;
00438 return 0;
00439 }
00440
00441 ERRVALUE Write (
00442 RVC::IMAGE& image,
00443 const INT32 band
00444 ) {
00445 if (!m_Dirty) return 0;
00446 const INT32 column = m_SpanColumn * m_NumColumns;
00447 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00448 ERRVALUE err = image.WriteBand(band, m_Line, column, m_Buffer, numcolumns);
00449 if (err < 0) return SetErrPosn(err);
00450 m_Dirty = false;
00451 return 0;
00452 }
00453
00454 _TTT Get (
00455 const INT32 column
00456 ) {
00457 return m_Buffer[column];
00458 }
00459
00460 void Put (
00461 const INT32 column,
00462 _TTT value
00463 ) {
00464 m_Buffer[column] = value;
00465 m_Dirty = true;
00466 }
00467
00468 INT32 GetSpanColumn (
00469 ) { return m_SpanColumn; }
00470
00471 INT32 GetLine (
00472 ) { return m_Line; }
00473
00474 _TTT* m_Buffer;
00475 INT32 m_NumColumns;
00476 bool m_Dirty;
00477 INT32 m_SpanColumn;
00478 INT32 m_Line;
00479
00480 };
00481
00482 ERRVALUE v_Get (
00483 const INT32 line,
00484 const INT32 column,
00485 _TT& value
00486 ) const {
00487 if (!IMAGECACHE_T<_TT>::IsInside(line, column)) { value = IMAGECACHE_T<_TT>::m_OutOfBound; return 0; }
00488
00489 const INT32 cs = column / m_NumColumns;
00490 const INT32 lsi = line % m_NumSpanLines;
00491 const INT32 csi = cs % m_NumSpanColumns;
00492 SPAN<_TT>& span = const_cast<SPAN<_TT>&>(m_Spans[lsi * m_NumSpanColumns + csi]);
00493 if ((span.GetSpanColumn() != cs) || (span.GetLine() != line)) {
00494 ERRVALUE err = 0;
00495 if (span.IsDirty()) {
00496 err = span.Write(IMAGECACHE_T<_TT>::m_Image, IMAGECACHE_T<_TT>::m_Band);
00497 if (err < 0) return SetErrPosn(err);
00498 }
00499 err = span.Read(IMAGECACHE_T<_TT>::m_Image, IMAGECACHE_T<_TT>::m_Band, line, cs);
00500 if (err < 0) return SetErrPosn(err);
00501 }
00502 value = span.Get(column % m_NumColumns);
00503 return 1;
00504 }
00505
00506 ERRVALUE v_Put (
00507 const INT32 line,
00508 const INT32 column,
00509 _TT value
00510 ) {
00511 if (!IMAGECACHE_T<_TT>::IsInside(line, column)) return 0;
00512
00513 const INT32 cs = column / m_NumColumns;
00514 const INT32 lsi = line % m_NumSpanLines;
00515 const INT32 csi = cs % m_NumSpanColumns;
00516 SPAN<_TT>& span = m_Spans[lsi * m_NumSpanColumns + csi];
00517 if ((span.GetSpanColumn() != cs) || (span.GetLine() != line)) {
00518 ERRVALUE err = 0;
00519 if (span.IsDirty()) {
00520 err = span.Write(IMAGECACHE_T<_TT>::m_Image, IMAGECACHE_T<_TT>::m_Band);
00521 if (err < 0) return SetErrPosn(err);
00522 }
00523 err = span.Read(IMAGECACHE_T<_TT>::m_Image, IMAGECACHE_T<_TT>::m_Band, line, cs);
00524 if (err < 0) return SetErrPosn(err);
00525 }
00526 span.Put(column % m_NumColumns, value);
00527 return 1;
00528 }
00529
00530 ERRVALUE v_Flush (
00531 ) {
00532 for (INT32 i = 0; i < m_NumSpans; ++i) {
00533 ERRVALUE err = m_Spans[i].Write(IMAGECACHE_T<_TT>::m_Image, IMAGECACHE_T<_TT>::m_Band);
00534 if (err < 0) return SetErrPosn(err);
00535 }
00536 return 0;
00537 }
00538
00539 bool Init (
00540 ) {
00541 m_Buffer = new _TT[m_NumSpans * m_SpanSize];
00542
00543 ERRVALUE err = m_Spans.Resize(m_NumSpans);
00544 if (err < 0) return false;
00545
00546 _TT* p = m_Buffer;
00547 for (INT32 i = 0; i < m_NumSpans; ++i, p += m_SpanSize) {
00548 m_Spans[i].Init(p, m_NumColumns);
00549 }
00550
00551 return true;
00552 }
00553
00554 void Done (
00555 ) {
00556 IMAGECACHE_T<_TT>::Flush();
00557 delete[] m_Buffer;
00558
00559 return;
00560 }
00561
00562 const INT32 m_NumColumns;
00563 const INT32 m_NumSpanColumns;
00564 const INT32 m_NumSpanLines;
00565 const INT32 m_NumSpans;
00566 const INT32 m_SpanSize;
00567
00568 _TT* m_Buffer;
00569 SIMPLE_ARRAY<SPAN<_TT> > m_Spans;
00570 #endif // GENERATING_DOXYGEN_OUTPUT
00571 };
00572
00573
00576 class IMAGECACHE {
00577 public:
00578
00580 IMAGECACHE (
00581 RVC::IMAGE& image,
00582 const UINT8* outofbound
00583 ) :
00584 m_Image(image),
00585 m_Band(((image.GetCellType() & (RVC::IMAGE::CELLTYPE_Color)) != 0) ? RVC::IMAGE::GetCompositeBandNum() : 0),
00586 m_ConvMode(RVC::IMAGE::GetNumBitsFromCellType(image.GetCellType()) < 8 ? RVC::IMAGE::CONVMODE_INT8 : RVC::IMAGE::CONVMODE_None),
00587 m_NumBytes(static_cast<UINT8>((RVC::IMAGE::GetNumBitsFromCellType(image.GetCellType()) + 7) / 8))
00588 {
00589 memcpy(m_OutOfBound, outofbound, m_NumBytes);
00590 }
00591
00593 virtual ~IMAGECACHE (
00594 ) {}
00595
00597 bool IsOpen (
00598 ) const {return m_Image.IsOpen(); }
00599
00600
00602 ERRVALUE Get (
00603 const INT32 line,
00604 const INT32 column,
00605 UINT8* value
00606 ) const { return v_Get(line, column, value); }
00607
00609 ERRVALUE Put (
00610 const INT32 line,
00611 const INT32 column,
00612 const UINT8* value
00613 ) { return v_Put(line, column, value); }
00614
00616 ERRVALUE Flush (
00617 ) { return v_Flush(); }
00618
00620 bool IsInside (
00621 const INT32 line,
00622 const INT32 column
00623 ) const {
00624 if (line < 0) return false;
00625 if (column < 0) return false;
00626 if (line >= m_Image.GetNumLines()) return false;
00627 if (column >= m_Image.GetNumColumns()) return false;
00628 return true;
00629 }
00630
00631 RVC::IMAGE& GetImage (
00632 ) const { return m_Image; }
00633
00634 protected:
00635
00636 const UINT8 m_NumBytes;
00637 const INT32 m_Band;
00638 const RVC::IMAGE::CONVMODE m_ConvMode;
00639
00640 UINT8 m_OutOfBound[8];
00641 RVC::IMAGE& m_Image;
00642
00643 private:
00644 #ifndef GENERATING_DOXYGEN_OUTPUT
00645 virtual ERRVALUE v_Get (const INT32 line, const INT32 column, UINT8* value) const = 0;
00646 virtual ERRVALUE v_Put (const INT32 line, const INT32 column, const UINT8* value) = 0;
00647 virtual ERRVALUE v_Flush () = 0;
00648 #endif // GENERATING_DOXYGEN_OUTPUT
00649 };
00650
00651
00653 class ROLLTILE : public IMAGECACHE {
00654 public:
00655
00657 ROLLTILE (
00658 RVC::IMAGE& image,
00659 const UINT8* outofbound,
00660 const INT32 numLines = 64,
00661 const INT32 numColumns = 64,
00662 const INT32 numTileLines = 3,
00663 const INT32 numTileColumns = 3
00664 ) :
00665 IMAGECACHE(image, outofbound),
00666 m_NumLines(numLines),
00667 m_NumColumns(numColumns),
00668 m_TileSize(numLines * numColumns),
00669 m_NumTileLines(numTileLines),
00670 m_NumTileColumns(numTileColumns),
00671 m_NumTiles(numTileLines * numTileColumns)
00672 {
00673 if (!Init()) Done();
00674 }
00675
00677 ~ROLLTILE (
00678 ) { Done(); }
00679
00680 INT32 GetNumColumnsPerTile (
00681 ) {return m_NumColumns; }
00682
00683 INT32 GetNumLinesPerTile (
00684 ) {return m_NumLines; }
00685
00686 private:
00687 #ifndef GENERATING_DOXYGEN_OUTPUT
00688 struct TILE {
00689
00690 TILE (
00691 ) :
00692 m_Buffer(0),
00693 m_NumBytes(0),
00694 m_NumColumns(-1),
00695 m_NumLines(-1),
00696 m_Dirty(false),
00697 m_TileColumn(-1),
00698 m_TileLine(-1)
00699 {
00700 }
00701
00702 ~TILE (
00703 ) {
00704 }
00705
00706 void Init (
00707 UINT8* buffer,
00708 UINT8 NumBytes,
00709 INT32 numColumns,
00710 INT32 numLines
00711 ) {
00712 m_Buffer = buffer;
00713 m_NumBytes = NumBytes;
00714 m_NumColumns = numColumns;
00715 m_NumLines = numLines;
00716 m_Dirty = false;;
00717 m_TileColumn = -1;
00718 m_TileLine = -1;
00719 return;
00720 }
00721
00722 bool IsDirty (
00723 ) { return m_Dirty; }
00724
00725 ERRVALUE Read (
00726 RVC::IMAGE& image,
00727 const INT32 band,
00728 const RVC::IMAGE::CONVMODE convmode,
00729 const INT32 tileLine,
00730 const INT32 tileColumn
00731 ) {
00732 const INT32 line = tileLine * m_NumLines;
00733 const INT32 numlines = MIN(m_NumLines, image.GetNumLines() - line);
00734 const INT32 column = tileColumn * m_NumColumns;
00735 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00736 UINT8 *p = m_Buffer;
00737 for (INT32 i = 0, cline = line; i < numlines; ++i, p += m_NumColumns * m_NumBytes, ++cline) {
00738 ERRVALUE err = image.ReadBand(band, cline, column, p, numcolumns, convmode);
00739 if (err < 0) return SetErrPosn(err);
00740 }
00741 m_TileColumn = tileColumn;
00742 m_TileLine = tileLine;
00743 return 0;
00744 }
00745
00746 ERRVALUE Write (
00747 RVC::IMAGE& image,
00748 const INT32 band,
00749 const RVC::IMAGE::CONVMODE convmode
00750 ) {
00751 if (!m_Dirty) return 0;
00752 const INT32 line = m_TileLine * m_NumLines;
00753 const INT32 numlines = MIN(m_NumLines, image.GetNumLines() - line);
00754 const INT32 column = m_TileColumn * m_NumColumns;
00755 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00756 UINT8 *p = m_Buffer;
00757 for (INT32 i = 0, cline = line; i < numlines; ++i, p += m_NumColumns * m_NumBytes, ++cline) {
00758 ERRVALUE err = image.WriteBand(band, cline, column, p, numcolumns, convmode);
00759 if (err < 0) return SetErrPosn(err);
00760 }
00761 m_Dirty = false;
00762 return 0;
00763 }
00764
00765 const UINT8* Get (
00766 const INT32 line,
00767 const INT32 column
00768 ) const {
00769 return &m_Buffer[(line * m_NumColumns + column) * m_NumBytes];
00770 }
00771
00772 void Put (
00773 const INT32 line,
00774 const INT32 column,
00775 const UINT8* value
00776 ) {
00777 memcpy(&m_Buffer[(line * m_NumColumns + column) * m_NumBytes], value, m_NumBytes);
00778 m_Dirty = true;
00779 }
00780
00781 INT32 GetTileColumn (
00782 ) { return m_TileColumn; }
00783
00784 INT32 GetTileLine (
00785 ) { return m_TileLine; }
00786
00787 UINT8* m_Buffer;
00788 UINT8 m_NumBytes;
00789 INT32 m_NumColumns;
00790 INT32 m_NumLines;
00791 bool m_Dirty;
00792 INT32 m_TileColumn;
00793 INT32 m_TileLine;
00794
00795 };
00796
00797 ERRVALUE v_Get (
00798 const INT32 line,
00799 const INT32 column,
00800 UINT8* value
00801 ) const {
00802 if (!IMAGECACHE::IsInside(line, column)) { memcpy(value, IMAGECACHE::m_OutOfBound, m_NumBytes); return 0; }
00803 const INT32 lt = line / m_NumLines;
00804 const INT32 ct = column / m_NumColumns;
00805 const INT32 lti = lt % m_NumTileLines;
00806 const INT32 cti = ct % m_NumTileColumns;
00807 TILE& tile = const_cast<TILE&>(m_Tiles[lti * m_NumTileColumns + cti]);
00808 if ((tile.GetTileColumn() != ct) || (tile.GetTileLine() != lt)) {
00809 ERRVALUE err = 0;
00810 if (tile.IsDirty()) {
00811 err = tile.Write(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode);
00812 if (err < 0) return SetErrPosn(err);
00813 }
00814 err = tile.Read(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode, lt, ct);
00815 if (err < 0) return SetErrPosn(err);
00816 }
00817 memcpy(value, const_cast<UINT8*>(tile.Get(line % m_NumLines, column % m_NumColumns)), m_NumBytes);
00818 return 1;
00819 }
00820
00821 ERRVALUE v_Put (
00822 const INT32 line,
00823 const INT32 column,
00824 const UINT8* value
00825 ) {
00826 if (!IMAGECACHE::IsInside(line, column)) return 0;
00827 const INT32 lt = line / m_NumLines;
00828 const INT32 ct = column / m_NumColumns;
00829 const INT32 lti = lt % m_NumTileLines;
00830 const INT32 cti = ct % m_NumTileColumns;
00831 TILE& tile = m_Tiles[lti * m_NumTileColumns + cti];
00832 if ((tile.GetTileColumn() != ct) || (tile.GetTileLine() != lt)) {
00833 ERRVALUE err = 0;
00834 if (tile.IsDirty()) {
00835 err = tile.Write(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode);
00836 if (err < 0) return SetErrPosn(err);
00837 }
00838 err = tile.Read(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode, lt, ct);
00839 if (err < 0) return SetErrPosn(err);
00840 }
00841 tile.Put(line % m_NumLines, column % m_NumColumns, value);
00842 return 1;
00843 }
00844
00845 ERRVALUE v_Flush (
00846 ) {
00847 for (INT32 i = 0; i < m_NumTiles; ++i) {
00848 ERRVALUE err = m_Tiles[i].Write(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode);
00849 if (err < 0) return SetErrPosn(err);
00850 }
00851 return 0;
00852 }
00853
00854 bool Init (
00855 ) {
00856 m_Buffer = new UINT8[m_NumTiles * m_TileSize * m_NumBytes];
00857
00858 ERRVALUE err = m_Tiles.Resize(m_NumTiles);
00859 if (err < 0) return false;
00860
00861 UINT8* p = m_Buffer;
00862 for (INT32 i = 0; i < m_NumTiles; ++i, p += m_TileSize * m_NumBytes) {
00863 m_Tiles[i].Init(p, m_NumBytes, m_NumColumns, m_NumLines);
00864 }
00865 return true;
00866 }
00867
00868 void Done (
00869 ) {
00870 IMAGECACHE::Flush();
00871 delete[] m_Buffer;
00872 return;
00873 }
00874
00875 const INT32 m_NumColumns;
00876 const INT32 m_NumLines;
00877 const INT32 m_NumTileColumns;
00878 const INT32 m_NumTileLines;
00879 const INT32 m_NumTiles;
00880 const INT32 m_TileSize;
00881
00882 UINT8* m_Buffer;
00883 SIMPLE_ARRAY<TILE> m_Tiles;
00884 #endif // GENERATING_DOXYGEN_OUTPUT
00885 };
00886
00887
00889 class ROLLSPAN : public IMAGECACHE {
00890 public:
00891
00893 ROLLSPAN (
00894 RVC::IMAGE& image,
00895 const UINT8* outofbound,
00896 const INT32 numColumns = 64,
00897 const INT32 numSpanLines = 192,
00898 const INT32 numSpanColumns = 3
00899 ) :
00900 IMAGECACHE(image, outofbound),
00901 m_NumColumns(numColumns),
00902 m_SpanSize(numColumns),
00903 m_NumSpanLines(numSpanLines),
00904 m_NumSpanColumns(numSpanColumns),
00905 m_NumSpans(numSpanLines * numSpanColumns)
00906 {
00907 if (!Init()) Done();
00908 }
00909
00911 ~ROLLSPAN (
00912 ) { Done(); }
00913
00914 INT32 GetNumColumnsPerSpan (
00915 ) { return m_NumColumns; }
00916
00917 private:
00918 #ifndef GENERATING_DOXYGEN_OUTPUT
00919 struct SPAN {
00920
00921 SPAN (
00922 ) :
00923 m_Buffer(0),
00924 m_NumBytes(0),
00925 m_NumColumns(-1),
00926 m_Dirty(false),
00927 m_SpanColumn(-1),
00928 m_Line(-1)
00929 {
00930 }
00931
00932 ~SPAN (
00933 ) {
00934 }
00935
00936 void Init (
00937 UINT8* buffer,
00938 UINT8 NumBytes,
00939 INT32 numColumns
00940 ) {
00941 m_Buffer = buffer;
00942 m_NumBytes = NumBytes;
00943 m_NumColumns = numColumns;
00944 m_Dirty = false;
00945 m_SpanColumn = -1;
00946 m_Line = -1;
00947 return;
00948 }
00949
00950 bool IsDirty (
00951 ) { return m_Dirty; }
00952
00953 ERRVALUE Read (
00954 RVC::IMAGE& image,
00955 const INT32 band,
00956 const RVC::IMAGE::CONVMODE convmode,
00957 const INT32 line,
00958 const INT32 spanColumn
00959 ) {
00960 const INT32 column = spanColumn * m_NumColumns;
00961 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00962 ERRVALUE err = image.ReadBand(band, line, column, m_Buffer, numcolumns, convmode);
00963 if (err < 0) return SetErrPosn(err);
00964 m_SpanColumn = spanColumn;
00965 m_Line = line;
00966 return 0;
00967 }
00968
00969 ERRVALUE Write (
00970 RVC::IMAGE& image,
00971 const INT32 band,
00972 const RVC::IMAGE::CONVMODE convmode
00973 ) {
00974 if (!m_Dirty) return 0;
00975 const INT32 column = m_SpanColumn * m_NumColumns;
00976 const INT32 numcolumns = MIN(m_NumColumns, image.GetNumColumns() - column);
00977 ERRVALUE err = image.WriteBand(band, m_Line, column, m_Buffer, numcolumns, convmode);
00978 if (err < 0) return SetErrPosn(err);
00979 m_Dirty = false;
00980 return 0;
00981 }
00982
00983 UINT8* Get (
00984 const INT32 column
00985 ) {
00986 return &m_Buffer[column * m_NumBytes];
00987 }
00988
00989 void Put (
00990 const INT32 column,
00991 const UINT8* value
00992 ) {
00993 memcpy(&m_Buffer[column * m_NumBytes], value, m_NumBytes);
00994 m_Dirty = true;
00995 }
00996
00997 INT32 GetSpanColumn (
00998 ) { return m_SpanColumn; }
00999
01000 INT32 GetLine (
01001 ) { return m_Line; }
01002
01003 UINT8* m_Buffer;
01004 UINT8 m_NumBytes;
01005 INT32 m_NumColumns;
01006 bool m_Dirty;
01007 INT32 m_SpanColumn;
01008 INT32 m_Line;
01009
01010 };
01011
01012 ERRVALUE v_Get (
01013 const INT32 line,
01014 const INT32 column,
01015 UINT8* value
01016 ) const {
01017 if (!IMAGECACHE::IsInside(line, column)) { memcpy(value, IMAGECACHE::m_OutOfBound, m_NumBytes); return 0; }
01018
01019 const INT32 cs = column / m_NumColumns;
01020 const INT32 lsi = line % m_NumSpanLines;
01021 const INT32 csi = cs % m_NumSpanColumns;
01022 SPAN& span = const_cast<SPAN&>(m_Spans[lsi * m_NumSpanColumns + csi]);
01023 if ((span.GetSpanColumn() != cs) || (span.GetLine() != line)) {
01024 ERRVALUE err = 0;
01025 if (span.IsDirty()) {
01026 err = span.Write(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode);
01027 if (err < 0) return SetErrPosn(err);
01028 }
01029 err = span.Read(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode, line, cs);
01030 if (err < 0) return SetErrPosn(err);
01031 }
01032 memcpy(value, span.Get(column % m_NumColumns), m_NumBytes);
01033 return 1;
01034 }
01035
01036 ERRVALUE v_Put (
01037 const INT32 line,
01038 const INT32 column,
01039 const UINT8* value
01040 ) {
01041 if (!IMAGECACHE::IsInside(line, column)) return 0;
01042
01043 const INT32 cs = column / m_NumColumns;
01044 const INT32 lsi = line % m_NumSpanLines;
01045 const INT32 csi = cs % m_NumSpanColumns;
01046 SPAN& span = m_Spans[lsi * m_NumSpanColumns + csi];
01047 if ((span.GetSpanColumn() != cs) || (span.GetLine() != line)) {
01048 ERRVALUE err = 0;
01049 if (span.IsDirty()) {
01050 err = span.Write(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode);
01051 if (err < 0) return SetErrPosn(err);
01052 }
01053 err = span.Read(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode, line, cs);
01054 if (err < 0) return SetErrPosn(err);
01055 }
01056 span.Put(column % m_NumColumns, value);
01057 return 1;
01058 }
01059
01060 ERRVALUE v_Flush (
01061 ) {
01062 for (INT32 i = 0; i < m_NumSpans; ++i) {
01063 ERRVALUE err = m_Spans[i].Write(IMAGECACHE::m_Image, IMAGECACHE::m_Band, IMAGECACHE::m_ConvMode);
01064 if (err < 0) return SetErrPosn(err);
01065 }
01066 return 0;
01067 }
01068
01069 bool Init (
01070 ) {
01071 m_Buffer = new UINT8[m_NumSpans * m_SpanSize * m_NumBytes];
01072
01073 ERRVALUE err = m_Spans.Resize(m_NumSpans);
01074 if (err < 0) return false;
01075
01076 UINT8* p = m_Buffer;
01077 for (INT32 i = 0; i < m_NumSpans; ++i, p += m_SpanSize * m_NumBytes) {
01078 m_Spans[i].Init(p, m_NumBytes, m_NumColumns);
01079 }
01080
01081 return true;
01082 }
01083
01084 void Done (
01085 ) {
01086 IMAGECACHE::Flush();
01087 delete[] m_Buffer;
01088
01089 return;
01090 }
01091
01092 const INT32 m_NumColumns;
01093 const INT32 m_NumSpanColumns;
01094 const INT32 m_NumSpanLines;
01095 const INT32 m_NumSpans;
01096 const INT32 m_SpanSize;
01097
01098 UINT8* m_Buffer;
01099 SIMPLE_ARRAY<SPAN> m_Spans;
01100 #endif // GENERATING_DOXYGEN_OUTPUT
01101 };
01102
01103
01104
01105 #endif // INC_MI32_IMAGECACHE_H