00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00028
00029 #include "PGFimage.h"
00030 #include "Decoder.h"
00031 #include "Encoder.h"
00032 #include <cmath>
00033 #include <cstring>
00034
00035 #define YUVoffset4 8 // 2^3
00036 #define YUVoffset6 32 // 2^5
00037 #define YUVoffset8 128 // 2^7
00038 #define YUVoffset16 32768 // 2^15
00039
00040
00042
00043 #ifdef NEXCEPTIONS
00044 OSError _PGF_Error_;
00045
00046 OSError GetLastPGFError() {
00047 OSError tmp = _PGF_Error_;
00048 _PGF_Error_ = NoError;
00049 return tmp;
00050 }
00051 #endif
00052
00054
00055 CPGFImage::CPGFImage()
00056 : m_decoder(0)
00057 , m_encoder(0)
00058 , m_levelLength(0)
00059 , m_currentLevel(0)
00060 , m_quant(0)
00061 , m_userDataPos(0)
00062 , m_downsample(false)
00063 , m_favorSpeedOverSize(false)
00064 , m_useOMPinEncoder(true)
00065 , m_useOMPinDecoder(true)
00066 , m_skipUserData(false)
00067 #ifdef __PGFROISUPPORT__
00068 , m_streamReinitialized(false)
00069 #endif
00070 , m_cb(0)
00071 , m_cbArg(0)
00072 , m_progressMode(PM_Relative)
00073 , m_percent(0)
00074 {
00075
00076
00077 memcpy(m_preHeader.magic, PGFMagic, 3);
00078 m_preHeader.version = PGFVersion;
00079 m_preHeader.hSize = 0;
00080
00081
00082 m_postHeader.userData = 0;
00083 m_postHeader.userDataLen = 0;
00084
00085
00086 for (int i=0; i < MaxChannels; i++) {
00087 m_channel[i] = 0;
00088 m_wtChannel[i] = 0;
00089 }
00090
00091
00092 m_width[0] = 0;
00093 m_height[0] = 0;
00094 }
00095
00097
00098 CPGFImage::~CPGFImage() {
00099 Destroy();
00100 }
00101
00103
00104
00105 void CPGFImage::Destroy() {
00106 Close();
00107
00108 for (int i=0; i < m_header.channels; i++) {
00109 delete m_wtChannel[i]; m_wtChannel[i]=0;
00110 m_channel[i] = 0;
00111 }
00112 delete[] m_postHeader.userData; m_postHeader.userData = 0; m_postHeader.userDataLen = 0;
00113 delete[] m_levelLength; m_levelLength = 0;
00114 delete m_encoder; m_encoder = NULL;
00115
00116 m_userDataPos = 0;
00117 }
00118
00120
00121
00122 void CPGFImage::Close() {
00123 delete m_decoder; m_decoder = 0;
00124 }
00125
00127
00128
00129
00130
00131 void CPGFImage::Open(CPGFStream *stream) THROW_ {
00132 ASSERT(stream);
00133
00134
00135 m_decoder = new CDecoder(stream, m_preHeader, m_header, m_postHeader, m_levelLength,
00136 m_userDataPos, m_useOMPinDecoder, m_skipUserData);
00137
00138 if (m_header.nLevels > MaxLevel) ReturnWithError(FormatCannotRead);
00139
00140
00141 m_currentLevel = m_header.nLevels;
00142
00143
00144 m_width[0] = m_header.width;
00145 m_height[0] = m_header.height;
00146
00147
00148 if (!CompleteHeader()) ReturnWithError(FormatCannotRead);
00149
00150
00151 if (m_header.quality > DownsampleThreshold &&
00152 (m_header.mode == ImageModeRGBColor ||
00153 m_header.mode == ImageModeRGBA ||
00154 m_header.mode == ImageModeRGB48 ||
00155 m_header.mode == ImageModeCMYKColor ||
00156 m_header.mode == ImageModeCMYK64 ||
00157 m_header.mode == ImageModeLabColor ||
00158 m_header.mode == ImageModeLab48)) {
00159 m_downsample = true;
00160 m_quant = m_header.quality - 1;
00161 } else {
00162 m_downsample = false;
00163 m_quant = m_header.quality;
00164 }
00165
00166
00167 if (m_downsample) {
00168 for (int i=1; i < m_header.channels; i++) {
00169 m_width[i] = (m_width[0] + 1)/2;
00170 m_height[i] = (m_height[0] + 1)/2;
00171 }
00172 } else {
00173 for (int i=1; i < m_header.channels; i++) {
00174 m_width[i] = m_width[0];
00175 m_height[i] = m_height[0];
00176 }
00177 }
00178
00179 if (m_header.nLevels > 0) {
00180
00181 for (int i=0; i < m_header.channels; i++) {
00182 m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels);
00183 }
00184
00185
00186 m_percent = pow(0.25, m_header.nLevels);
00187
00188 } else {
00189
00190
00191
00192 for (int c=0; c < m_header.channels; c++) {
00193 const UINT32 size = m_width[c]*m_height[c];
00194 m_channel[c] = new(std::nothrow) DataT[size];
00195 if (!m_channel[c]) ReturnWithError(InsufficientMemory);
00196
00197
00198 for (UINT32 i=0; i < size; i++) {
00199 int count = DataTSize;
00200 stream->Read(&count, &m_channel[c][i]);
00201 if (count != DataTSize) ReturnWithError(MissingData);
00202 }
00203 }
00204 }
00205 }
00206
00208 bool CPGFImage::CompleteHeader() {
00209 if (m_header.mode == ImageModeUnknown) {
00210
00211 switch(m_header.bpp) {
00212 case 1: m_header.mode = ImageModeBitmap; break;
00213 case 8: m_header.mode = ImageModeGrayScale; break;
00214 case 12: m_header.mode = ImageModeRGB12; break;
00215 case 16: m_header.mode = ImageModeRGB16; break;
00216 case 24: m_header.mode = ImageModeRGBColor; break;
00217 case 32: m_header.mode = ImageModeRGBA; break;
00218 case 48: m_header.mode = ImageModeRGB48; break;
00219 default: m_header.mode = ImageModeRGBColor; break;
00220 }
00221 }
00222 if (!m_header.bpp) {
00223
00224 switch(m_header.mode) {
00225 case ImageModeBitmap:
00226 m_header.bpp = 1;
00227 break;
00228 case ImageModeIndexedColor:
00229 case ImageModeGrayScale:
00230 m_header.bpp = 8;
00231 break;
00232 case ImageModeRGB12:
00233 m_header.bpp = 12;
00234 break;
00235 case ImageModeRGB16:
00236 case ImageModeGray16:
00237 m_header.bpp = 16;
00238 break;
00239 case ImageModeRGBColor:
00240 case ImageModeLabColor:
00241 m_header.bpp = 24;
00242 break;
00243 case ImageModeRGBA:
00244 case ImageModeCMYKColor:
00245 case ImageModeGray32:
00246 m_header.bpp = 32;
00247 break;
00248 case ImageModeRGB48:
00249 case ImageModeLab48:
00250 m_header.bpp = 48;
00251 break;
00252 case ImageModeCMYK64:
00253 m_header.bpp = 64;
00254 break;
00255 default:
00256 ASSERT(false);
00257 m_header.bpp = 24;
00258 }
00259 }
00260 if (m_header.mode == ImageModeRGBColor && m_header.bpp == 32) {
00261
00262 m_header.mode = ImageModeRGBA;
00263 }
00264 if (m_header.mode == ImageModeBitmap && m_header.bpp != 1) return false;
00265 if (m_header.mode == ImageModeIndexedColor && m_header.bpp != 8) return false;
00266 if (m_header.mode == ImageModeGrayScale && m_header.bpp != 8) return false;
00267 if (m_header.mode == ImageModeGray16 && m_header.bpp != 16) return false;
00268 if (m_header.mode == ImageModeGray32 && m_header.bpp != 32) return false;
00269 if (m_header.mode == ImageModeRGBColor && m_header.bpp != 24) return false;
00270 if (m_header.mode == ImageModeRGBA && m_header.bpp != 32) return false;
00271 if (m_header.mode == ImageModeRGB12 && m_header.bpp != 12) return false;
00272 if (m_header.mode == ImageModeRGB16 && m_header.bpp != 16) return false;
00273 if (m_header.mode == ImageModeRGB48 && m_header.bpp != 48) return false;
00274 if (m_header.mode == ImageModeLabColor && m_header.bpp != 24) return false;
00275 if (m_header.mode == ImageModeLab48 && m_header.bpp != 48) return false;
00276 if (m_header.mode == ImageModeCMYKColor && m_header.bpp != 32) return false;
00277 if (m_header.mode == ImageModeCMYK64 && m_header.bpp != 64) return false;
00278
00279
00280 if (!m_header.channels) {
00281 switch(m_header.mode) {
00282 case ImageModeBitmap:
00283 case ImageModeIndexedColor:
00284 case ImageModeGrayScale:
00285 case ImageModeGray16:
00286 case ImageModeGray32:
00287 m_header.channels = 1;
00288 break;
00289 case ImageModeRGBColor:
00290 case ImageModeRGB12:
00291 case ImageModeRGB16:
00292 case ImageModeRGB48:
00293 case ImageModeLabColor:
00294 case ImageModeLab48:
00295 m_header.channels = 3;
00296 break;
00297 case ImageModeRGBA:
00298 case ImageModeCMYKColor:
00299 case ImageModeCMYK64:
00300 m_header.channels = 4;
00301 break;
00302 default:
00303 return false;
00304 }
00305 }
00306
00307
00308 UINT8 bpc = m_header.bpp/m_header.channels;
00309 if (bpc > 31) bpc = 31;
00310 if (!m_header.usedBitsPerChannel || m_header.usedBitsPerChannel > bpc) {
00311 m_header.usedBitsPerChannel = bpc;
00312 }
00313
00314 return true;
00315 }
00316
00322 const UINT8* CPGFImage::GetUserData(UINT32& size) const {
00323 size = m_postHeader.userDataLen;
00324 return m_postHeader.userData;
00325 }
00326
00332 void CPGFImage::Reconstruct(int level ) THROW_ {
00333 if (m_header.nLevels == 0) {
00334
00335 if (level == 0) {
00336 for (int i=0; i < m_header.channels; i++) {
00337 ASSERT(m_wtChannel[i]);
00338 m_channel[i] = m_wtChannel[i]->GetSubband(0, LL)->GetBuffer();
00339 }
00340 }
00341 } else {
00342 int currentLevel = m_header.nLevels;
00343
00344 if (ROIisSupported()) {
00345
00346 SetROI(PGFRect(0, 0, m_header.width, m_header.height));
00347 }
00348
00349 while (currentLevel > level) {
00350 for (int i=0; i < m_header.channels; i++) {
00351 ASSERT(m_wtChannel[i]);
00352
00353 if (currentLevel == m_header.nLevels) {
00354
00355 m_wtChannel[i]->GetSubband(currentLevel, LL)->Dequantize(m_quant);
00356 }
00357 m_wtChannel[i]->GetSubband(currentLevel, HL)->Dequantize(m_quant);
00358 m_wtChannel[i]->GetSubband(currentLevel, LH)->Dequantize(m_quant);
00359 m_wtChannel[i]->GetSubband(currentLevel, HH)->Dequantize(m_quant);
00360
00361
00362 OSError err = m_wtChannel[i]->InverseTransform(currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
00363 if (err != NoError) ReturnWithError(err);
00364 ASSERT(m_channel[i]);
00365 }
00366
00367 currentLevel--;
00368 }
00369 }
00370 }
00371
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 void CPGFImage::Read(int level , CallbackPtr cb , void *data ) THROW_ {
00385 ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0);
00386 ASSERT(m_decoder);
00387
00388 #ifdef __PGFROISUPPORT__
00389 if (ROIisSupported() && m_header.nLevels > 0) {
00390
00391 PGFRect rect(0, 0, m_header.width, m_header.height);
00392 Read(rect, level, cb, data);
00393 return;
00394 }
00395 #endif
00396
00397 if (m_header.nLevels == 0) {
00398 if (level == 0) {
00399
00400
00401 if (cb) {
00402 if ((*cb)(1.0, true, data)) ReturnWithError(EscapePressed);
00403 }
00404 }
00405 } else {
00406 const int levelDiff = m_currentLevel - level;
00407 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
00408
00409
00410 while (m_currentLevel > level) {
00411 for (int i=0; i < m_header.channels; i++) {
00412 ASSERT(m_wtChannel[i]);
00413
00414 if (m_currentLevel == m_header.nLevels) {
00415
00416 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
00417 }
00418 if (m_preHeader.version & Version5) {
00419
00420 m_wtChannel[i]->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant);
00421 m_wtChannel[i]->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant);
00422 } else {
00423
00424 m_decoder->DecodeInterleaved(m_wtChannel[i], m_currentLevel, m_quant);
00425 }
00426 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant);
00427 }
00428
00429 volatile OSError error = NoError;
00430 #ifdef LIBPGF_USE_OPENMP
00431 #pragma omp parallel for default(shared)
00432 #endif
00433 for (int i=0; i < m_header.channels; i++) {
00434
00435 if (error == NoError) {
00436 OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
00437 if (err != NoError) error = err;
00438 }
00439 ASSERT(m_channel[i]);
00440 }
00441 if (error != NoError) ReturnWithError(error);
00442
00443
00444 m_currentLevel--;
00445
00446
00447 if (m_cb) m_cb(m_cbArg);
00448
00449
00450 if (cb) {
00451 percent *= 4;
00452 if (m_progressMode == PM_Absolute) m_percent = percent;
00453 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
00454 }
00455 }
00456 }
00457
00458
00459 if (m_currentLevel == 0) Close();
00460 }
00461
00462 #ifdef __PGFROISUPPORT__
00472 void CPGFImage::Read(PGFRect& rect, int level , CallbackPtr cb , void *data ) THROW_ {
00473 ASSERT((level >= 0 && level < m_header.nLevels) || m_header.nLevels == 0);
00474 ASSERT(m_decoder);
00475
00476 if (m_header.nLevels == 0 || !ROIisSupported()) {
00477 rect.left = rect.top = 0;
00478 rect.right = m_header.width; rect.bottom = m_header.height;
00479 Read(level, cb, data);
00480 } else {
00481 ASSERT(ROIisSupported());
00482
00483 ASSERT(rect.left < m_header.width && rect.top < m_header.height);
00484
00485 const int levelDiff = m_currentLevel - level;
00486 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
00487
00488
00489 if (levelDiff <= 0) {
00490
00491 m_currentLevel = m_header.nLevels;
00492 m_decoder->SetStreamPosToData();
00493 }
00494
00495
00496 if (rect.right == 0 || rect.right > m_header.width) rect.right = m_header.width;
00497 if (rect.bottom == 0 || rect.bottom > m_header.height) rect.bottom = m_header.height;
00498
00499
00500 SetROI(rect);
00501
00502 while (m_currentLevel > level) {
00503 for (int i=0; i < m_header.channels; i++) {
00504 ASSERT(m_wtChannel[i]);
00505
00506
00507 const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
00508 const PGFRect& tileIndices = m_wtChannel[i]->GetTileIndices(m_currentLevel);
00509
00510
00511 if (m_currentLevel == m_header.nLevels) {
00512 ASSERT(nTiles == 1);
00513 m_decoder->DecodeTileBuffer();
00514 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->PlaceTile(*m_decoder, m_quant);
00515 }
00516 for (UINT32 tileY=0; tileY < nTiles; tileY++) {
00517 for (UINT32 tileX=0; tileX < nTiles; tileX++) {
00518
00519 if (tileIndices.IsInside(tileX, tileY)) {
00520 m_decoder->DecodeTileBuffer();
00521 m_wtChannel[i]->GetSubband(m_currentLevel, HL)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
00522 m_wtChannel[i]->GetSubband(m_currentLevel, LH)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
00523 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->PlaceTile(*m_decoder, m_quant, true, tileX, tileY);
00524 } else {
00525
00526 m_decoder->SkipTileBuffer();
00527 }
00528 }
00529 }
00530 }
00531
00532 volatile OSError error = NoError;
00533 #ifdef LIBPGF_USE_OPENMP
00534 #pragma omp parallel for default(shared)
00535 #endif
00536 for (int i=0; i < m_header.channels; i++) {
00537
00538 if (error == NoError) {
00539 OSError err = m_wtChannel[i]->InverseTransform(m_currentLevel, &m_width[i], &m_height[i], &m_channel[i]);
00540 if (err != NoError) error = err;
00541 }
00542 ASSERT(m_channel[i]);
00543 }
00544 if (error != NoError) ReturnWithError(error);
00545
00546
00547 m_currentLevel--;
00548
00549
00550 if (m_cb) m_cb(m_cbArg);
00551
00552
00553 if (cb) {
00554 percent *= 4;
00555 if (m_progressMode == PM_Absolute) m_percent = percent;
00556 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
00557 }
00558 }
00559 }
00560
00561
00562 if (m_currentLevel == 0) Close();
00563 }
00564
00568 void CPGFImage::SetROI(PGFRect rect) {
00569 ASSERT(m_decoder);
00570 ASSERT(ROIisSupported());
00571
00572
00573 m_roi = rect;
00574
00575
00576 m_decoder->SetROI();
00577
00578
00579 const UINT32 dx = FilterWidth/2*(1 << m_currentLevel);
00580 const UINT32 dy = FilterHeight/2*(1 << m_currentLevel);
00581
00582 if (rect.left < dx) rect.left = 0;
00583 else rect.left -= dx;
00584 if (rect.top < dy) rect.top = 0;
00585 else rect.top -= dy;
00586 rect.right += dx;
00587 if (rect.right > m_header.width) rect.right = m_header.width;
00588 rect.bottom += dy;
00589 if (rect.bottom > m_header.height) rect.bottom = m_header.height;
00590
00591
00592 ASSERT(m_wtChannel[0]);
00593 m_wtChannel[0]->SetROI(rect);
00594 if (m_downsample && m_header.channels > 1) {
00595
00596 rect.left >>= 1;
00597 rect.top >>= 1;
00598 rect.right >>= 1;
00599 rect.bottom >>= 1;
00600 }
00601 for (int i=1; i < m_header.channels; i++) {
00602 ASSERT(m_wtChannel[i]);
00603 m_wtChannel[i]->SetROI(rect);
00604 }
00605 }
00606
00607 #endif // __PGFROISUPPORT__
00608
00613 UINT32 CPGFImage::GetEncodedHeaderLength() const {
00614 ASSERT(m_decoder);
00615 return m_decoder->GetEncodedHeaderLength();
00616 }
00617
00625 UINT32 CPGFImage::ReadEncodedHeader(UINT8* target, UINT32 targetLen) const THROW_ {
00626 ASSERT(target);
00627 ASSERT(targetLen > 0);
00628 ASSERT(m_decoder);
00629
00630
00631 m_decoder->SetStreamPosToStart();
00632
00633
00634 UINT32 len = __min(targetLen, GetEncodedHeaderLength());
00635
00636
00637 len = m_decoder->ReadEncodedData(target, len);
00638 ASSERT(len >= 0 && len <= targetLen);
00639
00640 return len;
00641 }
00642
00645 void CPGFImage::ResetStreamPos() THROW_ {
00646 ASSERT(m_decoder);
00647 return m_decoder->SetStreamPosToStart();
00648 }
00649
00659 UINT32 CPGFImage::ReadEncodedData(int level, UINT8* target, UINT32 targetLen) const THROW_ {
00660 ASSERT(level >= 0 && level < m_header.nLevels);
00661 ASSERT(target);
00662 ASSERT(targetLen > 0);
00663 ASSERT(m_decoder);
00664
00665
00666 m_decoder->SetStreamPosToData();
00667
00668
00669 UINT64 offset = 0;
00670
00671 for (int i=m_header.nLevels - 1; i > level; i--) {
00672 offset += m_levelLength[m_header.nLevels - 1 - i];
00673 }
00674 m_decoder->Skip(offset);
00675
00676
00677 UINT32 len = __min(targetLen, GetEncodedLevelLength(level));
00678
00679
00680 len = m_decoder->ReadEncodedData(target, len);
00681 ASSERT(len >= 0 && len <= targetLen);
00682
00683 return len;
00684 }
00685
00690 void CPGFImage::SetMaxValue(UINT32 maxValue) {
00691 const BYTE bpc = m_header.bpp/m_header.channels;
00692 BYTE pot = 0;
00693
00694 while(maxValue > 0) {
00695 pot++;
00696 maxValue >>= 1;
00697 }
00698
00699 if (pot > bpc) pot = bpc;
00700 if (pot > 31) pot = 31;
00701 m_header.usedBitsPerChannel = pot;
00702 }
00703
00708 BYTE CPGFImage::UsedBitsPerChannel() const {
00709 const BYTE bpc = m_header.bpp/m_header.channels;
00710
00711 if (bpc > 8) {
00712 return m_header.usedBitsPerChannel;
00713 } else {
00714 return bpc;
00715 }
00716 }
00717
00720 BYTE CPGFImage::CurrentVersion(BYTE version) {
00721 if (version & Version6) return 6;
00722 if (version & Version5) return 5;
00723 if (version & Version2) return 2;
00724 return 1;
00725 }
00726
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 void CPGFImage::ImportBitmap(int pitch, UINT8 *buff, BYTE bpp, int channelMap[] , CallbackPtr cb , void *data ) THROW_ {
00744 ASSERT(buff);
00745 ASSERT(m_channel[0]);
00746
00747
00748 RgbToYuv(pitch, buff, bpp, channelMap, cb, data);
00749
00750 if (m_downsample) {
00751
00752 for (int i=1; i < m_header.channels; i++) {
00753 Downsample(i);
00754 }
00755 }
00756 }
00757
00759
00760 void CPGFImage::Downsample(int ch) {
00761 ASSERT(ch > 0);
00762
00763 const int w = m_width[0];
00764 const int w2 = w/2;
00765 const int h2 = m_height[0]/2;
00766 const int oddW = w%2;
00767 const int oddH = m_height[0]%2;
00768 int loPos = 0;
00769 int hiPos = w;
00770 int sampledPos = 0;
00771 DataT* buff = m_channel[ch]; ASSERT(buff);
00772
00773 for (int i=0; i < h2; i++) {
00774 for (int j=0; j < w2; j++) {
00775
00776 buff[sampledPos] = (buff[loPos] + buff[loPos + 1] + buff[hiPos] + buff[hiPos + 1]) >> 2;
00777 loPos += 2; hiPos += 2;
00778 sampledPos++;
00779 }
00780 if (oddW) {
00781 buff[sampledPos] = (buff[loPos] + buff[hiPos]) >> 1;
00782 loPos++; hiPos++;
00783 sampledPos++;
00784 }
00785 loPos += w; hiPos += w;
00786 }
00787 if (oddH) {
00788 for (int j=0; j < w2; j++) {
00789 buff[sampledPos] = (buff[loPos] + buff[loPos+1]) >> 1;
00790 loPos += 2; hiPos += 2;
00791 sampledPos++;
00792 }
00793 if (oddW) {
00794 buff[sampledPos] = buff[loPos];
00795 }
00796 }
00797
00798
00799 m_width[ch] = (m_width[ch] + 1)/2;
00800 m_height[ch] = (m_height[ch] + 1)/2;
00801 }
00802
00804 void CPGFImage::ComputeLevels() {
00805 const int maxThumbnailWidth = 20*FilterWidth;
00806 const int m = __min(m_header.width, m_header.height);
00807 int s = m;
00808
00809 if (m_header.nLevels < 1 || m_header.nLevels > MaxLevel) {
00810 m_header.nLevels = 1;
00811
00812 while (s > maxThumbnailWidth) {
00813 m_header.nLevels++;
00814 s = s/2;
00815 }
00816 }
00817
00818 int levels = m_header.nLevels;
00819
00820
00821 s = FilterWidth*(1 << levels);
00822 while (m < s) {
00823 levels--;
00824 s = s/2;
00825 }
00826 if (levels > MaxLevel) m_header.nLevels = MaxLevel;
00827 else if (levels < 0) m_header.nLevels = 0;
00828 else m_header.nLevels = (UINT8)levels;
00829
00830
00831 m_percent = pow(0.25, m_header.nLevels);
00832
00833 ASSERT(0 <= m_header.nLevels && m_header.nLevels <= MaxLevel);
00834 }
00835
00844 void CPGFImage::SetHeader(const PGFHeader& header, BYTE flags , UINT8* userData , UINT32 userDataLength ) THROW_ {
00845 ASSERT(!m_decoder);
00846 ASSERT(header.quality <= MaxQuality);
00847
00848
00849 #ifdef __PGFROISUPPORT__
00850 m_streamReinitialized = false;
00851 #endif
00852
00853
00854 memcpy(m_preHeader.magic, PGFMagic, 3);
00855 m_preHeader.version = PGFVersion | flags;
00856 m_preHeader.hSize = HeaderSize;
00857
00858
00859 memcpy(&m_header, &header, HeaderSize);
00860
00861
00862 CompleteHeader();
00863
00864
00865 ComputeLevels();
00866
00867
00868 if (m_header.quality > DownsampleThreshold && (m_header.mode == ImageModeRGBColor ||
00869 m_header.mode == ImageModeRGBA ||
00870 m_header.mode == ImageModeRGB48 ||
00871 m_header.mode == ImageModeCMYKColor ||
00872 m_header.mode == ImageModeCMYK64 ||
00873 m_header.mode == ImageModeLabColor ||
00874 m_header.mode == ImageModeLab48)) {
00875 m_downsample = true;
00876 m_quant = m_header.quality - 1;
00877 } else {
00878 m_downsample = false;
00879 m_quant = m_header.quality;
00880 }
00881
00882
00883 if (m_header.mode == ImageModeIndexedColor) {
00884
00885 m_preHeader.hSize += ColorTableSize;
00886 }
00887 if (userDataLength && userData) {
00888 m_postHeader.userData = new(std::nothrow) UINT8[userDataLength];
00889 if (!m_postHeader.userData) ReturnWithError(InsufficientMemory);
00890 m_postHeader.userDataLen = userDataLength;
00891 memcpy(m_postHeader.userData, userData, userDataLength);
00892
00893 m_preHeader.hSize += userDataLength;
00894 }
00895
00896
00897 for (int i=0; i < m_header.channels; i++) {
00898
00899 m_width[i] = m_header.width;
00900 m_height[i] = m_header.height;
00901
00902
00903 ASSERT(!m_channel[i]);
00904 m_channel[i] = new(std::nothrow) DataT[m_header.width*m_header.height];
00905 if (!m_channel[i]) {
00906 if (i) i--;
00907 while(i) {
00908 delete[] m_channel[i]; m_channel[i] = 0;
00909 i--;
00910 }
00911 ReturnWithError(InsufficientMemory);
00912 }
00913 }
00914 }
00915
00923 UINT32 CPGFImage::WriteHeader(CPGFStream* stream) THROW_ {
00924 ASSERT(m_header.nLevels <= MaxLevel);
00925 ASSERT(m_header.quality <= MaxQuality);
00926
00927 if (m_header.nLevels > 0) {
00928 volatile OSError error = NoError;
00929
00930 #ifdef LIBPGF_USE_OPENMP
00931 #pragma omp parallel for default(shared)
00932 #endif
00933 for (int i=0; i < m_header.channels; i++) {
00934 DataT *temp = NULL;
00935 if (error == NoError) {
00936 if (m_wtChannel[i]) {
00937 ASSERT(m_channel[i]);
00938
00939 int size = m_height[i]*m_width[i];
00940 temp = new(std::nothrow) DataT[size];
00941 if (temp) {
00942 memcpy(temp, m_channel[i], size*DataTSize);
00943 delete m_wtChannel[i];
00944 m_channel[i] = NULL;
00945 } else {
00946 error = InsufficientMemory;
00947 }
00948 }
00949 if (error == NoError) {
00950 if (temp) {
00951 ASSERT(!m_channel[i]);
00952 m_channel[i] = temp;
00953 }
00954 m_wtChannel[i] = new CWaveletTransform(m_width[i], m_height[i], m_header.nLevels, m_channel[i]);
00955 if (m_wtChannel[i]) {
00956 #ifdef __PGFROISUPPORT__
00957 m_wtChannel[i]->SetROI(PGFRect(0, 0, m_width[i], m_height[i]));
00958 #endif
00959
00960
00961 for (int l=0; error == NoError && l < m_header.nLevels; l++) {
00962 OSError err = m_wtChannel[i]->ForwardTransform(l, m_quant);
00963 if (err != NoError) error = err;
00964 }
00965 } else {
00966 delete[] m_channel[i];
00967 error = InsufficientMemory;
00968 }
00969 }
00970 }
00971 }
00972 if (error != NoError) {
00973
00974 for (int i=0; i < m_header.channels; i++) {
00975 delete m_wtChannel[i];
00976 }
00977 ReturnWithError(error);
00978 }
00979
00980 m_currentLevel = m_header.nLevels;
00981
00982
00983 m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_userDataPos, m_useOMPinEncoder);
00984 if (m_favorSpeedOverSize) m_encoder->FavorSpeedOverSize();
00985
00986 #ifdef __PGFROISUPPORT__
00987 if (ROIisSupported()) {
00988
00989 m_encoder->SetROI();
00990 }
00991 #endif
00992
00993 } else {
00994
00995
00996
00997 m_encoder = new CEncoder(stream, m_preHeader, m_header, m_postHeader, m_userDataPos, m_useOMPinEncoder);
00998 }
00999
01000 INT64 nBytes = m_encoder->ComputeHeaderLength();
01001 return (nBytes > 0) ? (UINT32)nBytes : 0;
01002 }
01003
01005
01006
01007
01008
01009
01010
01011
01012 void CPGFImage::WriteLevel() THROW_ {
01013 ASSERT(m_encoder);
01014 ASSERT(m_currentLevel > 0);
01015 ASSERT(m_header.nLevels > 0);
01016
01017 #ifdef __PGFROISUPPORT__
01018 if (ROIisSupported()) {
01019 const int lastChannel = m_header.channels - 1;
01020
01021 for (int i=0; i < m_header.channels; i++) {
01022
01023 const UINT32 nTiles = m_wtChannel[i]->GetNofTiles(m_currentLevel);
01024 const UINT32 lastTile = nTiles - 1;
01025
01026 if (m_currentLevel == m_header.nLevels) {
01027
01028 ASSERT(nTiles == 1);
01029 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
01030 m_encoder->EncodeTileBuffer();
01031 }
01032 for (UINT32 tileY=0; tileY < nTiles; tileY++) {
01033 for (UINT32 tileX=0; tileX < nTiles; tileX++) {
01034 m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder, true, tileX, tileY);
01035 m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder, true, tileX, tileY);
01036 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder, true, tileX, tileY);
01037 if (i == lastChannel && tileY == lastTile && tileX == lastTile) {
01038
01039 m_encoder->SetEncodedLevel(--m_currentLevel);
01040 }
01041 m_encoder->EncodeTileBuffer();
01042 }
01043 }
01044 }
01045 } else
01046 #endif
01047 {
01048 for (int i=0; i < m_header.channels; i++) {
01049 ASSERT(m_wtChannel[i]);
01050 if (m_currentLevel == m_header.nLevels) {
01051
01052 m_wtChannel[i]->GetSubband(m_currentLevel, LL)->ExtractTile(*m_encoder);
01053 }
01054
01055 m_wtChannel[i]->GetSubband(m_currentLevel, HL)->ExtractTile(*m_encoder);
01056 m_wtChannel[i]->GetSubband(m_currentLevel, LH)->ExtractTile(*m_encoder);
01057 m_wtChannel[i]->GetSubband(m_currentLevel, HH)->ExtractTile(*m_encoder);
01058 }
01059
01060
01061 m_encoder->SetEncodedLevel(--m_currentLevel);
01062 }
01063 }
01064
01066
01067 UINT32 CPGFImage::UpdatePostHeaderSize() THROW_ {
01068 ASSERT(m_encoder);
01069
01070 INT64 offset = m_encoder->ComputeOffset(); ASSERT(offset >= 0);
01071
01072 if (offset > 0) {
01073
01074 m_preHeader.hSize += (UINT32)offset;
01075 m_encoder->UpdatePostHeaderSize(m_preHeader);
01076 }
01077
01078
01079 return m_encoder->WriteLevelLength(m_levelLength);
01080 }
01081
01092 UINT32 CPGFImage::WriteImage(CPGFStream* stream, CallbackPtr cb , void *data ) THROW_ {
01093 ASSERT(stream);
01094 ASSERT(m_preHeader.hSize);
01095
01096 int levels = m_header.nLevels;
01097 double percent = pow(0.25, levels);
01098
01099
01100 UINT32 nWrittenBytes = UpdatePostHeaderSize();
01101
01102 if (levels == 0) {
01103
01104 for (int c=0; c < m_header.channels; c++) {
01105 const UINT32 size = m_width[c]*m_height[c];
01106
01107
01108 for (UINT32 i=0; i < size; i++) {
01109 int count = DataTSize;
01110 stream->Write(&count, &m_channel[c][i]);
01111 }
01112 }
01113
01114
01115 if (cb) {
01116 if ((*cb)(1, true, data)) ReturnWithError(EscapePressed);
01117 }
01118
01119 } else {
01120
01121
01122
01123
01124
01125 for (m_currentLevel = levels; m_currentLevel > 0; ) {
01126 WriteLevel();
01127
01128
01129 if (cb) {
01130 percent *= 4;
01131 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01132 }
01133 }
01134
01135
01136 m_encoder->Flush();
01137 }
01138
01139
01140 nWrittenBytes += m_encoder->UpdateLevelLength();
01141
01142
01143 delete m_encoder; m_encoder = NULL;
01144
01145 ASSERT(!m_encoder);
01146
01147 return nWrittenBytes;
01148 }
01149
01163 void CPGFImage::Write(CPGFStream* stream, UINT32* nWrittenBytes , CallbackPtr cb , void *data ) THROW_ {
01164 ASSERT(stream);
01165 ASSERT(m_preHeader.hSize);
01166
01167
01168 UINT32 nBytes = WriteHeader(stream);
01169
01170
01171 nBytes += WriteImage(stream, cb, data);
01172
01173
01174 if (nWrittenBytes) *nWrittenBytes += nBytes;
01175 }
01176
01177 #ifdef __PGFROISUPPORT__
01179 // Encode and write down to given level at current stream position.
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 UINT32 CPGFImage::Write(int level, CallbackPtr cb , void *data ) THROW_ {
01193 ASSERT(m_header.nLevels > 0);
01194 ASSERT(0 <= level && level < m_header.nLevels);
01195 ASSERT(m_encoder);
01196 ASSERT(ROIisSupported());
01197
01198 const int levelDiff = m_currentLevel - level;
01199 double percent = (m_progressMode == PM_Relative) ? pow(0.25, levelDiff) : m_percent;
01200 UINT32 nWrittenBytes = 0;
01201
01202 if (m_currentLevel == m_header.nLevels) {
01203
01204 nWrittenBytes = UpdatePostHeaderSize();
01205 } else {
01206
01207 if (m_encoder->ComputeBufferLength()) {
01208 m_streamReinitialized = true;
01209 }
01210 }
01211
01212
01213 while (m_currentLevel > level) {
01214 WriteLevel();
01215
01216 if (m_levelLength) {
01217 nWrittenBytes += m_levelLength[m_header.nLevels - m_currentLevel - 1];
01218 }
01219
01220
01221 if (cb) {
01222 percent *= 4;
01223 if (m_progressMode == PM_Absolute) m_percent = percent;
01224 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01225 }
01226 }
01227
01228
01229 if (m_currentLevel == 0) {
01230 if (!m_streamReinitialized) {
01231
01232 m_encoder->UpdateLevelLength();
01233 }
01234
01235 delete m_encoder; m_encoder = NULL;
01236 }
01237
01238 return nWrittenBytes;
01239 }
01240 #endif // __PGFROISUPPORT__
01241
01242
01244
01245
01246
01247 bool CPGFImage::ImportIsSupported(BYTE mode) {
01248 size_t size = DataTSize;
01249
01250 if (size >= 2) {
01251 switch(mode) {
01252 case ImageModeBitmap:
01253 case ImageModeIndexedColor:
01254 case ImageModeGrayScale:
01255 case ImageModeRGBColor:
01256 case ImageModeCMYKColor:
01257 case ImageModeHSLColor:
01258 case ImageModeHSBColor:
01259
01260 case ImageModeLabColor:
01261 case ImageModeRGB12:
01262 case ImageModeRGB16:
01263 case ImageModeRGBA:
01264 return true;
01265 }
01266 }
01267 if (size >= 3) {
01268 switch(mode) {
01269 case ImageModeGray16:
01270 case ImageModeRGB48:
01271 case ImageModeLab48:
01272 case ImageModeCMYK64:
01273
01274 return true;
01275 }
01276 }
01277 if (size >=4) {
01278 switch(mode) {
01279 case ImageModeGray32:
01280 return true;
01281 }
01282 }
01283 return false;
01284 }
01285
01292 void CPGFImage::GetColorTable(UINT32 iFirstColor, UINT32 nColors, RGBQUAD* prgbColors) const THROW_ {
01293 if (iFirstColor + nColors > ColorTableLen) ReturnWithError(ColorTableError);
01294
01295 for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
01296 prgbColors[j] = m_postHeader.clut[i];
01297 }
01298 }
01299
01306 void CPGFImage::SetColorTable(UINT32 iFirstColor, UINT32 nColors, const RGBQUAD* prgbColors) THROW_ {
01307 if (iFirstColor + nColors > ColorTableLen) ReturnWithError(ColorTableError);
01308
01309 for (UINT32 i=iFirstColor, j=0; j < nColors; i++, j++) {
01310 m_postHeader.clut[i] = prgbColors[j];
01311 }
01312 }
01313
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 void CPGFImage::RgbToYuv(int pitch, UINT8* buff, BYTE bpp, int channelMap[], CallbackPtr cb, void *data ) THROW_ {
01332 ASSERT(buff);
01333 int yPos = 0, cnt = 0;
01334 double percent = 0;
01335 const double dP = 1.0/m_header.height;
01336 int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
01337
01338 if (channelMap == NULL) channelMap = defMap;
01339
01340 switch(m_header.mode) {
01341 case ImageModeBitmap:
01342 {
01343 ASSERT(m_header.channels == 1);
01344 ASSERT(m_header.bpp == 1);
01345 ASSERT(bpp == 1);
01346
01347 const UINT32 w = m_header.width;
01348 const UINT32 w2 = (m_header.width + 7)/8;
01349 DataT* y = m_channel[0]; ASSERT(y);
01350
01351 for (UINT32 h=0; h < m_header.height; h++) {
01352 if (cb) {
01353 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01354 percent += dP;
01355 }
01356
01357 for (UINT32 j=0; j < w2; j++) {
01358 y[yPos++] = buff[j] - YUVoffset8;
01359 }
01360 for (UINT32 j=w2; j < w; j++) {
01361 y[yPos++] = YUVoffset8;
01362 }
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 buff += pitch;
01374 }
01375 }
01376 break;
01377 case ImageModeIndexedColor:
01378 case ImageModeGrayScale:
01379 case ImageModeHSLColor:
01380 case ImageModeHSBColor:
01381 case ImageModeLabColor:
01382 {
01383 ASSERT(m_header.channels >= 1);
01384 ASSERT(m_header.bpp == m_header.channels*8);
01385 ASSERT(bpp%8 == 0);
01386 const int channels = bpp/8; ASSERT(channels >= m_header.channels);
01387
01388 for (UINT32 h=0; h < m_header.height; h++) {
01389 if (cb) {
01390 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01391 percent += dP;
01392 }
01393
01394 cnt = 0;
01395 for (UINT32 w=0; w < m_header.width; w++) {
01396 for (int c=0; c < m_header.channels; c++) {
01397 m_channel[c][yPos] = buff[cnt + channelMap[c]] - YUVoffset8;
01398 }
01399 cnt += channels;
01400 yPos++;
01401 }
01402 buff += pitch;
01403 }
01404 }
01405 break;
01406 case ImageModeGray16:
01407 case ImageModeLab48:
01408 {
01409 ASSERT(m_header.channels >= 1);
01410 ASSERT(m_header.bpp == m_header.channels*16);
01411 ASSERT(bpp%16 == 0);
01412
01413 UINT16 *buff16 = (UINT16 *)buff;
01414 const int pitch16 = pitch/2;
01415 const int channels = bpp/16; ASSERT(channels >= m_header.channels);
01416 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01417 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01418
01419 for (UINT32 h=0; h < m_header.height; h++) {
01420 if (cb) {
01421 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01422 percent += dP;
01423 }
01424
01425 cnt = 0;
01426 for (UINT32 w=0; w < m_header.width; w++) {
01427 for (int c=0; c < m_header.channels; c++) {
01428 m_channel[c][yPos] = (buff16[cnt + channelMap[c]] >> shift) - yuvOffset16;
01429 }
01430 cnt += channels;
01431 yPos++;
01432 }
01433 buff16 += pitch16;
01434 }
01435 }
01436 break;
01437 case ImageModeRGBColor:
01438 {
01439 ASSERT(m_header.channels == 3);
01440 ASSERT(m_header.bpp == m_header.channels*8);
01441 ASSERT(bpp%8 == 0);
01442
01443 DataT* y = m_channel[0]; ASSERT(y);
01444 DataT* u = m_channel[1]; ASSERT(u);
01445 DataT* v = m_channel[2]; ASSERT(v);
01446 const int channels = bpp/8; ASSERT(channels >= m_header.channels);
01447 UINT8 b, g, r;
01448
01449 for (UINT32 h=0; h < m_header.height; h++) {
01450 if (cb) {
01451 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01452 percent += dP;
01453 }
01454
01455 cnt = 0;
01456 for (UINT32 w=0; w < m_header.width; w++) {
01457 b = buff[cnt + channelMap[0]];
01458 g = buff[cnt + channelMap[1]];
01459 r = buff[cnt + channelMap[2]];
01460
01461 y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
01462 u[yPos] = r - g;
01463 v[yPos] = b - g;
01464 yPos++;
01465 cnt += channels;
01466 }
01467 buff += pitch;
01468 }
01469 }
01470 break;
01471 case ImageModeRGB48:
01472 {
01473 ASSERT(m_header.channels == 3);
01474 ASSERT(m_header.bpp == m_header.channels*16);
01475 ASSERT(bpp%16 == 0);
01476
01477 UINT16 *buff16 = (UINT16 *)buff;
01478 const int pitch16 = pitch/2;
01479 const int channels = bpp/16; ASSERT(channels >= m_header.channels);
01480 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01481 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01482
01483 DataT* y = m_channel[0]; ASSERT(y);
01484 DataT* u = m_channel[1]; ASSERT(u);
01485 DataT* v = m_channel[2]; ASSERT(v);
01486 UINT16 b, g, r;
01487
01488 for (UINT32 h=0; h < m_header.height; h++) {
01489 if (cb) {
01490 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01491 percent += dP;
01492 }
01493
01494 cnt = 0;
01495 for (UINT32 w=0; w < m_header.width; w++) {
01496 b = buff16[cnt + channelMap[0]] >> shift;
01497 g = buff16[cnt + channelMap[1]] >> shift;
01498 r = buff16[cnt + channelMap[2]] >> shift;
01499
01500 y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
01501 u[yPos] = r - g;
01502 v[yPos] = b - g;
01503 yPos++;
01504 cnt += channels;
01505 }
01506 buff16 += pitch16;
01507 }
01508 }
01509 break;
01510 case ImageModeRGBA:
01511 case ImageModeCMYKColor:
01512 {
01513 ASSERT(m_header.channels == 4);
01514 ASSERT(m_header.bpp == m_header.channels*8);
01515 ASSERT(bpp%8 == 0);
01516 const int channels = bpp/8; ASSERT(channels >= m_header.channels);
01517
01518 DataT* y = m_channel[0]; ASSERT(y);
01519 DataT* u = m_channel[1]; ASSERT(u);
01520 DataT* v = m_channel[2]; ASSERT(v);
01521 DataT* a = m_channel[3]; ASSERT(a);
01522 UINT8 b, g, r;
01523
01524 for (UINT32 h=0; h < m_header.height; h++) {
01525 if (cb) {
01526 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01527 percent += dP;
01528 }
01529
01530 cnt = 0;
01531 for (UINT32 w=0; w < m_header.width; w++) {
01532 b = buff[cnt + channelMap[0]];
01533 g = buff[cnt + channelMap[1]];
01534 r = buff[cnt + channelMap[2]];
01535
01536 y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset8;
01537 u[yPos] = r - g;
01538 v[yPos] = b - g;
01539 a[yPos++] = buff[cnt + channelMap[3]] - YUVoffset8;
01540 cnt += channels;
01541 }
01542 buff += pitch;
01543 }
01544 }
01545 break;
01546 case ImageModeCMYK64:
01547 {
01548 ASSERT(m_header.channels == 4);
01549 ASSERT(m_header.bpp == m_header.channels*16);
01550 ASSERT(bpp%16 == 0);
01551
01552 UINT16 *buff16 = (UINT16 *)buff;
01553 const int pitch16 = pitch/2;
01554 const int channels = bpp/16; ASSERT(channels >= m_header.channels);
01555 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01556 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01557
01558 DataT* y = m_channel[0]; ASSERT(y);
01559 DataT* u = m_channel[1]; ASSERT(u);
01560 DataT* v = m_channel[2]; ASSERT(v);
01561 DataT* a = m_channel[3]; ASSERT(a);
01562 UINT16 b, g, r;
01563
01564 for (UINT32 h=0; h < m_header.height; h++) {
01565 if (cb) {
01566 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01567 percent += dP;
01568 }
01569
01570 cnt = 0;
01571 for (UINT32 w=0; w < m_header.width; w++) {
01572 b = buff16[cnt + channelMap[0]] >> shift;
01573 g = buff16[cnt + channelMap[1]] >> shift;
01574 r = buff16[cnt + channelMap[2]] >> shift;
01575
01576 y[yPos] = ((b + (g << 1) + r) >> 2) - yuvOffset16;
01577 u[yPos] = r - g;
01578 v[yPos] = b - g;
01579 a[yPos++] = (buff16[cnt + channelMap[3]] >> shift) - yuvOffset16;
01580 cnt += channels;
01581 }
01582 buff16 += pitch16;
01583 }
01584 }
01585 break;
01586 #ifdef __PGF32SUPPORT__
01587 case ImageModeGray32:
01588 {
01589 ASSERT(m_header.channels == 1);
01590 ASSERT(m_header.bpp == 32);
01591 ASSERT(bpp == 32);
01592 ASSERT(DataTSize == sizeof(UINT32));
01593
01594 DataT* y = m_channel[0]; ASSERT(y);
01595
01596 UINT32 *buff32 = (UINT32 *)buff;
01597 const int pitch32 = pitch/4;
01598 const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01599 const DataT yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
01600
01601 for (UINT32 h=0; h < m_header.height; h++) {
01602 if (cb) {
01603 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01604 percent += dP;
01605 }
01606
01607 for (UINT32 w=0; w < m_header.width; w++) {
01608 y[yPos++] = (buff32[w] >> shift) - yuvOffset31;
01609 }
01610 buff32 += pitch32;
01611 }
01612 }
01613 break;
01614 #endif
01615 case ImageModeRGB12:
01616 {
01617 ASSERT(m_header.channels == 3);
01618 ASSERT(m_header.bpp == m_header.channels*4);
01619 ASSERT(bpp == m_header.channels*4);
01620
01621 DataT* y = m_channel[0]; ASSERT(y);
01622 DataT* u = m_channel[1]; ASSERT(u);
01623 DataT* v = m_channel[2]; ASSERT(v);
01624
01625 UINT8 rgb = 0, b, g, r;
01626
01627 for (UINT32 h=0; h < m_header.height; h++) {
01628 if (cb) {
01629 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01630 percent += dP;
01631 }
01632
01633 cnt = 0;
01634 for (UINT32 w=0; w < m_header.width; w++) {
01635 if (w%2 == 0) {
01636
01637 rgb = buff[cnt];
01638 b = rgb & 0x0F;
01639 g = (rgb & 0xF0) >> 4;
01640 cnt++;
01641 rgb = buff[cnt];
01642 r = rgb & 0x0F;
01643 } else {
01644
01645 b = (rgb & 0xF0) >> 4;
01646 cnt++;
01647 rgb = buff[cnt];
01648 g = rgb & 0x0F;
01649 r = (rgb & 0xF0) >> 4;
01650 cnt++;
01651 }
01652
01653
01654 y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset4;
01655 u[yPos] = r - g;
01656 v[yPos] = b - g;
01657 yPos++;
01658 }
01659 buff += pitch;
01660 }
01661 }
01662 break;
01663 case ImageModeRGB16:
01664 {
01665 ASSERT(m_header.channels == 3);
01666 ASSERT(m_header.bpp == 16);
01667 ASSERT(bpp == 16);
01668
01669 DataT* y = m_channel[0]; ASSERT(y);
01670 DataT* u = m_channel[1]; ASSERT(u);
01671 DataT* v = m_channel[2]; ASSERT(v);
01672
01673 UINT16 *buff16 = (UINT16 *)buff;
01674 UINT16 rgb, b, g, r;
01675 const int pitch16 = pitch/2;
01676
01677 for (UINT32 h=0; h < m_header.height; h++) {
01678 if (cb) {
01679 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01680 percent += dP;
01681 }
01682 for (UINT32 w=0; w < m_header.width; w++) {
01683 rgb = buff16[w];
01684 r = (rgb & 0xF800) >> 10;
01685 g = (rgb & 0x07E0) >> 5;
01686 b = (rgb & 0x001F) << 1;
01687
01688 y[yPos] = ((b + (g << 1) + r) >> 2) - YUVoffset6;
01689 u[yPos] = r - g;
01690 v[yPos] = b - g;
01691 yPos++;
01692 }
01693
01694 buff16 += pitch16;
01695 }
01696 }
01697 break;
01698 default:
01699 ASSERT(false);
01700 }
01701 }
01702
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720 void CPGFImage::GetBitmap(int pitch, UINT8* buff, BYTE bpp, int channelMap[] , CallbackPtr cb , void *data ) const THROW_ {
01721 ASSERT(buff);
01722 UINT32 w = m_width[0];
01723 UINT32 h = m_height[0];
01724 UINT8* targetBuff = 0;
01725 UINT8* buffStart = 0;
01726 int targetPitch = 0;
01727
01728 #ifdef __PGFROISUPPORT__
01729 const PGFRect& roi = (ROIisSupported()) ? m_wtChannel[0]->GetROI(m_currentLevel) : PGFRect(0, 0, w, h);
01730 const PGFRect levelRoi(LevelWidth(m_roi.left, m_currentLevel), LevelHeight(m_roi.top, m_currentLevel), LevelWidth(m_roi.Width(), m_currentLevel), LevelHeight(m_roi.Height(), m_currentLevel));
01731 ASSERT(w <= roi.Width() && h <= roi.Height());
01732 ASSERT(roi.left <= levelRoi.left && levelRoi.right <= roi.right);
01733 ASSERT(roi.top <= levelRoi.top && levelRoi.bottom <= roi.bottom);
01734
01735 if (ROIisSupported() && (levelRoi.Width() < w || levelRoi.Height() < h)) {
01736
01737
01738 targetPitch = pitch;
01739 pitch = AlignWordPos(w*bpp)/8;
01740
01741
01742 targetBuff = buff;
01743 buff = buffStart = new(std::nothrow) UINT8[pitch*h];
01744 if (!buff) ReturnWithError(InsufficientMemory);
01745 }
01746 #endif
01747
01748 const bool wOdd = (1 == w%2);
01749
01750 const double dP = 1.0/h;
01751 int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
01752 if (channelMap == NULL) channelMap = defMap;
01753 int sampledPos = 0, yPos = 0;
01754 DataT uAvg, vAvg;
01755 double percent = 0;
01756 UINT32 i, j;
01757
01758 switch(m_header.mode) {
01759 case ImageModeBitmap:
01760 {
01761 ASSERT(m_header.channels == 1);
01762 ASSERT(m_header.bpp == 1);
01763 ASSERT(bpp == 1);
01764
01765 const UINT32 w2 = (w + 7)/8;
01766 DataT* y = m_channel[0]; ASSERT(y);
01767
01768 for (i=0; i < h; i++) {
01769
01770 for (j=0; j < w2; j++) {
01771 buff[j] = Clamp8(y[yPos++] + YUVoffset8);
01772 }
01773 yPos += w - w2;
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786 buff += pitch;
01787
01788 if (cb) {
01789 percent += dP;
01790 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01791 }
01792 }
01793 break;
01794 }
01795 case ImageModeIndexedColor:
01796 case ImageModeGrayScale:
01797 case ImageModeHSLColor:
01798 case ImageModeHSBColor:
01799 {
01800 ASSERT(m_header.channels >= 1);
01801 ASSERT(m_header.bpp == m_header.channels*8);
01802 ASSERT(bpp%8 == 0);
01803
01804 int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
01805
01806 for (i=0; i < h; i++) {
01807 cnt = 0;
01808 for (j=0; j < w; j++) {
01809 for (int c=0; c < m_header.channels; c++) {
01810 buff[cnt + channelMap[c]] = Clamp8(m_channel[c][yPos] + YUVoffset8);
01811 }
01812 cnt += channels;
01813 yPos++;
01814 }
01815 buff += pitch;
01816
01817 if (cb) {
01818 percent += dP;
01819 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01820 }
01821 }
01822 break;
01823 }
01824 case ImageModeGray16:
01825 {
01826 ASSERT(m_header.channels >= 1);
01827 ASSERT(m_header.bpp == m_header.channels*16);
01828
01829 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01830 int cnt, channels;
01831
01832 if (bpp%16 == 0) {
01833 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01834 UINT16 *buff16 = (UINT16 *)buff;
01835 int pitch16 = pitch/2;
01836 channels = bpp/16; ASSERT(channels >= m_header.channels);
01837
01838 for (i=0; i < h; i++) {
01839 cnt = 0;
01840 for (j=0; j < w; j++) {
01841 for (int c=0; c < m_header.channels; c++) {
01842 buff16[cnt + channelMap[c]] = Clamp16((m_channel[c][yPos] + yuvOffset16) << shift);
01843 }
01844 cnt += channels;
01845 yPos++;
01846 }
01847 buff16 += pitch16;
01848
01849 if (cb) {
01850 percent += dP;
01851 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01852 }
01853 }
01854 } else {
01855 ASSERT(bpp%8 == 0);
01856 const int shift = __max(0, UsedBitsPerChannel() - 8);
01857 channels = bpp/8; ASSERT(channels >= m_header.channels);
01858
01859 for (i=0; i < h; i++) {
01860 cnt = 0;
01861 for (j=0; j < w; j++) {
01862 for (int c=0; c < m_header.channels; c++) {
01863 buff[cnt + channelMap[c]] = Clamp8((m_channel[c][yPos] + yuvOffset16) >> shift);
01864 }
01865 cnt += channels;
01866 yPos++;
01867 }
01868 buff += pitch;
01869
01870 if (cb) {
01871 percent += dP;
01872 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01873 }
01874 }
01875 }
01876 break;
01877 }
01878 case ImageModeRGBColor:
01879 {
01880 ASSERT(m_header.channels == 3);
01881 ASSERT(m_header.bpp == m_header.channels*8);
01882 ASSERT(bpp%8 == 0);
01883 ASSERT(bpp >= m_header.bpp);
01884
01885 DataT* y = m_channel[0]; ASSERT(y);
01886 DataT* u = m_channel[1]; ASSERT(u);
01887 DataT* v = m_channel[2]; ASSERT(v);
01888 UINT8 *buffg = &buff[channelMap[1]],
01889 *buffr = &buff[channelMap[2]],
01890 *buffb = &buff[channelMap[0]];
01891 UINT8 g;
01892 int cnt, channels = bpp/8;
01893 if(m_downsample){
01894 for (i=0; i < h; i++) {
01895 if (i%2) sampledPos -= (w + 1)/2;
01896 cnt = 0;
01897 for (j=0; j < w; j++) {
01898
01899 uAvg = u[sampledPos];
01900 vAvg = v[sampledPos];
01901
01902 buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2));
01903 buffr[cnt] = Clamp8(uAvg + g);
01904 buffb[cnt] = Clamp8(vAvg + g);
01905 yPos++;
01906 cnt += channels;
01907 if (j%2) sampledPos++;
01908 }
01909 buffb += pitch;
01910 buffg += pitch;
01911 buffr += pitch;
01912 if (wOdd) sampledPos++;
01913 if (cb) {
01914 percent += dP;
01915 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01916 }
01917 }
01918 }else{
01919 for (i=0; i < h; i++) {
01920 cnt = 0;
01921 for (j = 0; j < w; j++) {
01922 uAvg = u[yPos];
01923 vAvg = v[yPos];
01924
01925 buffg[cnt] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2));
01926 buffr[cnt] = Clamp8(uAvg + g);
01927 buffb[cnt] = Clamp8(vAvg + g);
01928 yPos++;
01929 cnt += channels;
01930 }
01931 buffb += pitch;
01932 buffg += pitch;
01933 buffr += pitch;
01934
01935 if (cb) {
01936 percent += dP;
01937 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01938 }
01939 }
01940 }
01941 break;
01942 }
01943 case ImageModeRGB48:
01944 {
01945 ASSERT(m_header.channels == 3);
01946 ASSERT(m_header.bpp == 48);
01947
01948 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
01949
01950 DataT* y = m_channel[0]; ASSERT(y);
01951 DataT* u = m_channel[1]; ASSERT(u);
01952 DataT* v = m_channel[2]; ASSERT(v);
01953 int cnt, channels;
01954 DataT g;
01955
01956 if (bpp >= 48 && bpp%16 == 0) {
01957 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
01958 UINT16 *buff16 = (UINT16 *)buff;
01959 int pitch16 = pitch/2;
01960 channels = bpp/16; ASSERT(channels >= m_header.channels);
01961
01962 for (i=0; i < h; i++) {
01963 if (i%2) sampledPos -= (w + 1)/2;
01964 cnt = 0;
01965 for (j=0; j < w; j++) {
01966 if (m_downsample) {
01967
01968 uAvg = u[sampledPos];
01969 vAvg = v[sampledPos];
01970 } else {
01971 uAvg = u[yPos];
01972 vAvg = v[yPos];
01973 }
01974
01975 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2);
01976 buff16[cnt + channelMap[1]] = Clamp16(g << shift);
01977 buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
01978 buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
01979 yPos++;
01980 cnt += channels;
01981 if (j%2) sampledPos++;
01982 }
01983 buff16 += pitch16;
01984 if (wOdd) sampledPos++;
01985
01986 if (cb) {
01987 percent += dP;
01988 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
01989 }
01990 }
01991 } else {
01992 ASSERT(bpp%8 == 0);
01993 const int shift = __max(0, UsedBitsPerChannel() - 8);
01994 channels = bpp/8; ASSERT(channels >= m_header.channels);
01995
01996 for (i=0; i < h; i++) {
01997 if (i%2) sampledPos -= (w + 1)/2;
01998 cnt = 0;
01999 for (j=0; j < w; j++) {
02000 if (m_downsample) {
02001
02002 uAvg = u[sampledPos];
02003 vAvg = v[sampledPos];
02004 } else {
02005 uAvg = u[yPos];
02006 vAvg = v[yPos];
02007 }
02008
02009 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2);
02010 buff[cnt + channelMap[1]] = Clamp8(g >> shift);
02011 buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
02012 buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
02013 yPos++;
02014 cnt += channels;
02015 if (j%2) sampledPos++;
02016 }
02017 buff += pitch;
02018 if (wOdd) sampledPos++;
02019
02020 if (cb) {
02021 percent += dP;
02022 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02023 }
02024 }
02025 }
02026 break;
02027 }
02028 case ImageModeLabColor:
02029 {
02030 ASSERT(m_header.channels == 3);
02031 ASSERT(m_header.bpp == m_header.channels*8);
02032 ASSERT(bpp%8 == 0);
02033
02034 DataT* l = m_channel[0]; ASSERT(l);
02035 DataT* a = m_channel[1]; ASSERT(a);
02036 DataT* b = m_channel[2]; ASSERT(b);
02037 int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
02038
02039 for (i=0; i < h; i++) {
02040 if (i%2) sampledPos -= (w + 1)/2;
02041 cnt = 0;
02042 for (j=0; j < w; j++) {
02043 if (m_downsample) {
02044
02045 uAvg = a[sampledPos];
02046 vAvg = b[sampledPos];
02047 } else {
02048 uAvg = a[yPos];
02049 vAvg = b[yPos];
02050 }
02051 buff[cnt + channelMap[0]] = Clamp8(l[yPos] + YUVoffset8);
02052 buff[cnt + channelMap[1]] = Clamp8(uAvg + YUVoffset8);
02053 buff[cnt + channelMap[2]] = Clamp8(vAvg + YUVoffset8);
02054 cnt += channels;
02055 yPos++;
02056 if (j%2) sampledPos++;
02057 }
02058 buff += pitch;
02059 if (wOdd) sampledPos++;
02060
02061 if (cb) {
02062 percent += dP;
02063 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02064 }
02065 }
02066 break;
02067 }
02068 case ImageModeLab48:
02069 {
02070 ASSERT(m_header.channels == 3);
02071 ASSERT(m_header.bpp == m_header.channels*16);
02072
02073 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
02074
02075 DataT* l = m_channel[0]; ASSERT(l);
02076 DataT* a = m_channel[1]; ASSERT(a);
02077 DataT* b = m_channel[2]; ASSERT(b);
02078 int cnt, channels;
02079
02080 if (bpp%16 == 0) {
02081 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
02082 UINT16 *buff16 = (UINT16 *)buff;
02083 int pitch16 = pitch/2;
02084 channels = bpp/16; ASSERT(channels >= m_header.channels);
02085
02086 for (i=0; i < h; i++) {
02087 if (i%2) sampledPos -= (w + 1)/2;
02088 cnt = 0;
02089 for (j=0; j < w; j++) {
02090 if (m_downsample) {
02091
02092 uAvg = a[sampledPos];
02093 vAvg = b[sampledPos];
02094 } else {
02095 uAvg = a[yPos];
02096 vAvg = b[yPos];
02097 }
02098 buff16[cnt + channelMap[0]] = Clamp16((l[yPos] + yuvOffset16) << shift);
02099 buff16[cnt + channelMap[1]] = Clamp16((uAvg + yuvOffset16) << shift);
02100 buff16[cnt + channelMap[2]] = Clamp16((vAvg + yuvOffset16) << shift);
02101 cnt += channels;
02102 yPos++;
02103 if (j%2) sampledPos++;
02104 }
02105 buff16 += pitch16;
02106 if (wOdd) sampledPos++;
02107
02108 if (cb) {
02109 percent += dP;
02110 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02111 }
02112 }
02113 } else {
02114 ASSERT(bpp%8 == 0);
02115 const int shift = __max(0, UsedBitsPerChannel() - 8);
02116 channels = bpp/8; ASSERT(channels >= m_header.channels);
02117
02118 for (i=0; i < h; i++) {
02119 if (i%2) sampledPos -= (w + 1)/2;
02120 cnt = 0;
02121 for (j=0; j < w; j++) {
02122 if (m_downsample) {
02123
02124 uAvg = a[sampledPos];
02125 vAvg = b[sampledPos];
02126 } else {
02127 uAvg = a[yPos];
02128 vAvg = b[yPos];
02129 }
02130 buff[cnt + channelMap[0]] = Clamp8((l[yPos] + yuvOffset16) >> shift);
02131 buff[cnt + channelMap[1]] = Clamp8((uAvg + yuvOffset16) >> shift);
02132 buff[cnt + channelMap[2]] = Clamp8((vAvg + yuvOffset16) >> shift);
02133 cnt += channels;
02134 yPos++;
02135 if (j%2) sampledPos++;
02136 }
02137 buff += pitch;
02138 if (wOdd) sampledPos++;
02139
02140 if (cb) {
02141 percent += dP;
02142 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02143 }
02144 }
02145 }
02146 break;
02147 }
02148 case ImageModeRGBA:
02149 case ImageModeCMYKColor:
02150 {
02151 ASSERT(m_header.channels == 4);
02152 ASSERT(m_header.bpp == m_header.channels*8);
02153 ASSERT(bpp%8 == 0);
02154
02155 DataT* y = m_channel[0]; ASSERT(y);
02156 DataT* u = m_channel[1]; ASSERT(u);
02157 DataT* v = m_channel[2]; ASSERT(v);
02158 DataT* a = m_channel[3]; ASSERT(a);
02159 UINT8 g, aAvg;
02160 int cnt, channels = bpp/8; ASSERT(channels >= m_header.channels);
02161
02162 for (i=0; i < h; i++) {
02163 if (i%2) sampledPos -= (w + 1)/2;
02164 cnt = 0;
02165 for (j=0; j < w; j++) {
02166 if (m_downsample) {
02167
02168 uAvg = u[sampledPos];
02169 vAvg = v[sampledPos];
02170 aAvg = Clamp8(a[sampledPos] + YUVoffset8);
02171 } else {
02172 uAvg = u[yPos];
02173 vAvg = v[yPos];
02174 aAvg = Clamp8(a[yPos] + YUVoffset8);
02175 }
02176
02177 buff[cnt + channelMap[1]] = g = Clamp8(y[yPos] + YUVoffset8 - ((uAvg + vAvg ) >> 2));
02178 buff[cnt + channelMap[2]] = Clamp8(uAvg + g);
02179 buff[cnt + channelMap[0]] = Clamp8(vAvg + g);
02180 buff[cnt + channelMap[3]] = aAvg;
02181 yPos++;
02182 cnt += channels;
02183 if (j%2) sampledPos++;
02184 }
02185 buff += pitch;
02186 if (wOdd) sampledPos++;
02187
02188 if (cb) {
02189 percent += dP;
02190 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02191 }
02192 }
02193 break;
02194 }
02195 case ImageModeCMYK64:
02196 {
02197 ASSERT(m_header.channels == 4);
02198 ASSERT(m_header.bpp == 64);
02199
02200 const DataT yuvOffset16 = 1 << (UsedBitsPerChannel() - 1);
02201
02202 DataT* y = m_channel[0]; ASSERT(y);
02203 DataT* u = m_channel[1]; ASSERT(u);
02204 DataT* v = m_channel[2]; ASSERT(v);
02205 DataT* a = m_channel[3]; ASSERT(a);
02206 DataT g, aAvg;
02207 int cnt, channels;
02208
02209 if (bpp%16 == 0) {
02210 const int shift = 16 - UsedBitsPerChannel(); ASSERT(shift >= 0);
02211 UINT16 *buff16 = (UINT16 *)buff;
02212 int pitch16 = pitch/2;
02213 channels = bpp/16; ASSERT(channels >= m_header.channels);
02214
02215 for (i=0; i < h; i++) {
02216 if (i%2) sampledPos -= (w + 1)/2;
02217 cnt = 0;
02218 for (j=0; j < w; j++) {
02219 if (m_downsample) {
02220
02221 uAvg = u[sampledPos];
02222 vAvg = v[sampledPos];
02223 aAvg = a[sampledPos] + yuvOffset16;
02224 } else {
02225 uAvg = u[yPos];
02226 vAvg = v[yPos];
02227 aAvg = a[yPos] + yuvOffset16;
02228 }
02229
02230 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2);
02231 buff16[cnt + channelMap[1]] = Clamp16(g << shift);
02232 buff16[cnt + channelMap[2]] = Clamp16((uAvg + g) << shift);
02233 buff16[cnt + channelMap[0]] = Clamp16((vAvg + g) << shift);
02234 buff16[cnt + channelMap[3]] = Clamp16(aAvg << shift);
02235 yPos++;
02236 cnt += channels;
02237 if (j%2) sampledPos++;
02238 }
02239 buff16 += pitch16;
02240 if (wOdd) sampledPos++;
02241
02242 if (cb) {
02243 percent += dP;
02244 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02245 }
02246 }
02247 } else {
02248 ASSERT(bpp%8 == 0);
02249 const int shift = __max(0, UsedBitsPerChannel() - 8);
02250 channels = bpp/8; ASSERT(channels >= m_header.channels);
02251
02252 for (i=0; i < h; i++) {
02253 if (i%2) sampledPos -= (w + 1)/2;
02254 cnt = 0;
02255 for (j=0; j < w; j++) {
02256 if (m_downsample) {
02257
02258 uAvg = u[sampledPos];
02259 vAvg = v[sampledPos];
02260 aAvg = a[sampledPos] + yuvOffset16;
02261 } else {
02262 uAvg = u[yPos];
02263 vAvg = v[yPos];
02264 aAvg = a[yPos] + yuvOffset16;
02265 }
02266
02267 g = y[yPos] + yuvOffset16 - ((uAvg + vAvg ) >> 2);
02268 buff[cnt + channelMap[1]] = Clamp8(g >> shift);
02269 buff[cnt + channelMap[2]] = Clamp8((uAvg + g) >> shift);
02270 buff[cnt + channelMap[0]] = Clamp8((vAvg + g) >> shift);
02271 buff[cnt + channelMap[3]] = Clamp8(aAvg >> shift);
02272 yPos++;
02273 cnt += channels;
02274 if (j%2) sampledPos++;
02275 }
02276 buff += pitch;
02277 if (wOdd) sampledPos++;
02278
02279 if (cb) {
02280 percent += dP;
02281 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02282 }
02283 }
02284 }
02285 break;
02286 }
02287 #ifdef __PGF32SUPPORT__
02288 case ImageModeGray32:
02289 {
02290 ASSERT(m_header.channels == 1);
02291 ASSERT(m_header.bpp == 32);
02292
02293 const int yuvOffset31 = 1 << (UsedBitsPerChannel() - 1);
02294
02295 DataT* y = m_channel[0]; ASSERT(y);
02296
02297 if (bpp == 32) {
02298 const int shift = 31 - UsedBitsPerChannel(); ASSERT(shift >= 0);
02299 UINT32 *buff32 = (UINT32 *)buff;
02300 int pitch32 = pitch/4;
02301
02302 for (i=0; i < h; i++) {
02303 for (j=0; j < w; j++) {
02304 buff32[j] = Clamp31((y[yPos++] + yuvOffset31) << shift);
02305 }
02306 buff32 += pitch32;
02307
02308 if (cb) {
02309 percent += dP;
02310 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02311 }
02312 }
02313 } else if (bpp == 16) {
02314 const int usedBits = UsedBitsPerChannel();
02315 UINT16 *buff16 = (UINT16 *)buff;
02316 int pitch16 = pitch/2;
02317
02318 if (usedBits < 16) {
02319 const int shift = 16 - usedBits;
02320 for (i=0; i < h; i++) {
02321 for (j=0; j < w; j++) {
02322 buff16[j] = Clamp16((y[yPos++] + yuvOffset31) << shift);
02323 }
02324 buff16 += pitch16;
02325
02326 if (cb) {
02327 percent += dP;
02328 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02329 }
02330 }
02331 } else {
02332 const int shift = __max(0, usedBits - 16);
02333 for (i=0; i < h; i++) {
02334 for (j=0; j < w; j++) {
02335 buff16[j] = Clamp16((y[yPos++] + yuvOffset31) >> shift);
02336 }
02337 buff16 += pitch16;
02338
02339 if (cb) {
02340 percent += dP;
02341 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02342 }
02343 }
02344 }
02345 } else {
02346 ASSERT(bpp == 8);
02347 const int shift = __max(0, UsedBitsPerChannel() - 8);
02348
02349 for (i=0; i < h; i++) {
02350 for (j=0; j < w; j++) {
02351 buff[j] = Clamp8((y[yPos++] + yuvOffset31) >> shift);
02352 }
02353 buff += pitch;
02354
02355 if (cb) {
02356 percent += dP;
02357 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02358 }
02359 }
02360 }
02361 break;
02362 }
02363 #endif
02364 case ImageModeRGB12:
02365 {
02366 ASSERT(m_header.channels == 3);
02367 ASSERT(m_header.bpp == m_header.channels*4);
02368 ASSERT(bpp == m_header.channels*4);
02369 ASSERT(!m_downsample);
02370
02371 DataT* y = m_channel[0]; ASSERT(y);
02372 DataT* u = m_channel[1]; ASSERT(u);
02373 DataT* v = m_channel[2]; ASSERT(v);
02374 UINT16 yval;
02375 int cnt;
02376
02377 for (i=0; i < h; i++) {
02378 cnt = 0;
02379 for (j=0; j < w; j++) {
02380
02381 uAvg = u[yPos];
02382 vAvg = v[yPos];
02383 yval = Clamp4(y[yPos++] + YUVoffset4 - ((uAvg + vAvg ) >> 2));
02384 if (j%2 == 0) {
02385 buff[cnt] = UINT8(Clamp4(vAvg + yval) | (yval << 4));
02386 cnt++;
02387 buff[cnt] = Clamp4(uAvg + yval);
02388 } else {
02389 buff[cnt] |= Clamp4(vAvg + yval) << 4;
02390 cnt++;
02391 buff[cnt] = UINT8(yval | (Clamp4(uAvg + yval) << 4));
02392 cnt++;
02393 }
02394 }
02395 buff += pitch;
02396
02397 if (cb) {
02398 percent += dP;
02399 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02400 }
02401 }
02402 break;
02403 }
02404 case ImageModeRGB16:
02405 {
02406 ASSERT(m_header.channels == 3);
02407 ASSERT(m_header.bpp == 16);
02408 ASSERT(bpp == 16);
02409 ASSERT(!m_downsample);
02410
02411 DataT* y = m_channel[0]; ASSERT(y);
02412 DataT* u = m_channel[1]; ASSERT(u);
02413 DataT* v = m_channel[2]; ASSERT(v);
02414 UINT16 yval;
02415 UINT16 *buff16 = (UINT16 *)buff;
02416 int pitch16 = pitch/2;
02417
02418 for (i=0; i < h; i++) {
02419 for (j=0; j < w; j++) {
02420
02421 uAvg = u[yPos];
02422 vAvg = v[yPos];
02423 yval = Clamp6(y[yPos++] + YUVoffset6 - ((uAvg + vAvg ) >> 2));
02424 buff16[j] = (yval << 5) | ((Clamp6(uAvg + yval) >> 1) << 11) | (Clamp6(vAvg + yval) >> 1);
02425 }
02426 buff16 += pitch16;
02427
02428 if (cb) {
02429 percent += dP;
02430 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02431 }
02432 }
02433 break;
02434 }
02435 default:
02436 ASSERT(false);
02437 }
02438
02439 #ifdef __PGFROISUPPORT__
02440 if (targetBuff) {
02441
02442 if (bpp%8 == 0) {
02443 BYTE bypp = bpp/8;
02444 buff = buffStart + (levelRoi.top - roi.top)*pitch + (levelRoi.left - roi.left)*bypp;
02445 w = levelRoi.Width()*bypp;
02446 h = levelRoi.Height();
02447
02448 for (i=0; i < h; i++) {
02449 for (j=0; j < w; j++) {
02450 targetBuff[j] = buff[j];
02451 }
02452 targetBuff += targetPitch;
02453 buff += pitch;
02454 }
02455 } else {
02456
02457 }
02458
02459 delete[] buffStart; buffStart = 0;
02460 }
02461 #endif
02462 }
02463
02478 void CPGFImage::GetYUV(int pitch, DataT* buff, BYTE bpp, int channelMap[] , CallbackPtr cb , void *data ) const THROW_ {
02479 ASSERT(buff);
02480 const UINT32 w = m_width[0];
02481 const UINT32 h = m_height[0];
02482 const bool wOdd = (1 == w%2);
02483 const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
02484 const int pitch2 = pitch/DataTSize;
02485 const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
02486 const double dP = 1.0/h;
02487
02488 int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
02489 if (channelMap == NULL) channelMap = defMap;
02490 int sampledPos = 0, yPos = 0;
02491 DataT uAvg, vAvg;
02492 double percent = 0;
02493 UINT32 i, j;
02494
02495 if (m_header.channels == 3) {
02496 ASSERT(bpp%dataBits == 0);
02497
02498 DataT* y = m_channel[0]; ASSERT(y);
02499 DataT* u = m_channel[1]; ASSERT(u);
02500 DataT* v = m_channel[2]; ASSERT(v);
02501 int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02502
02503 for (i=0; i < h; i++) {
02504 if (i%2) sampledPos -= (w + 1)/2;
02505 cnt = 0;
02506 for (j=0; j < w; j++) {
02507 if (m_downsample) {
02508
02509 uAvg = u[sampledPos];
02510 vAvg = v[sampledPos];
02511 } else {
02512 uAvg = u[yPos];
02513 vAvg = v[yPos];
02514 }
02515 buff[cnt + channelMap[0]] = y[yPos];
02516 buff[cnt + channelMap[1]] = uAvg;
02517 buff[cnt + channelMap[2]] = vAvg;
02518 yPos++;
02519 cnt += channels;
02520 if (j%2) sampledPos++;
02521 }
02522 buff += pitch2;
02523 if (wOdd) sampledPos++;
02524
02525 if (cb) {
02526 percent += dP;
02527 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02528 }
02529 }
02530 } else if (m_header.channels == 4) {
02531 ASSERT(m_header.bpp == m_header.channels*8);
02532 ASSERT(bpp%dataBits == 0);
02533
02534 DataT* y = m_channel[0]; ASSERT(y);
02535 DataT* u = m_channel[1]; ASSERT(u);
02536 DataT* v = m_channel[2]; ASSERT(v);
02537 DataT* a = m_channel[3]; ASSERT(a);
02538 UINT8 aAvg;
02539 int cnt, channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02540
02541 for (i=0; i < h; i++) {
02542 if (i%2) sampledPos -= (w + 1)/2;
02543 cnt = 0;
02544 for (j=0; j < w; j++) {
02545 if (m_downsample) {
02546
02547 uAvg = u[sampledPos];
02548 vAvg = v[sampledPos];
02549 aAvg = Clamp8(a[sampledPos] + yuvOffset);
02550 } else {
02551 uAvg = u[yPos];
02552 vAvg = v[yPos];
02553 aAvg = Clamp8(a[yPos] + yuvOffset);
02554 }
02555
02556 buff[cnt + channelMap[0]] = y[yPos];
02557 buff[cnt + channelMap[1]] = uAvg;
02558 buff[cnt + channelMap[2]] = vAvg;
02559 buff[cnt + channelMap[3]] = aAvg;
02560 yPos++;
02561 cnt += channels;
02562 if (j%2) sampledPos++;
02563 }
02564 buff += pitch2;
02565 if (wOdd) sampledPos++;
02566
02567 if (cb) {
02568 percent += dP;
02569 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02570 }
02571 }
02572 }
02573 }
02574
02589 void CPGFImage::ImportYUV(int pitch, DataT *buff, BYTE bpp, int channelMap[] , CallbackPtr cb , void *data ) THROW_ {
02590 ASSERT(buff);
02591 const double dP = 1.0/m_header.height;
02592 const int dataBits = DataTSize*8; ASSERT(dataBits == 16 || dataBits == 32);
02593 const int pitch2 = pitch/DataTSize;
02594 const int yuvOffset = (dataBits == 16) ? YUVoffset8 : YUVoffset16;
02595
02596 int yPos = 0, cnt = 0;
02597 double percent = 0;
02598 int defMap[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; ASSERT(sizeof(defMap)/sizeof(defMap[0]) == MaxChannels);
02599
02600 if (channelMap == NULL) channelMap = defMap;
02601
02602 if (m_header.channels == 3) {
02603 ASSERT(bpp%dataBits == 0);
02604
02605 DataT* y = m_channel[0]; ASSERT(y);
02606 DataT* u = m_channel[1]; ASSERT(u);
02607 DataT* v = m_channel[2]; ASSERT(v);
02608 const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02609
02610 for (UINT32 h=0; h < m_header.height; h++) {
02611 if (cb) {
02612 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02613 percent += dP;
02614 }
02615
02616 cnt = 0;
02617 for (UINT32 w=0; w < m_header.width; w++) {
02618 y[yPos] = buff[cnt + channelMap[0]];
02619 u[yPos] = buff[cnt + channelMap[1]];
02620 v[yPos] = buff[cnt + channelMap[2]];
02621 yPos++;
02622 cnt += channels;
02623 }
02624 buff += pitch2;
02625 }
02626 } else if (m_header.channels == 4) {
02627 ASSERT(bpp%dataBits == 0);
02628
02629 DataT* y = m_channel[0]; ASSERT(y);
02630 DataT* u = m_channel[1]; ASSERT(u);
02631 DataT* v = m_channel[2]; ASSERT(v);
02632 DataT* a = m_channel[3]; ASSERT(a);
02633 const int channels = bpp/dataBits; ASSERT(channels >= m_header.channels);
02634
02635 for (UINT32 h=0; h < m_header.height; h++) {
02636 if (cb) {
02637 if ((*cb)(percent, true, data)) ReturnWithError(EscapePressed);
02638 percent += dP;
02639 }
02640
02641 cnt = 0;
02642 for (UINT32 w=0; w < m_header.width; w++) {
02643 y[yPos] = buff[cnt + channelMap[0]];
02644 u[yPos] = buff[cnt + channelMap[1]];
02645 v[yPos] = buff[cnt + channelMap[2]];
02646 a[yPos] = buff[cnt + channelMap[3]] - yuvOffset;
02647 yPos++;
02648 cnt += channels;
02649 }
02650 buff += pitch2;
02651 }
02652 }
02653
02654 if (m_downsample) {
02655
02656 for (int i=1; i < m_header.channels; i++) {
02657 Downsample(i);
02658 }
02659 }
02660 }
02661