00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 #include "camtypes.h"
00105
00106
00107
00108 #include "grndrgn.h"
00109
00110
00111
00112
00113
00114 #include "bitfilt.h"
00115 #include "bitmpinf.h"
00116 #include "progress.h"
00117 #include "tunemem.h"
00118
00119
00120 #include "oilbitmap.h"
00121
00122
00123 #include "gpalopt.h"
00124
00125 #include "hardwaremanager.h"
00126 using namespace oilHardwareManager;
00127
00128
00129 #define new CAM_DEBUG_NEW
00130
00131
00132
00133 #define DIB_DEBUG 0
00134
00135
00136
00137
00138 static BOOL RenderDirection4=FALSE;
00139 static BOOL RenderDirection8=FALSE;
00140 static BOOL RenderDirection16=TRUE;
00141 static BOOL RenderDirection24=FALSE;
00142
00143
00144
00145
00146
00147
00148
00149
00150 static UINT32 SubbandConversionSize=0x80000;
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 LPBITMAPINFO AllocDIB( UINT32 Width, UINT32 Height, UINT32 Depth, LPBYTE *Bits, MemoryBlock *Blk, BOOL UseLimitedHeap)
00182 {
00183 LPBITMAPINFO lpInfo;
00184
00185 ENSURE(Blk==NULL, "Cannot do blks yet");
00186
00187 INT32 size = DIBUtil::ScanlineSize( Width, Depth ) * Height;
00188 #if DIB_DEBUG
00189 const INT32 dbsize = DIBUtil::ScanlineSize( Width, Depth ) * DIB_DEBUG*2;
00190 if (dbsize<16)
00191 dbsize = 16;
00192 #else
00193 const INT32 dbsize = 0;
00194 #endif
00195
00196 if (size==0)
00197 size = 4;
00198
00199
00200 TunedMemory* pTuned = GetTunedMemManager();
00201
00202
00203 LPBYTE Bytes = NULL;
00204 if (Bits)
00205 {
00206
00207 *Bits = NULL;
00208
00209
00210 if (UseLimitedHeap)
00211 Bytes = (LPBYTE) pTuned->LimitedCCMalloc(size + dbsize + EXTRA_GAVIN_BYTES + DIBUtil::ScanlineSize(Width, Depth));
00212 else
00213 Bytes = (LPBYTE)CCMalloc(size + dbsize + EXTRA_GAVIN_BYTES + DIBUtil::ScanlineSize(Width, Depth));
00214
00215
00216 if (Bytes==NULL)
00217 return NULL;
00218 }
00219
00220
00221 size_t extras;
00222 INT32 used_cols = 0;
00223
00224 switch (Depth)
00225 {
00226 case 1:
00227 extras = 2*sizeof(COLORREF);
00228 used_cols = 2;
00229 break;
00230 case 4:
00231 extras = 16*sizeof(COLORREF);
00232 used_cols = 16;
00233 break;
00234 case 8:
00235 extras = 256*sizeof(COLORREF);
00236 used_cols = 256;
00237 break;
00238 case 16:
00239 extras = 3*sizeof(COLORREF);
00240 break;
00241 case 24:
00242 extras = 0;
00243 break;
00244 case 32:
00245 extras = 3*sizeof(COLORREF);
00246 break;
00247 default:
00248 ENSURE(FALSE, "Bad bitmap depth");
00249 return NULL;
00250 }
00251
00252
00253 if (UseLimitedHeap)
00254 lpInfo = (LPBITMAPINFO) pTuned->LimitedCCMalloc(sizeof(BITMAPINFO) + extras);
00255 else
00256 lpInfo = (LPBITMAPINFO) CCMalloc(sizeof(BITMAPINFO) + extras);
00257
00258
00259 if (lpInfo == NULL)
00260 {
00261
00262 if (UseLimitedHeap)
00263 pTuned->LimitedCCFree(Bytes);
00264 else
00265 CCFree(Bytes);
00266
00267 return NULL;
00268 }
00269
00270 lpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00271 lpInfo->bmiHeader.biWidth = Width;
00272 lpInfo->bmiHeader.biHeight = Height;
00273 lpInfo->bmiHeader.biPlanes = 1;
00274 lpInfo->bmiHeader.biBitCount = Depth;
00275 lpInfo->bmiHeader.biCompression = BI_RGB;
00276 lpInfo->bmiHeader.biXPelsPerMeter = 3780;
00277 lpInfo->bmiHeader.biYPelsPerMeter = 3780;
00278 lpInfo->bmiHeader.biClrUsed = used_cols;
00279 lpInfo->bmiHeader.biClrImportant = 0;
00280 lpInfo->bmiHeader.biSizeImage = size;
00281
00282 if (extras > 0)
00283 {
00284 memset(&(lpInfo->bmiColors[0]), 0, extras);
00285 }
00286
00287 if (Bits)
00288 {
00289 #if DIB_DEBUG
00290 const size_t count = DIBUtil::ScanlineSize( Width, Depth );
00291 memset( Bytes, 0x42, count*DIB_DEBUG );
00292 memset( Bytes + count * (Height + DIB_DEBUG), 0x42, count*DIB_DEBUG );
00293 Bytes += count * DIB_DEBUG;
00294 PINT32 lpLong = (PINT32) (Bytes-4);
00295 *lpLong = count;
00296 lpLong[-1] = (INT32)(Bytes + count * Height);
00297 #endif
00298 *Bits = Bytes;
00299 }
00300
00301 return lpInfo;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 void FreeDIB( LPBITMAPINFO lpInfo, LPBYTE Bits, MemoryBlock *Blk, BOOL UseLimitedHeap)
00322 {
00323 ENSURE(Blk==NULL, "Cannot free blocks");
00324 #if DIB_DEBUG
00325 if (Bits)
00326 {
00327 const size_t count = *(PINT32)(Bits-4);
00328 const LPBYTE endbuf= (LPBYTE)*(PINT32)(Bits-8);
00329 LPBYTE p = Bits - count * DIB_DEBUG;
00330 size_t i = count - 8;
00331 while (i--)
00332 {
00333 if (*p != 0x42)
00334 ENSURE(FALSE, "top of bitmap corrupted");
00335 p++;
00336 }
00337 p = endbuf;
00338 i = count;
00339 while (i--)
00340 {
00341 if (*p != 0x42)
00342 ENSURE(FALSE, "bottom of bitmap corrupted");
00343 p++;
00344 }
00345 Bits -= count * DIB_DEBUG;
00346 }
00347 #endif
00348
00349
00350 if (UseLimitedHeap)
00351 {
00352
00353 TunedMemory* pTuned = GetTunedMemManager();
00354 pTuned->LimitedCCFree(Bits);
00355 pTuned->LimitedCCFree(lpInfo);
00356 }
00357 else
00358 {
00359 CCFree(Bits);
00360 CCFree(lpInfo);
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 INT32 GetDIBBitsSize( LPBITMAPINFOHEADER bh )
00385 {
00386
00387
00388 return bh->biSizeImage;
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 UINT32 DIBUtil::ScanlineSize( UINT32 Width, UINT32 Depth )
00422 {
00423 switch (Depth)
00424 {
00425 case 1:
00426 return ((Width+31)&~31)>>3;
00427 case 2:
00428
00429 return ((Width+15)&~15)>>2;
00430 case 4:
00431 return ((Width+7)&~7)>>1;
00432 case 8:
00433 return ((Width+3)&~3);
00434 case 16:
00435 return ((Width+1)&~1)<<1;
00436 case 24:
00437
00438 return ((Width*3)+3)&~3;
00439 case 32:
00440 return Width<<2;
00441 default:
00442 ENSURE(FALSE, "Unknown bitmap depth");
00443 return 0L;
00444 }
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 UINT32 DIBUtil::ScanlineBytes( UINT32 Width, UINT32 Depth )
00465 {
00466 switch (Depth)
00467 {
00468 case 1:
00469 return Width >> 3;
00470 case 2:
00471 return Width >> 2;
00472 case 4:
00473 return Width >> 1;
00474 case 8:
00475 return Width;
00476 case 16:
00477 return Width << 1;
00478 case 24:
00479 ENSURE(FALSE, "Aren't 24-bit bitmaps stored in 32BPP???");
00480 return Width * 3;
00481 case 32:
00482 return Width << 2;
00483 default:
00484 ENSURE(FALSE, "Unknown bitmap depth");
00485 return 0L;
00486 }
00487 }
00488
00489
00490
00491
00492 #define EXPAND(x) ( (x<<3) | (x>>2) )
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 void DIBUtil::Convert16to24( INT32 PixelWidth, LPBYTE InputBits, LPBYTE OutputBits )
00508 {
00509 LPWORD Source = (LPWORD)InputBits;
00510
00511 while (PixelWidth--)
00512 {
00513 const WORD Data = *Source++;
00514
00515
00516
00517 const BYTE Blue = Data & 0x1F;
00518 *OutputBits++ = EXPAND(Blue);
00519
00520 const BYTE Green = (Data>>5) & 0x1F;
00521 *OutputBits++ = EXPAND(Green);
00522
00523 const BYTE Red = (Data>>10) & 0x1F;
00524 *OutputBits++ = EXPAND(Red);
00525 }
00526 }
00527
00528
00529 void DIBUtil::Convert32to24( INT32 PixelWidth, LPBYTE InputBits, LPBYTE OutputBits )
00530 {
00531
00532
00533
00534 while (PixelWidth--)
00535 {
00536 OutputBits[0] = InputBits[0];
00537 OutputBits[1] = InputBits[1];
00538 OutputBits[2] = InputBits[2];
00539 OutputBits += 3;
00540 InputBits += 4;
00541 }
00542 }
00543
00544
00545
00546 void DIBUtil::Convert32to24Alpha(INT32 PixelWidth, LPBYTE InputBits, LPBYTE OutputBits, COLORREF Colour)
00547 {
00548
00549
00550
00551 const BYTE RedBG = (BYTE)(Colour & 0xFF);
00552 const BYTE GreenBG = (BYTE)((Colour >> 8) & 0xFF);
00553 const BYTE BlueBG = (BYTE)((Colour >> 16) & 0xFF);
00554
00555 while (PixelWidth--)
00556 {
00557 const BYTE Trans = InputBits[3];
00558 const BYTE Alpha = 255 - Trans;
00559 OutputBits[0] = ((InputBits[0] * Alpha) + (RedBG * Trans)) / 255;
00560 OutputBits[1] = ((InputBits[1] * Alpha) + (GreenBG * Trans)) / 255;
00561 OutputBits[2] = ((InputBits[2] * Alpha) + (BlueBG * Trans)) / 255;
00562 OutputBits += 3;
00563 InputBits += 4;
00564 }
00565 }
00566
00567
00568
00569 void DIBUtil::Convert32to32( INT32 PixelWidth, LPBYTE InputBits, LPBYTE OutputBits )
00570 {
00571
00572 LPDWORD Source = (LPDWORD)InputBits;
00573 LPDWORD Dest = (LPDWORD)OutputBits;
00574 while (PixelWidth--)
00575 {
00576
00577 *Dest++ = *Source++;
00578 }
00579 }
00580
00581
00582
00583 void DIBUtil::Convert8to8( INT32 PixelWidth, LPBYTE InputBits, LPBYTE OutputBits )
00584 {
00585 LPBYTE Source = (LPBYTE)InputBits;
00586 LPBYTE Dest = (LPBYTE)OutputBits;
00587 while (PixelWidth--)
00588 {
00589 *Dest++ = *Source++;
00590 }
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 BOOL DIBUtil::PlotDeepDIB( wxDC *pDC, LPBITMAPINFO lpBitmapInfo, LPBYTE lpBits, INT32 Left, INT32 Top, INT32 Width, INT32 Height, INT32 SourceLeft, INT32 SourceTop, BitmapConvertHint Hint, HPALETTE hPal)
00627 {
00628 PORTNOTETRACE("other","DIBUtil::PlotDeepDIB - do nothing");
00629 #ifndef EXCLUDE_FROM_XARALX
00630 const WORD BitmapDepth = lpBitmapInfo->bmiHeader.biBitCount;
00631
00632 ERROR2IF( BitmapDepth!=16 && BitmapDepth!=32, FALSE, "Wrong depth deep bitmap" );
00633
00634 INT32 DitherMode = 0;
00635 BOOL UseGavin = FALSE;
00636 UINT32 TempBitmapDepth = 24;
00637
00638
00639 if (BitmapDepth==32)
00640 {
00641
00642
00643 switch (Hint)
00644 {
00645 case CONVHINT_NONE:
00646
00647 break;
00648 case CONVHINT_PRINTER:
00649
00650 break;
00651 case CONVHINT_FINAL24:
00652
00653 DitherMode=8;
00654 UseGavin=TRUE;
00655 break;
00656 case CONVHINT_FINAL16:
00657 DitherMode = 2;
00658 UseGavin = TRUE;
00659 break;
00660 case CONVHINT_FINAL555:
00661 DitherMode = 2;
00662 UseGavin = TRUE;
00663 break;
00664 case CONVHINT_FINAL565:
00665 DitherMode = 0;
00666 UseGavin = TRUE;
00667 break;
00668 case CONVHINT_FINAL655:
00669 DitherMode = 1;
00670 UseGavin = TRUE;
00671 break;
00672 case CONVHINT_FINAL664:
00673 DitherMode = 3;
00674 UseGavin = TRUE;
00675 break;
00676 case CONVHINT_SCREEN8:
00677 DitherMode = 1;
00678 UseGavin = TRUE;
00679 TempBitmapDepth = 8;
00680 break;
00681 case CONVHINT_SCREEN4:
00682 DitherMode = 1;
00683 UseGavin = TRUE;
00684 TempBitmapDepth = 4;
00685 break;
00686 default:
00687 ERROR3( "Strange hint in PlotDeepDIB" );
00688 return FALSE;
00689 break;
00690 }
00691 }
00692
00693 if (BitmapDepth==16)
00694 {
00695 DitherMode=2;
00696 UseGavin=TRUE;
00697 }
00698
00699
00700 const INT32 ScanlineBytes = ScanlineSize( lpBitmapInfo->bmiHeader.biWidth, BitmapDepth );
00701
00702 BOOL PlotDownwards = RenderDirection8;
00703
00704
00705
00706 switch (Hint)
00707 {
00708 case CONVHINT_SCREEN4:
00709 PlotDownwards = RenderDirection4; break;
00710
00711 case CONVHINT_PRINTER:
00712 PlotDownwards = FALSE; break;
00713
00714 case CONVHINT_FINAL24:
00715 PlotDownwards = RenderDirection24; break;
00716
00717 case CONVHINT_FINAL16:
00718 case CONVHINT_FINAL555:
00719 case CONVHINT_FINAL565:
00720 case CONVHINT_FINAL655:
00721 case CONVHINT_FINAL664:
00722 PlotDownwards = RenderDirection16; break;
00723
00724 case CONVHINT_NONE:
00725 case CONVHINT_SCREEN8:
00726 default:
00727 PlotDownwards = RenderDirection8; break;
00728 }
00729
00730
00731
00732
00733
00734 if ( BitmapDepth==16 && UseGavin && (SourceLeft & 1)!=0 )
00735 {
00736 SourceLeft--;
00737 Left--;
00738 Width++;
00739 }
00740
00741
00742 lpBits += SourceLeft << ( BitmapDepth==16 ? 1 : 2 );
00743
00744 lpBits += (lpBitmapInfo->bmiHeader.biHeight - ((PlotDownwards?0:Height) + SourceTop) ) * ScanlineBytes;
00745
00746
00747
00748 INT32 SliceWidth = UseGavin ? lpBitmapInfo->bmiHeader.biWidth : Width;
00749
00750
00751 const INT32 DestlineBytes = ScanlineSize( SliceWidth, TempBitmapDepth );
00752
00753
00754
00755 INT32 SliceHeight = SubbandConversionSize / DestlineBytes;
00756 if (SliceHeight<4)
00757 SliceHeight=4;
00758 else
00759 SliceHeight = (SliceHeight+3) & ~3;
00760
00761 if (SliceHeight>Height) SliceHeight=Height;
00762
00763 INT32 OurSliceHeight=SliceHeight;
00764
00765 if (PlotDownwards)
00766 {
00767
00768
00769 SliceHeight=Height;
00770 while (OurSliceHeight>SliceHeight)
00771 OurSliceHeight-=Height;
00772 }
00773
00774
00775
00776
00777
00778 LPBYTE Buffer;
00779 LPBITMAPINFO BufferDIB = AllocDIB( SliceWidth, SliceHeight, TempBitmapDepth, &Buffer, NULL );
00780
00781 ERROR1IF( BufferDIB==NULL, FALSE, _R(IDS_OUT_OF_MEMORY) );
00782
00783 INT32 ColourFlag = 0;
00784
00785 if (TempBitmapDepth<24)
00786 {
00787
00788 ColourFlag = GRenderRegion::SetPaletteEntries( BufferDIB, pDC );
00789 }
00790
00791
00792 INT32 DestY = Top + (PlotDownwards?0:Height);
00793 INT32 ThisSlice;
00794
00795 FNPTR_SCANLINE ConvertFn = NULL;
00796 INT32 RealHeight = lpBitmapInfo->bmiHeader.biHeight;
00797
00798 if (!UseGavin)
00799 {
00800
00801 ConvertFn = BitmapDepth==16 ? Convert16to24 : Convert32to24;
00802 }
00803
00804
00805 while (Height)
00806 {
00807
00808 ThisSlice = min(OurSliceHeight, Height);
00809 OurSliceHeight=SliceHeight;
00810
00811 if (UseGavin)
00812 {
00813
00814 lpBitmapInfo->bmiHeader.biHeight = ThisSlice;
00815 BufferDIB->bmiHeader.biHeight = ThisSlice;
00816
00817
00818
00819 if (PlotDownwards) lpBits -= ThisSlice * ScanlineBytes;
00820
00821 GRenderRegion::GetStaticDrawContext()->ConvertBitmap( &lpBitmapInfo->bmiHeader, lpBits,
00822 &BufferDIB->bmiHeader, Buffer, DitherMode );
00823
00824 if (!PlotDownwards) lpBits += ThisSlice * ScanlineBytes;
00825
00826 }
00827 else
00828 {
00829
00830 LPBYTE ConvertedBuffer = Buffer;
00831 if (PlotDownwards) lpBits -= ThisSlice * ScanlineBytes;
00832 for (INT32 i=0; i<ThisSlice; i++)
00833 {
00834 ConvertFn( Width, lpBits, ConvertedBuffer );
00835 lpBits += ScanlineBytes;
00836 ConvertedBuffer += DestlineBytes;
00837 }
00838 if (PlotDownwards) lpBits -= ThisSlice * ScanlineBytes;
00839 }
00840
00841
00842
00843 if (!PlotDownwards) DestY -= ThisSlice;
00844
00845 if( Hint == CONVHINT_PRINTER )
00846 {
00847
00848 StretchDIBits( hDC, Left, DestY,
00849 Width, ThisSlice,
00850 0,0,
00851 Width, ThisSlice,
00852 Buffer, BufferDIB,
00853 DIB_RGB_COLORS,
00854 SRCCOPY );
00855 }
00856 else if (TempBitmapDepth<24)
00857 {
00858
00859 GRenderRegion::PlotBitmap( hDC, ColourFlag, BufferDIB, Buffer, Left, DestY,
00860 Width, ThisSlice, hPal, 0,0 );
00861 }
00862 else
00863 {
00864 INT32 num = SetDIBitsToDevice( hDC, Left, DestY,
00865 Width, ThisSlice,
00866 0,0,
00867 0,ThisSlice,
00868 Buffer, BufferDIB,
00869 DIB_RGB_COLORS );
00870
00871 }
00872
00873 if (PlotDownwards) DestY += ThisSlice;
00874 Height -= ThisSlice;
00875 }
00876
00877 if (UseGavin)
00878 lpBitmapInfo->bmiHeader.biHeight = RealHeight;
00879
00880 FreeDIB( BufferDIB, Buffer );
00881 #endif
00882 return TRUE;
00883 }
00884
00885 #define RLE_ESCAPE 0
00886 #define RLE_EOL 0
00887 #define RLE_EOF 1
00888 #define RLE_JMP 2
00889 #define RLE_RUN 3
00890
00891
00892
00893
00894 static BOOL UnpackRle8( CCLexFile *File, const BITMAPINFOHEADER& Header, LPBYTE Bits )
00895 {
00896 BYTE Buffer[2];
00897 BYTE cnt;
00898 BYTE b;
00899 WORD x;
00900 WORD dx,dy;
00901 DWORD wWidthBytes;
00902
00903 wWidthBytes = Header.biWidth+3 & ~3;
00904
00905 x = 0;
00906
00907 for(;;)
00908 {
00909 if (File->read( Buffer, 2 ).bad())
00910 return FALSE;
00911 cnt = Buffer[0];
00912 b = Buffer[1];
00913
00914 if (cnt == RLE_ESCAPE)
00915 {
00916 switch (b)
00917 {
00918 case RLE_EOF:
00919 return TRUE;
00920
00921 case RLE_EOL:
00922 Bits += wWidthBytes - x;
00923 x = 0;
00924 break;
00925
00926 case RLE_JMP:
00927 if (File->read( Buffer, 2 ).bad())
00928 return FALSE;
00929 dx = (WORD)Buffer[0];
00930 dy = (WORD)Buffer[1];
00931
00932 Bits += wWidthBytes * dy + dx;
00933 x += dx;
00934
00935 break;
00936
00937 default:
00938 cnt = b;
00939 x += cnt;
00940 if (File->read( Bits, cnt ).bad())
00941 return FALSE;
00942 Bits += cnt;
00943
00944 if (b & 1)
00945 {
00946 if (File->read( Buffer, 1).bad())
00947 return FALSE;
00948 }
00949
00950 break;
00951 }
00952 }
00953 else
00954 {
00955 x += cnt;
00956
00957 while (cnt-- > 0)
00958 *Bits++ = b;
00959 }
00960 }
00961 return TRUE;
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 static void ReadPalette( CCLexFile *File, INT32 HowMany, size_t SizeOfRGB, LPRGBQUAD Result )
00982 {
00983
00984 while (HowMany--)
00985 {
00986
00987 File->read( &(Result->rgbBlue), sizeof(BYTE));
00988 File->read( &(Result->rgbGreen), sizeof(BYTE));
00989 File->read( &(Result->rgbRed), sizeof(BYTE));
00990 if (SizeOfRGB==sizeof(RGBQUAD))
00991 {
00992 File->read( &(Result->rgbReserved), sizeof(BYTE));
00993 }
00994 else if (SizeOfRGB==sizeof(RGBTRIPLE))
00995 {
00996 Result->rgbReserved=0;
00997 }
00998 else
00999 {
01000 ENSURE(FALSE, "Strange RGB size if ReadPalette");
01001 }
01002 Result++;
01003 }
01004 }
01005
01006
01007 #define FAKE_32_TRANS 0
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 BOOL DIBUtil::CanReadFromFile( const BitmapInfo *pInfo )
01029 {
01030 ERROR2IF(pInfo==NULL,FALSE,"CanReadFromFile BitmapInfo pointer is null");
01031 BOOL Understand = FALSE;
01032
01033
01034 INT32 Depth = pInfo->PixelDepth;
01035 TRACEUSER( "Neville", wxT("DIBUtil::CanReadFromFile depth = %d\n"), Depth );
01036 if (Depth == 32)
01037 Understand = TRUE;
01038 else
01039 Understand = FALSE;
01040
01041 return Understand;
01042 }
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 BOOL DIBUtil::CanReadFromFile( const LPBITMAPCOREHEADER pCoreHeader )
01063 {
01064 ERROR2IF(pCoreHeader==NULL,FALSE,"CanReadFromFile CoreHeader pointer is null");
01065 BOOL Understand = FALSE;
01066
01067
01068 INT32 Depth = pCoreHeader->bcBitCount;
01069 TRACEUSER( "Neville", wxT("DIBUtil::CanReadFromFile OS/2 type depth = %d\n"), Depth );
01070 if (Depth == 32)
01071 Understand = TRUE;
01072 else
01073 Understand = FALSE;
01074
01075 return Understand;
01076 }
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 BOOL DIBUtil::CanReadFromFile( const LPBITMAPINFOHEADER pInfoHeader )
01097 {
01098 ERROR2IF(pInfoHeader==NULL,FALSE,"CanReadFromFile InfoHeader pointer is null");
01099 BOOL Understand = FALSE;
01100
01101
01102 INT32 Depth = pInfoHeader->biBitCount;
01103 TRACEUSER( "Neville", wxT("DIBUtil::CanReadFromFile Win 3.0+ type depth = %d\n"), Depth );
01104 if (Depth == 32)
01105 Understand = TRUE;
01106 else
01107 Understand = FALSE;
01108
01109 return Understand;
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 BOOL DIBUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits, BOOL ReadHeader,
01145 String_64 *ProgressString, BaseCamelotFilter *pFilter )
01146 {
01147 ERROR2IF(File == NULL,FALSE,"DIBUtil::ReadFromFile null File pointer");
01148 ERROR2IF(Info == NULL,FALSE,"DIBUtil::ReadFromFile null Info pointer");
01149 ERROR2IF(Bits == NULL,FALSE,"DIBUtil::ReadFromFile null Bits pointer");
01150
01151 BITMAPINFOHEADER InfoHeader;
01152 UINT32 Depth;
01153 DWORD BitsSize=0;
01154 INT32 SizeOfHeader = 0;
01155
01156 *Info = NULL;
01157 *Bits = NULL;
01158
01159
01160
01161
01162
01163
01164 BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
01165 BOOL OldReportingState = File->SetReportErrors( FALSE );
01166
01167
01168
01169 if (ProgressString != NULL)
01170 {
01171 BeginSlowJob(100, FALSE, ProgressString);
01172 }
01173
01174 try
01175 {
01176 if (ReadHeader)
01177 {
01178 BITMAPFILEHEADER Header;
01179
01180 File->read( &Header, sizeof(Header) );
01181 Header.bfType = LEtoNative(Header.bfType);
01182 Header.bfSize = LEtoNative(UINT32(Header.bfSize));
01183 Header.bfReserved1 = LEtoNative(Header.bfReserved1);
01184 Header.bfReserved2 = LEtoNative(Header.bfReserved2);
01185 Header.bfOffBits = LEtoNative(UINT32(Header.bfOffBits));
01186
01187 if (File->bad())
01188 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01189
01190 if (Header.bfType != 0x4D42)
01191 File->GotError( _R(IDE_BADFORMAT) );
01192 }
01193
01194
01195 size_t SizeOfRGB=0;
01196
01197 File->read( &SizeOfHeader, sizeof(INT32) );
01198 SizeOfHeader = LEtoNative(SizeOfHeader);
01199 if ( SizeOfHeader==sizeof(InfoHeader) )
01200 {
01201
01202 SizeOfRGB = sizeof(RGBQUAD);
01203 File->read( &InfoHeader.biWidth, sizeof(InfoHeader)-sizeof(INT32) );
01204
01205 InfoHeader.biWidth = LEtoNative(InfoHeader.biWidth);
01206 InfoHeader.biHeight = LEtoNative(InfoHeader.biHeight);
01207 InfoHeader.biPlanes = LEtoNative(InfoHeader.biPlanes);
01208 InfoHeader.biBitCount = LEtoNative(InfoHeader.biBitCount);
01209 InfoHeader.biCompression = LEtoNative(UINT32(InfoHeader.biCompression));
01210 InfoHeader.biSizeImage = LEtoNative(UINT32(InfoHeader.biSizeImage));
01211 InfoHeader.biXPelsPerMeter = LEtoNative(InfoHeader.biXPelsPerMeter);
01212 InfoHeader.biYPelsPerMeter = LEtoNative(InfoHeader.biYPelsPerMeter);
01213 InfoHeader.biClrUsed = LEtoNative(UINT32(InfoHeader.biClrUsed));
01214 InfoHeader.biClrImportant = LEtoNative(UINT32(InfoHeader.biClrImportant));
01215 }
01216 else if ( SizeOfHeader==sizeof(BITMAPCOREHEADER) )
01217 {
01218
01219 BITMAPCOREHEADER TempHeader;
01220 File->read( &TempHeader.bcWidth, sizeof(TempHeader)-sizeof(INT32) );
01221
01222 TempHeader.bcWidth = LEtoNative(TempHeader.bcWidth);
01223 TempHeader.bcHeight = LEtoNative(TempHeader.bcHeight);
01224 TempHeader.bcPlanes = LEtoNative(TempHeader.bcPlanes);
01225 TempHeader.bcBitCount = LEtoNative(TempHeader.bcBitCount);
01226
01227 SizeOfRGB = sizeof(RGBTRIPLE);
01228 InfoHeader.biWidth = TempHeader.bcWidth;
01229 InfoHeader.biHeight = TempHeader.bcHeight;
01230 InfoHeader.biPlanes = TempHeader.bcPlanes;
01231 InfoHeader.biBitCount = TempHeader.bcBitCount;
01232 InfoHeader.biCompression = BI_RGB;
01233 InfoHeader.biSizeImage = 0L;
01234 InfoHeader.biXPelsPerMeter = 0L;
01235 InfoHeader.biYPelsPerMeter = 0L;
01236 InfoHeader.biClrImportant = 0;
01237 if (InfoHeader.biBitCount < 24 )
01238 InfoHeader.biClrUsed = 1<<InfoHeader.biBitCount;
01239 else
01240 InfoHeader.biClrUsed = 0;
01241 }
01242 else
01243 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01244
01245
01246 if (File->bad())
01247 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01248
01249 if (InfoHeader.biWidth == 0 || InfoHeader.biHeight == 0 )
01250 File->GotError( _R(IDE_BADFORMAT) );
01251
01252 if (InfoHeader.biPlanes != 1)
01253 File->GotError( _R(IDE_BADFORMAT) );
01254
01255 Depth = InfoHeader.biBitCount;
01256
01257 BOOL Convert16to24 = FALSE;
01258 if (InfoHeader.biBitCount == 16 && InfoHeader.biCompression == BI_BITFIELDS)
01259 {
01260
01261 Depth = 24;
01262 Convert16to24 = TRUE;
01263 }
01264
01265
01266 if ( (Depth != 1) && (Depth != 4) && (Depth != 8) && (Depth != 24) && (Depth != 32))
01267 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01268
01269
01270 *Info = AllocDIB( InfoHeader.biWidth, InfoHeader.biHeight, Depth,
01271 Bits, NULL );
01272
01273 if (*Info == NULL)
01274 File->GotError( _R(IDS_OUT_OF_MEMORY) );
01275
01276
01277
01278
01279
01280
01281 TRACEUSER( "Neville", _T("DIBUtil::ReadFromFile XPelsPerMeter=%d\n"),InfoHeader.biXPelsPerMeter);
01282 TRACEUSER( "Neville", _T("DIBUtil::ReadFromFile YPelsPerMeter=%d\n"),InfoHeader.biYPelsPerMeter);
01283 if (InfoHeader.biXPelsPerMeter > BaseBitmapFilter::MinPelsPerMeter)
01284 {
01285 (*Info)->bmiHeader.biXPelsPerMeter = InfoHeader.biXPelsPerMeter;
01286 (*Info)->bmiHeader.biYPelsPerMeter = InfoHeader.biYPelsPerMeter;
01287 }
01288 else
01289 {
01290 (*Info)->bmiHeader.biXPelsPerMeter = 0;
01291 (*Info)->bmiHeader.biYPelsPerMeter = 0;
01292 }
01293
01294
01295
01296
01297 UINT32 PalColours = 0;
01298 if (Depth <= 8)
01299 {
01300 PalColours = InfoHeader.biClrUsed;
01301
01302
01303 if (InfoHeader.biClrUsed == 0)
01304 {
01305 (*Info)->bmiHeader.biClrUsed = 1<<Depth;
01306 PalColours = 1<<Depth;
01307 }
01308 else
01309 (*Info)->bmiHeader.biClrUsed = InfoHeader.biClrUsed;
01310 }
01311
01312
01313 switch (Depth)
01314 {
01315 case 1:
01316 case 4:
01317 case 8:
01318
01319 ReadPalette( File, PalColours, SizeOfRGB, (*Info)->bmiColors);
01320 break;
01321
01322 case 24:
01323 case 32:
01324
01325
01326
01327 if (InfoHeader.biClrUsed)
01328 File->seekIn( InfoHeader.biClrUsed * SizeOfRGB, ios::cur );
01329 break;
01330
01331 default:
01332 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01333 }
01334
01335 if (File->bad())
01336 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01337
01338
01339
01340 UINT32 RedColourMask = 0;
01341 UINT32 GreenColourMask = 0;
01342 UINT32 BlueColourMask = 0;
01343 switch (InfoHeader.biCompression)
01344 {
01345 case BI_RGB:
01346 BitsSize = (*Info)->bmiHeader.biSizeImage;
01347 break;
01348
01349 case CC_BMPTYPE:
01350 if (Depth != 32)
01351 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01352 BitsSize = (*Info)->bmiHeader.biSizeImage;
01353 break;
01354
01355 case BI_RLE8:
01356 if (!UnpackRle8( File, InfoHeader, *Bits ))
01357 File->GotError( _R(IDE_BADFORMAT) );
01358 BitsSize = 0L;
01359 break;
01360
01361 case BI_BITFIELDS:
01362
01363 BitsSize = (*Info)->bmiHeader.biSizeImage;
01364 File->read( &RedColourMask, sizeof(RedColourMask) );
01365 File->read( &GreenColourMask, sizeof(GreenColourMask) );
01366 File->read( &BlueColourMask, sizeof(BlueColourMask) );
01367
01368 RedColourMask = LEtoNative(RedColourMask);
01369 GreenColourMask = LEtoNative(GreenColourMask);
01370 BlueColourMask = LEtoNative(BlueColourMask);
01371
01372 if (File->bad())
01373 File->GotError( _R(IDE_BADFORMAT) );
01374 TRACEUSER( "Neville", _T("DIBUtil::ReadFromFile BI_BITFIELDS RedColourMask = %d\n"),RedColourMask);
01375 TRACEUSER( "Neville", _T("DIBUtil::ReadFromFile BI_BITFIELDS GreenColourMask = %d\n"),GreenColourMask);
01376 TRACEUSER( "Neville", _T("DIBUtil::ReadFromFile BI_BITFIELDS BlueColourMask = %d\n"),BlueColourMask);
01377
01378
01379
01380 if (Depth == 32 && RedColourMask != 0xFF0000 && GreenColourMask != 0xFF00 && BlueColourMask != 0xFF)
01381 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01382 else if (Depth != 24 && Depth != 32)
01383 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01384 break;
01385
01386 default:
01387 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01388 }
01389
01390 if (Convert16to24 == TRUE && Depth == 24)
01391 {
01392
01393
01394
01395
01396
01397
01398
01399
01400 WORD Pixel = 0;
01401 INT32 Bshift = 0;
01402 if (BlueColourMask != 0x1F)
01403 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01404
01405 INT32 Gshift = 0;
01406 if (GreenColourMask == 0x7e0 || GreenColourMask == 0x3e0)
01407 Gshift = 5;
01408 else
01409 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01410
01411 INT32 Rshift = 0;
01412 if (RedColourMask == 0x7c00)
01413 Rshift = 10;
01414 else if (RedColourMask == 0xf800)
01415 Rshift = 11;
01416 else
01417 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01418
01419 UINT32 ScanLineWidth = DIBUtil::ScanlineSize(InfoHeader.biWidth, Depth);
01420 LPBYTE pBits = *Bits;
01421 INT32 Height = InfoHeader.biHeight;
01422 INT32 Width = InfoHeader.biWidth;
01423 for (INT32 y = 0; y < Height; y++ )
01424 {
01425 for (INT32 x = 0; x < Width; x++ )
01426 {
01427
01428 File->read( &Pixel, sizeof(Pixel) );
01429
01430 Pixel = LEtoNative(Pixel);
01431
01432 if (File->bad())
01433 File->GotError( _R(IDE_BADFORMAT) );
01434
01435 UINT32 B = ((Pixel & BlueColourMask) >> Bshift);
01436 UINT32 G = ((Pixel & GreenColourMask) >> Gshift);
01437 UINT32 R = ((Pixel & RedColourMask) >> Rshift);
01438
01439
01440 pBits[x * 3 + 0] = (B << 3) | (B >> 2);
01441 if (GreenColourMask == 0x7e0)
01442 pBits[x * 3 + 1] = (G << 2) | (G >> 4);
01443 else
01444 pBits[x * 3 + 1] = (G << 3) | (G >> 2);
01445 pBits[x * 3 + 2] = (R << 3) | (R >> 2);
01446 }
01447
01448
01449 pBits += ScanLineWidth;
01450
01451 ContinueSlowJob((INT32)((100 * y)/Height));
01452 }
01453 }
01454
01455
01456 else if (BitsSize > 0)
01457 {
01458
01459
01460 if (pFilter == NULL)
01461 {
01462 if (BitsSize < 1024 || ProgressString == NULL)
01463 {
01464
01465 File->read( *Bits, BitsSize );
01466 }
01467 else
01468 {
01469
01470 DWORD ChunkSize = BitsSize/100;
01471 DWORD Position = 0;
01472 LPBYTE pBitInfo = *Bits;
01473
01474 while (Position < BitsSize)
01475 {
01476 if ( (BitsSize - Position) > ChunkSize)
01477 File->read( pBitInfo, ChunkSize );
01478 else
01479 {
01480 ChunkSize = BitsSize - Position;
01481 File->read( pBitInfo, ChunkSize );
01482 }
01483
01484
01485 Position += ChunkSize;
01486 pBitInfo += ChunkSize;
01487 ContinueSlowJob((INT32)(100*Position/BitsSize));
01488 }
01489 }
01490 }
01491 else
01492 {
01493
01494
01495 LPBYTE pBitInfo = *Bits;
01496 UINT32 ScanLineWidth = DIBUtil::ScanlineSize(InfoHeader.biWidth, Depth);
01497 UINT32 height = InfoHeader.biHeight;
01498
01499
01500
01501
01502
01503
01504 UINT32 RecordSize = pFilter->GetCurrentRecordSize();
01505 if (RecordSize == 0)
01506 RecordSize = 1;
01507 INT32 UpdateValue = RecordSize/height;
01508
01509 for (UINT32 i = 0; i < height; i++)
01510 {
01511 File->read( pBitInfo, ScanLineWidth );
01512 pBitInfo += ScanLineWidth;
01513 pFilter->IncProgressBarCount(UpdateValue);
01514 }
01515 }
01516 }
01517
01518
01519
01520 if (File->bad())
01521 File->GotError( _R(IDE_FORMATNOTSUPPORTED) );
01522
01523 if (FAKE_32_TRANS && (Depth==32) && (InfoHeader.biCompression!=CC_BMPTYPE) )
01524 {
01525
01526 LPRGBQUAD Data = (LPRGBQUAD)(*Bits);
01527
01528 UINT32 Height = (*Info)->bmiHeader.biHeight;
01529 UINT32 h = Height;
01530 Height /= 2;
01531
01532 while (h--)
01533 {
01534 INT32 TValue = (INT32)h - (INT32)Height;
01535 TValue = abs(TValue);
01536 TValue = TValue * 0xFF / Height;
01537
01538 UINT32 w = (*Info)->bmiHeader.biWidth;
01539 while (w--)
01540 {
01541 Data->rgbReserved = (BYTE)TValue;
01542 Data++;
01543 }
01544
01545 }
01546 }
01547
01548
01549 if (ProgressString != NULL)
01550 {
01551 EndSlowJob();
01552 }
01553
01554
01555 File->SetThrowExceptions( OldThrowingState );
01556 File->SetReportErrors( OldReportingState );
01557
01558
01559 return TRUE;
01560 }
01561 catch( CFileException )
01562 {
01563
01564 TRACE( _T("DIBUtil::ReadFromFile CC catch handler\n"));
01565
01566 FreeDIB( *Info, *Bits );
01567 *Info = NULL;
01568 *Bits = NULL;
01569
01570
01571 if (ProgressString != NULL)
01572 {
01573 EndSlowJob();
01574 }
01575
01576
01577 File->SetThrowExceptions( OldThrowingState );
01578 File->SetReportErrors( OldReportingState );
01579
01580 return FALSE;
01581 }
01582
01583 ERROR2( FALSE, "Escaped exception clause somehow" );
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621 BOOL DIBUtil::WriteToFile ( CCLexFile *File, LPBITMAPINFO Info, LPBYTE Bits, String_64 *ProgressString, BOOL WriteHeader, BaseCamelotFilter *pFilter)
01622 {
01623 #ifndef WIN32
01624 Error::SetError( _R(IDE_BADFORMAT) );
01625 return FALSE;
01626 #else
01627 ERROR2IF(File==NULL,FALSE,"DIBUtil::WriteToFile File pointer is null");
01628 ERROR2IF(Info==NULL,FALSE,"DIBUtil::WriteToFile BitmapInfo pointer is null");
01629 ERROR2IF(Bits==NULL,FALSE,"DIBUtil::WriteToFile Bits pointer is null");
01630
01631
01632
01633
01634
01635
01636 BOOL OldThrowingState = File->SetThrowExceptions( TRUE );
01637 BOOL OldReportingState = File->SetReportErrors( FALSE );
01638
01639
01640
01641 if (ProgressString != NULL)
01642 {
01643 BeginSlowJob(100, FALSE, ProgressString);
01644 }
01645
01646 try
01647 {
01648
01649
01650
01651 LPBITMAPINFOHEADER pInfoHeader = &Info->bmiHeader;
01652 ERROR2IF(pInfoHeader==NULL,FALSE,"DIBUtil::WriteToFile BitmapInfoHeader pointer is null");
01653
01654
01655 INT32 PalSize = Info->bmiHeader.biClrUsed;
01656 TRACEUSER( "Neville", _T("DIBUtil::WriteToFile PalSize = %d\n"),PalSize);
01657 TRACEUSER( "Neville", _T("DIBUtil::WriteToFile XPelsPerMeter=%d\n"),pInfoHeader->biXPelsPerMeter);
01658 TRACEUSER( "Neville", _T("DIBUtil::WriteToFile YPelsPerMeter=%d\n"),pInfoHeader->biYPelsPerMeter);
01659
01660 if (WriteHeader)
01661 {
01662
01663 BITMAPFILEHEADER Header;
01664
01665 Header.bfType = ('M'<<8) | 'B';
01666 Header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
01667 sizeof(RGBQUAD)*PalSize + pInfoHeader->biSizeImage;
01668 Header.bfReserved1 = 0;
01669 Header.bfReserved2 = 0;
01670 Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
01671 sizeof(RGBQUAD)*PalSize;
01672
01673
01674 File->write( &Header, sizeof(Header) );
01675 }
01676
01677
01678
01679 File->write( pInfoHeader, sizeof(BITMAPINFOHEADER) );
01680
01681
01682 if (PalSize)
01683 {
01684
01685 const UINT32 TotalPal = sizeof(PALETTEENTRY) * PalSize;
01686 File->write( Info->bmiColors, TotalPal );
01687 }
01688
01689
01690 DWORD BitsSize = pInfoHeader->biSizeImage;
01691
01692
01693
01694 if (BitsSize > 0)
01695 {
01696
01697
01698 if (pFilter == NULL)
01699 {
01700 if (BitsSize < 1024 || ProgressString == NULL)
01701 {
01702
01703 File->write( Bits, BitsSize);
01704 }
01705 else
01706 {
01707
01708 DWORD ChunkSize = BitsSize/100;
01709 DWORD Position = 0;
01710 LPBYTE pBitInfo = Bits;
01711
01712 while (Position < BitsSize)
01713 {
01714 if ( (BitsSize - Position) > ChunkSize)
01715 File->write( pBitInfo, ChunkSize);
01716 else
01717 {
01718 ChunkSize = BitsSize - Position;
01719 File->write( pBitInfo, ChunkSize);
01720 }
01721
01722
01723 Position += ChunkSize;
01724 pBitInfo += ChunkSize;
01725 ContinueSlowJob((INT32)(100*Position/BitsSize));
01726 }
01727 }
01728 }
01729 else
01730 {
01731
01732
01733 LPBYTE pBitInfo = Bits;
01734 UINT32 ScanLineWidth = DIBUtil::ScanlineSize(pInfoHeader->biWidth, pInfoHeader->biBitCount);
01735 UINT32 height = pInfoHeader->biHeight;
01736
01737 for (UINT32 i = 0; i < height; i++)
01738 {
01739 File->write( pBitInfo, ScanLineWidth );
01740 pBitInfo += ScanLineWidth;
01741 pFilter->IncProgressBarCount(1);
01742 }
01743 }
01744 }
01745
01746
01747 if (ProgressString != NULL)
01748 {
01749 EndSlowJob();
01750 }
01751
01752
01753 File->SetThrowExceptions( OldThrowingState );
01754 File->SetReportErrors( OldReportingState );
01755
01756
01757 return TRUE;
01758 }
01759 catch( CFileException )
01760 {
01761
01762 TRACE( _T("DIBUtil::WriteToFile CC catch handler\n"));
01763
01764
01765 if (ProgressString != NULL)
01766 {
01767 EndSlowJob();
01768 }
01769
01770
01771 File->SetThrowExceptions( OldThrowingState );
01772 File->SetReportErrors( OldReportingState );
01773
01774 return FALSE;
01775 }
01776
01777 ERROR2( FALSE, "Escaped exception clause somehow" );
01778
01779 #endif
01780 }
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803 BOOL DIBUtil::WriteToFile ( CCLexFile* pFile, LPBYTE pBits, UINT32 Width, UINT32 Height, UINT32 Depth, String_64 *pProgressString)
01804 {
01805 ERROR3IF(Depth!=1, "Only 1bpp DIBs supported");
01806 ERROR3IF(Width==0, "Zero width");
01807 ERROR3IF(Height==0, "Zero height");
01808
01809
01810 const INT32 NumColours = 1 << Depth;
01811 BITMAPINFO* pBmpInfo = (BITMAPINFO*) CCMalloc (sizeof(BITMAPINFO) + sizeof(RGBQUAD)*NumColours);
01812 if (pBmpInfo == NULL)
01813 return FALSE;
01814
01815
01816 pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01817 pBmpInfo->bmiHeader.biWidth = Width;
01818 pBmpInfo->bmiHeader.biHeight = Height;
01819 pBmpInfo->bmiHeader.biPlanes = 1;
01820 pBmpInfo->bmiHeader.biBitCount = Depth;
01821 pBmpInfo->bmiHeader.biCompression = BI_RGB;
01822 pBmpInfo->bmiHeader.biXPelsPerMeter = 0;
01823 pBmpInfo->bmiHeader.biYPelsPerMeter = 0;
01824 pBmpInfo->bmiHeader.biClrImportant = 0;
01825
01826
01827 pBmpInfo->bmiHeader.biClrUsed = 2;
01828 pBmpInfo->bmiHeader.biSizeImage = Height*(((Width+31)/32)*4);
01829
01830
01831 pBmpInfo->bmiColors[0].rgbRed = 0x00;
01832 pBmpInfo->bmiColors[0].rgbGreen = 0x00;
01833 pBmpInfo->bmiColors[0].rgbBlue = 0x00;
01834 pBmpInfo->bmiColors[0].rgbReserved = 0;
01835 pBmpInfo->bmiColors[1].rgbRed = 0xff;
01836 pBmpInfo->bmiColors[1].rgbGreen = 0xff;
01837 pBmpInfo->bmiColors[1].rgbBlue = 0xff;
01838 pBmpInfo->bmiColors[1].rgbReserved = 0;
01839
01840
01841 BOOL result = DIBUtil::WriteToFile ( pFile, pBmpInfo, pBits, pProgressString );
01842
01843 CCFree(pBmpInfo);
01844
01845 return result;
01846 }
01847
01848
01849
01850
01851 #define WRITE_32BIT 0
01852
01853
01854
01855
01856 HPALETTE CreateIdentityPalette( PALETTEENTRY aRGB[], INT32 nColors )
01857 {
01858 PORTNOTETRACE("other","CreateIdentityPalette - do nothing - no palette support anymore");
01859 #ifndef EXCLUDE_FROM_XARALX
01860 INT32 i;
01861 struct {
01862 WORD Version;
01863 WORD NumberOfEntries;
01864 PALETTEENTRY aEntries[256];
01865 } Palette =
01866 {
01867 0x300,
01868 256
01869 };
01870
01871
01872 wxScreenDC dc;
01873
01874
01875
01876
01877 if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
01878
01879 {
01880
01881
01882 for(i = 0; i < nColors; i++)
01883 {
01884 Palette.aEntries[i].peRed = aRGB[i].peRed;
01885 Palette.aEntries[i].peGreen = aRGB[i].peGreen;
01886 Palette.aEntries[i].peBlue = aRGB[i].peBlue;
01887
01888 Palette.aEntries[i].peFlags = 0;
01889 }
01890
01891
01892 for (; i < 256; ++i)
01893 {
01894
01895 Palette.aEntries[i].peFlags = 0;
01896 }
01897
01898
01899
01900 Palette.aEntries[255].peRed = 255;
01901 Palette.aEntries[255].peGreen = 255;
01902 Palette.aEntries[255].peBlue = 255;
01903 Palette.aEntries[255].peFlags = 0;
01904
01905
01906
01907 Palette.aEntries[0].peRed = 0;
01908 Palette.aEntries[0].peGreen = 0;
01909 Palette.aEntries[0].peBlue = 0;
01910 Palette.aEntries[0].peFlags = 0;
01911
01912 }
01913 else
01914
01915
01916
01917 {
01918 INT32 nStaticColors;
01919 INT32 nUsableColors;
01920
01921
01922 nStaticColors = GetDeviceCaps(hdc, NUMCOLORS);
01923 GetSystemPaletteEntries(hdc, 0, 256, Palette.aEntries);
01924
01925
01926 nStaticColors = nStaticColors / 2;
01927
01928 for (i=0; i<nStaticColors; i++)
01929 Palette.aEntries[i].peFlags = 0;
01930
01931
01932 nUsableColors = nColors - nStaticColors;
01933 for (; i<nUsableColors; i++)
01934 {
01935 Palette.aEntries[i].peRed = aRGB[i].peRed;
01936 Palette.aEntries[i].peGreen = aRGB[i].peGreen;
01937 Palette.aEntries[i].peBlue = aRGB[i].peBlue;
01938
01939 Palette.aEntries[i].peFlags = 0;
01940 }
01941
01942
01943
01944 for (; i<256 - nStaticColors; i++)
01945
01946 Palette.aEntries[i].peFlags = 0;
01947
01948
01949 for (i = 256 - nStaticColors; i<256; i++)
01950 Palette.aEntries[i].peFlags = 0;
01951 }
01952
01953
01954 return CreatePalette((LOGPALETTE *)&Palette);
01955 #else
01956 return NULL;
01957 #endif
01958 }
01959
01960
01961
01962 void ClearSystemPalette(void)
01963 {
01964
01965
01966 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
01967
01968
01969 struct
01970 {
01971 WORD Version;
01972 WORD NumberOfEntries;
01973 PALETTEENTRY aEntries[256];
01974 } Palette =
01975 {
01976 0x300,
01977 256
01978 };
01979
01980 HPALETTE ScreenPalette = 0;
01981 HDC ScreenDC;
01982 INT32 Counter;
01983
01984
01985 for(Counter = 0; Counter < 256; Counter++)
01986 {
01987 Palette.aEntries[Counter].peRed = 0;
01988 Palette.aEntries[Counter].peGreen = 0;
01989 Palette.aEntries[Counter].peBlue = 0;
01990
01991
01992 Palette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
01993 }
01994
01995
01996 ScreenDC = GetDC(NULL);
01997 ScreenPalette = CreatePalette((LOGPALETTE *)&Palette);
01998 if (ScreenPalette)
01999 {
02000 ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
02001 RealizePalette(ScreenDC);
02002 ScreenPalette = SelectPalette(ScreenDC,ScreenPalette,FALSE);
02003 DeleteObject(ScreenPalette);
02004 }
02005 ReleaseDC(NULL, ScreenDC);
02006 #endif // EXCLUDE_FROM_RALPH, EXCLUDE_FROM_XARALX
02007 }
02008
02009 HPALETTE DIBUtil::MakeIdentityPalette(PALETTEENTRY aRGB[], INT32 nColors)
02010 {
02011 ClearSystemPalette();
02012 return CreateIdentityPalette( aRGB, nColors );
02013 }
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038 BitmapConvertHint DIBUtil::CalcConvertHint( DWORD ScreenBPP, wxDC *pDC )
02039 {
02040 switch(ScreenBPP)
02041 {
02042 case 4:
02043 return(CONVHINT_SCREEN4);
02044
02045 case 8:
02046 return(CONVHINT_SCREEN8);
02047
02048 case 16:
02049 case 24:
02050 case 32:
02051
02052
02053
02054 break;
02055
02056 default:
02057 ERROR2(CONVHINT_NONE, "Unknown output screen BPP");
02058 }
02059
02060
02061
02062 BYTE LastValue[3] = {0, 0, 0};
02063 BYTE Count[3] = {0, 0, 0};
02064 wxMemoryDC memdc;
02065 wxBitmap bitmap( 1, 1 );
02066 memdc.SelectObject( bitmap );
02067 for ( UINT32 Value=0x00; Value<0x100; Value++ )
02068 {
02069 wxColour colour;
02070 memdc.SetPen(wxPen(wxColour(Value,Value,Value)));
02071 memdc.DrawPoint(0,0);
02072 memdc.GetPixel(0,0,&colour);
02073 if ( colour.Red()!=LastValue[0] )
02074 {
02075 LastValue[0] = colour.Red();
02076 Count[0]++;
02077 }
02078 if ( colour.Green()!=LastValue[1] )
02079 {
02080 LastValue[1] = colour.Green();
02081 Count[1]++;
02082 }
02083 if ( colour.Blue()!=LastValue[2] )
02084 {
02085 LastValue[2] = colour.Blue();
02086 Count[2]++;
02087 }
02088 }
02089 memdc.SelectObject( wxNullBitmap );
02090
02091
02092
02093 for (INT32 Gun = 0; Gun < 3; Gun++)
02094 {
02095 INT32 BitPos = 0;
02096 while (Count[Gun] > 0)
02097 {
02098 BitPos++;
02099 Count[Gun] /= 2;
02100 }
02101 Count[Gun] = BitPos;
02102 }
02103
02104 TRACEALL( wxT("16bpp RGB gun configuration auto-detected as %ld.%ld.%ld\n"),
02105 Count[0], Count[1], Count[2]);
02106
02107
02108 switch(Count[0])
02109 {
02110 case 5:
02111 if (Count[2] == 5)
02112 {
02113 if (Count[1] == 5)
02114 return(CONVHINT_FINAL555);
02115
02116 if (Count[1] == 6)
02117 return(CONVHINT_FINAL565);
02118 }
02119 break;
02120
02121 case 6:
02122 if (Count[1] == 5 && Count[2] == 5)
02123 return(CONVHINT_FINAL655);
02124
02125 if (Count[1] == 6 && Count[2] == 4)
02126 return(CONVHINT_FINAL664);
02127 break;
02128
02129 case 8:
02130 if (Count[1] == 8 && Count[2] == 8)
02131 return(CONVHINT_FINAL24);
02132 break;
02133 }
02134
02135
02136 TRACEALL( wxT("Unknown 16bpp RGB gun configuration (%ld.%ld.%ld). Defaulting to CONVHINT_NONE\n"),
02137 Count[0], Count[1], Count[2]);
02138 return(CONVHINT_NONE);
02139 }
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166 DWORD DIBUtil::GetGavinBlitFormat(DWORD ScreenBPP, DWORD BitmapBPP, BitmapConvertHint ScreenHint)
02167 {
02168 BOOL Transparent = (BitmapBPP == 32);
02169
02170 if (Transparent)
02171 {
02172
02173 switch (ScreenHint)
02174 {
02175 case CONVHINT_FINAL565:
02176 return(0);
02177
02178 case CONVHINT_FINAL655:
02179 return(1);
02180
02181 case CONVHINT_FINAL555:
02182 case CONVHINT_FINAL16:
02183 return(2);
02184
02185 case CONVHINT_FINAL664:
02186 return(3);
02187
02188 case CONVHINT_SCREEN4:
02189 case CONVHINT_SCREEN8:
02190 case CONVHINT_FINAL24:
02191 case CONVHINT_NONE:
02192 default:
02193
02194 break;
02195 }
02196 }
02197
02198 return(2);
02199 }
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227 BOOL DIBUtil::MakeTransparentBitmap ( LPBITMAPINFO pPseudoColourInfo,
02228 LPBYTE pPseudoColourBits,
02229 LPBITMAPINFO pMonochromeInfo,
02230 LPBYTE pMonochromeBits,
02231 const BYTE TransColour )
02232 {
02233
02234 PORTNOTE("dialog","Removed BmapPrevDlg usage")
02235 #ifndef EXCLUDE_FROM_XARALX
02236 INT32 NumberOfTransparentColours = BmapPrevDlg::GetNumberOfTransparentColours();
02237 #endif
02238
02239 BOOL bHaveBackground = FALSE;
02240
02241
02242
02243 PORTNOTE("dialog","Removed BmapPrevDlg usage")
02244 #ifndef EXCLUDE_FROM_XARALX
02245 for ( INT32 j=0; j < NumberOfTransparentColours; j++ )
02246 {
02247 if ( BmapPrevDlg::GetTransparentColour ( j ) == TransColour )
02248 {
02249 bHaveBackground = TRUE;
02250 break;
02251 }
02252 }
02253 #endif
02254
02255
02256 ERROR2IF ( pPseudoColourInfo == NULL || pPseudoColourBits == NULL, FALSE,
02257 "DIBUtil::MakeTransparentBitmap missing psuedo colour bitmap" );
02258 ERROR2IF ( pMonochromeInfo == NULL || pMonochromeBits == NULL, FALSE,
02259 "DIBUtil::MakeTransparentBitmap missing monochrome bitmap" );
02260
02261 BITMAPINFOHEADER* pImageBMI = &( pPseudoColourInfo->bmiHeader );
02262 BITMAPINFOHEADER* pMaskBMI = &( pMonochromeInfo->bmiHeader );
02263
02264 ERROR2IF ( pMaskBMI->biBitCount != 1, FALSE,
02265 "DIBUtil::MakeTransparentBitmap Monochrome not 1BPP");
02266 ERROR2IF ( ( pImageBMI->biWidth != pMaskBMI->biWidth ) ||
02267 ( pImageBMI->biHeight != pMaskBMI->biHeight ), FALSE,
02268 "DIBUtil::MakeTransparentBitmap hasn't been passed identical bitmaps." );
02269
02270 BYTE* pImagePixel = pPseudoColourBits;
02271 BYTE* pMaskPixel = pMonochromeBits;
02272
02273 switch (pImageBMI->biBitCount)
02274 {
02275 case 8:
02276 {
02277
02278 for (INT32 y = 0; y < pImageBMI->biHeight; y++)
02279 {
02280
02281
02282 INT32 bbit = 7;
02283
02284 for (INT32 x = 0; x < pImageBMI->biWidth; x++)
02285 {
02286
02287
02288
02289 if( bHaveBackground && ( ( *pMaskPixel ) & ( 1 << bbit ) ) )
02290 {
02291 *pImagePixel = TransColour;
02292 }
02293
02294
02295
02296
02297 else
02298 {
02299 PORTNOTE("dialog","Removed BmapPrevDlg usage")
02300 #ifndef EXCLUDE_FROM_XARALX
02301 for ( INT32 i=0; i < NumberOfTransparentColours; i++ )
02302 {
02303 if ( *pImagePixel == BmapPrevDlg::GetTransparentColour ( i ) )
02304 {
02305 *pImagePixel = TransColour;
02306
02307
02308 break;
02309 }
02310 }
02311 #endif
02312 }
02313
02314
02315 pImagePixel++;
02316
02317
02318 if (!(bbit--))
02319 {
02320 pMaskPixel++;
02321 bbit = 7;
02322 }
02323 }
02324
02325
02326 pImagePixel = reinterpret_cast<LPBYTE> ( ( reinterpret_cast<DWORD_PTR>
02327 ( pImagePixel ) + 3 ) & ~3 );
02328 pMaskPixel = reinterpret_cast<LPBYTE> ( ( reinterpret_cast<DWORD_PTR>
02329 ( pMaskPixel ) + ( ( bbit==7 ) ? 3 : 4 ) ) & ~3 );
02330 }
02331 }
02332
02333 ERROR3IF ( static_cast<DWORD> ( pImagePixel - pPseudoColourBits )
02334 != pImageBMI->biSizeImage,
02335 "Missed image pixels");
02336
02337 break;
02338
02339 case 4 :
02340 {
02341
02342 ERROR3IF(TransColour > 15, "Trans Colour was out of the 4bpp range");
02343 const BYTE RealTransColour = min( TransColour, BYTE(15) );
02344 const INT32 ScanlineWidth = DIBUtil::ScanlineSize(pImageBMI->biWidth, 4);
02345
02346 for (INT32 y = 0; y < pImageBMI->biHeight; y++)
02347 {
02348 INT32 bbit = 7;
02349 BYTE* ScanLineStart = pImagePixel;
02350 for (INT32 x = 0; x < pImageBMI->biWidth; x++)
02351 {
02352
02353 BYTE UpperNibble = (*pImagePixel) >> 4;
02354 BYTE LowerNibble = (*pImagePixel) & 0xF;
02355
02356 if ((*pMaskPixel) & (1<<bbit))
02357 {
02358 if (x%2 == 0)
02359 *pImagePixel = (RealTransColour << 4) | LowerNibble;
02360 else
02361 *pImagePixel = (UpperNibble << 4) | RealTransColour;
02362 }
02363
02364 PORTNOTE("dialog","Removed BmapPrevDlg usage")
02365 #ifndef EXCLUDE_FROM_XARALX
02366 for( INT32 i=0; i < NumberOfTransparentColours; i++ )
02367 {
02368
02369
02370 if( Pixel == BmapPrevDlg::GetTransparentColour( i ) )
02371 {
02372 if (x%2 == 0)
02373 *pImagePixel = (RealTransColour << 4) | LowerNibble;
02374 else
02375 *pImagePixel = (UpperNibble << 4) | RealTransColour;
02376
02377 i = NumberOfTransparentColours;
02378 }
02379 }
02380 #endif
02381
02382 if (x%2==1)
02383 pImagePixel++;
02384
02385 if (!(bbit--))
02386 {
02387 pMaskPixel++;
02388 bbit = 7;
02389 }
02390 }
02391
02392 pImagePixel = ScanLineStart+ScanlineWidth;
02393 pMaskPixel = LPBYTE( ( (DWORD_PTR(pMaskPixel)) + ( ( bbit == 7 ) ? 3 : 4 ) ) & ~ 3 );
02394 }
02395 }
02396
02397 ERROR3IF ( static_cast<DWORD> ( pImagePixel - pPseudoColourBits )
02398 != pImageBMI->biSizeImage,
02399 "Missed image pixels");
02400
02401 break;
02402
02403 case 1 :
02404 {
02405 const INT32 MonoScanlineWidth = DIBUtil::ScanlineSize ( pImageBMI->biWidth, 1 );
02406
02407
02408 for (INT32 loop = 0; loop < MonoScanlineWidth*pImageBMI->biHeight; loop++)
02409 {
02410
02411
02412
02413 PORTNOTE("dialog","Removed BmapPrevDlg usage")
02414 #ifndef EXCLUDE_FROM_XARALX
02415 if( NumberOfTransparentColours == 2 )
02416 {
02417 pPseudoColourBits[loop] = 0;
02418 }
02419 else if( NumberOfTransparentColours == 1 )
02420 {
02421 if( BmapPrevDlg::m_bIsOrderedDither )
02422 {
02423 if( BmapPrevDlg::GetTransparentColour( 0 ) == 1 )
02424 {
02425 pPseudoColourBits[loop] = pPseudoColourBits[loop];
02426 }
02427 else
02428 {
02429 if( pPseudoColourBits[loop] > 0 )
02430 pPseudoColourBits[loop] = 255 - pPseudoColourBits[loop];
02431 else
02432 pPseudoColourBits[loop] = 255;
02433 }
02434 }
02435 else
02436 {
02437 if( BmapPrevDlg::GetTransparentColour( 0 ) == 0 )
02438 {
02439 pPseudoColourBits[loop] = pPseudoColourBits[loop];
02440 }
02441 else
02442 {
02443 if( pPseudoColourBits[loop] > 0 )
02444 pPseudoColourBits[loop] = 255 - pPseudoColourBits[loop];
02445 else
02446 pPseudoColourBits[loop] = 255;
02447 }
02448 }
02449 }
02450 #endif
02451 }
02452 }
02453
02454 break;
02455
02456 default:
02457 ERROR2(FALSE, "DIBUtil::MakeTransparentBitmap PseudoColour bitmap not 8/4/1 BPP");
02458 }
02459
02460 return TRUE;
02461 }
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487 BOOL DIBUtil::MakeBitmapMask(LPBITMAPINFO pPseudoColourInfo, LPBYTE pPseudoColourBits,
02488 LPBITMAPINFO pMonochromeInfo, LPBYTE pMonochromeBits,
02489 const BYTE TransCol)
02490 {
02491
02492
02493 ERROR2IF(pPseudoColourInfo==NULL || pPseudoColourBits==NULL, FALSE, "DIBUtil::MakeBitmapMask missing psuedo colour bitmap");
02494 ERROR2IF(pMonochromeInfo==NULL || pMonochromeBits==NULL, FALSE, "DIBUtil::MakeBitmapMask missing monochrome bitmap");
02495
02496 BITMAPINFOHEADER * pABMI=&(pPseudoColourInfo->bmiHeader);
02497 BITMAPINFOHEADER * pBBMI=&(pMonochromeInfo->bmiHeader);
02498 LPBYTE pABytes=pPseudoColourBits;
02499 LPBYTE pBBytes=pMonochromeBits;
02500
02501 ERROR2IF(pABMI->biBitCount != 8, FALSE, "DIBUtil::MakeBitmapMask PseudoColour bitmap not 8BPP");
02502 ERROR2IF(pBBMI->biBitCount != 8, FALSE, "DIBUtil::MakeBitmapMask Monochrome not 8BPP");
02503 ERROR2IF((pABMI->biWidth != pBBMI->biWidth) || (pABMI->biHeight != pBBMI->biHeight), FALSE,
02504 "DIBUtil::MakeBitmapMask needs identically sized bitmaps and that's not what you've given it.");
02505
02506 LPBYTE A=pABytes;
02507 LPBYTE B=pBBytes;
02508
02509
02510
02511
02512 #if 1
02513 for (INT32 y = 0; y < pABMI->biHeight; y++)
02514 {
02515 for (INT32 x = 0; x < pABMI->biWidth; x++)
02516 B[x] = -(A[x]==TransCol) ;
02517 A += pABMI->biWidth ;
02518 B += pABMI->biWidth ;
02519 A = (LPBYTE)( (((DWORD_PTR)(A))+3) & ~ 3);
02520 B = (LPBYTE)( (((DWORD_PTR)(B))+3) & ~ 3);
02521 }
02522 #else
02523 memset(B, 0, pBBMI->biSizeImage);
02524
02525 for (INT32 y = 0; y < pABMI->biHeight; y++)
02526 {
02527
02528 for (INT32 x = 0; x < pABMI->biWidth; x++)
02529 {
02530
02531 if ((*(A++))==TransCol)
02532 (*B) = 0xFF;
02533
02534
02535
02536
02537
02538
02539
02540
02541 B++;
02542 }
02543 A=(LPBYTE)( (((DWORD)(A))+3) & ~ 3);
02544 B=(LPBYTE)( (((DWORD)(B))+3) & ~ 3);
02545
02546 }
02547 #endif
02548 ERROR3IF( (((DWORD_PTR)A-(DWORD_PTR)pABytes)!=pABMI->biSizeImage), "Alex got his other algorithm wrong in one way");
02549 ERROR3IF( (((DWORD_PTR)B-(DWORD_PTR)pBBytes)!=pBBMI->biSizeImage), "Alex got his other algorithm wrong in another way");
02550
02551
02552 RGBQUAD * Palette= pMonochromeInfo->bmiColors;
02553
02554
02555
02556
02557
02558 ERROR2IF((pBBMI->biClrUsed < 256), FALSE, "DIBUtil::MakeBitmapMask not passed a large enough mono palette");
02559 Palette[0].rgbRed=Palette[0].rgbBlue=Palette[0].rgbGreen=0;
02560 Palette[255].rgbRed=Palette[255].rgbBlue=Palette[255].rgbGreen=255;
02561
02562 return TRUE;
02563 }
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588 BOOL DIBUtil::MakeBitmapSmaller(UINT32 OldWidth, UINT32 OldHeight, UINT32 BaseX, UINT32 BaseY,
02589 UINT32 NewWidth, UINT32 NewHeight, UINT32 BPP, LPBYTE pBits)
02590 {
02591 ERROR2IF(!pBits, FALSE, "DIBUtil::MakeBitmapSmaller would really appreciate a bitmap");
02592 ERROR2IF((BPP!=8) && (BPP!=16) && (BPP!=32), FALSE, "DIBUtil::MakeBitmapSmaller passed invalid BPP");
02593 ERROR2IF(OldWidth<NewWidth, FALSE, "DIBUtil::MakeBitmapSmaller thinks you are making the bitmap wider");
02594 ERROR2IF(OldHeight<NewHeight, FALSE, "DIBUtil::MakeBitmapSmaller thinks you are making the bitmap taller");
02595
02596 ERROR2IF((BaseX>OldWidth) || (BaseY>OldHeight), FALSE, "DIBUtil::MakeBitmapSmaller passed bad Base");
02597 ERROR2IF((BaseX+NewWidth>OldWidth) || (BaseY+NewHeight>OldHeight), FALSE, "DIBUtil::MakeBitmapSmaller passed bad rect");
02598
02599 ERROR2IF(!OldWidth || !NewWidth || !OldHeight || !NewHeight, FALSE, "DIBUtil::MakeBitmapSmaller passed bad width/height");
02600
02601 UINT32 OldWidthR=OldWidth;
02602 UINT32 NewWidthR=NewWidth;
02603 UINT32 BPPShift=2;
02604
02605 switch (BPP)
02606 {
02607 case 8:
02608 OldWidthR=(OldWidth+3)&~3;
02609 NewWidthR=(NewWidth+3)&~3;
02610 BPPShift=0;
02611 break;
02612 case 16:
02613 OldWidthR=(OldWidth+1)&~1;
02614 NewWidthR=(NewWidth+1)&~1;
02615 BPPShift=1;
02616 break;
02617 case 32:
02618 default:
02619 break;
02620 }
02621
02622
02623 UINT32 NewByteW = DIBUtil::ScanlineSize(NewWidth, BPP);
02624 UINT32 OldByteW = DIBUtil::ScanlineSize(OldWidth, BPP);
02625
02626 LPBYTE pSrc=pBits+OldByteW*BaseY+(BaseX<<BPPShift);
02627 LPBYTE pDest=pBits;
02628
02629 for (UINT32 y=0; y<NewHeight; y++)
02630 {
02631 memcpy(pDest, pSrc, NewByteW);
02632 pDest+=NewByteW;
02633 pSrc+=OldByteW;
02634 }
02635 return TRUE;
02636 }
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653 BOOL DIBUtil::Init()
02654 {
02655 return
02656 Camelot.DeclareSection( wxT("DisplayKludges"), 10)
02657 && Camelot.DeclarePref(NULL, wxT("RenderDirection4"), &RenderDirection4, FALSE, TRUE )
02658 && Camelot.DeclarePref(NULL, wxT("RenderDirection8"), &RenderDirection8, FALSE, TRUE )
02659 && Camelot.DeclarePref(NULL, wxT("RenderDirection16"), &RenderDirection16, FALSE, TRUE )
02660 && Camelot.DeclarePref(NULL, wxT("RenderDirection24"), &RenderDirection24, FALSE, TRUE )
02661 && Camelot.DeclarePref(NULL, wxT("SubbandConversionSize"), &SubbandConversionSize, 0x200, 0x1000000);
02662 }
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679
02680 UINT32 DIBUtil::CalcPaletteSize(UINT32 Depth, bool bUsingBitFields, UINT32 UsedColours)
02681 {
02682 ERROR3IF((bUsingBitFields && (Depth != 16 || Depth != 32)), "Invalid use of DIBUtil::CalcPaletteSize()");
02683
02684
02685 UINT32 extras = 0;
02686 switch (Depth)
02687 {
02688 case 1:
02689 if (UsedColours > 0 && UsedColours <= 2)
02690 extras = UsedColours;
02691 else
02692 extras = 2;
02693 break;
02694 case 4:
02695 if (UsedColours > 0 && UsedColours <= 16)
02696 extras = UsedColours;
02697 else
02698 extras = 16;
02699 break;
02700 case 8:
02701 if (UsedColours > 0 && UsedColours <= 256)
02702 extras = UsedColours;
02703 else
02704 extras = 256;
02705 break;
02706 case 16:
02707 case 32:
02708 if (bUsingBitFields)
02709 extras = 3;
02710 break;
02711 }
02712 ERROR3IF(extras == 0 && Depth != 16 && Depth != 24 && Depth != 32, "Unsupported DIB depth!");
02713
02714 return(extras * sizeof(RGBQUAD));
02715 }
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744 void DebugMemCopy(LPBYTE pDest, LPBYTE pSrc, UINT32 size)
02745 {
02746 memcpy(pDest, pSrc, size);
02747 }
02748
02749
02750 BOOL DIBUtil::CopyBitmap(LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits,
02751 LPBITMAPINFO *pDestInfo, LPBYTE *pDestBits)
02752 {
02753
02754 *pDestInfo = NULL;
02755 *pDestBits = NULL;
02756
02757 ERROR2IF(pSourceInfo == NULL || pSourceBits == NULL, FALSE, "DIBUtil::CopyBitmap bad source bitmap");
02758
02759
02760
02761 LPBITMAPINFOHEADER pSourceInfoHeader = &(pSourceInfo->bmiHeader);
02762 DWORD biCompression = pSourceInfoHeader->biCompression;
02763
02764
02765 *pDestInfo = AllocDIB( pSourceInfoHeader->biWidth, pSourceInfoHeader->biHeight,
02766 pSourceInfoHeader->biBitCount,
02767 pDestBits );
02768
02769 (*pDestInfo)->bmiHeader.biCompression = biCompression;
02770
02771
02772 if (*pDestInfo == NULL || *pDestBits == NULL )
02773 return FALSE;
02774
02775
02776 DWORD BitmapSize = pSourceInfo->bmiHeader.biSizeImage;
02777 #ifdef _DEBUG
02778 DebugMemCopy(*pDestBits, pSourceBits, BitmapSize);
02779 #else
02780 memcpy(*pDestBits, pSourceBits, BitmapSize);
02781 #endif
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796 return TRUE;
02797 }
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828 BOOL DIBUtil::CopyEntireBitmap(LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits,
02829 LPBITMAPINFO *pDestInfo, LPBYTE *pDestBits)
02830 {
02831
02832 *pDestInfo = NULL;
02833 *pDestBits = NULL;
02834
02835 ERROR2IF(pSourceInfo == NULL || pSourceBits == NULL, FALSE, "DIBUtil::CopyBitmap bad source bitmap");
02836
02837
02838
02839 LPBITMAPINFOHEADER pSourceInfoHeader = &(pSourceInfo->bmiHeader);
02840
02841
02842 *pDestInfo = AllocDIB( pSourceInfoHeader->biWidth, pSourceInfoHeader->biHeight,
02843 pSourceInfoHeader->biBitCount,
02844 pDestBits );
02845
02846
02847 if (*pDestInfo == NULL || *pDestBits == NULL )
02848 return FALSE;
02849
02850
02851 DWORD BitmapSize = pSourceInfo->bmiHeader.biSizeImage;
02852 memcpy(*pDestBits, pSourceBits, BitmapSize);
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868 LPBITMAPINFOHEADER pDestInfoHeader = &((*pDestInfo)->bmiHeader);
02869 pDestInfoHeader->biPlanes = pSourceInfoHeader->biPlanes;
02870 pDestInfoHeader->biCompression = pSourceInfoHeader->biCompression;
02871 pDestInfoHeader->biXPelsPerMeter = pSourceInfoHeader->biXPelsPerMeter;
02872 pDestInfoHeader->biYPelsPerMeter = pSourceInfoHeader->biYPelsPerMeter;
02873 pDestInfoHeader->biClrImportant = pSourceInfoHeader->biClrImportant;
02874 pDestInfoHeader->biClrUsed = pSourceInfoHeader->biClrUsed;
02875
02876 LPRGBQUAD pSourcePalette = &(pSourceInfo->bmiColors[0]);
02877 LPRGBQUAD pDestPalette = &((*pDestInfo)->bmiColors[0]);
02878 UINT32 NumberOfColours = pSourceInfoHeader->biClrUsed;
02879
02880
02881 if (pSourceInfoHeader->biBitCount <= 8 && NumberOfColours == 0)
02882 NumberOfColours = 1 << pSourceInfoHeader->biBitCount;
02883 CopyPalette(pSourcePalette, pDestPalette, NumberOfColours);
02884
02885 return TRUE;
02886 }
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905 BOOL DIBUtil::CopyPalette(LPRGBQUAD pSourcePalette, LPRGBQUAD pDestPalette, UINT32 NumberOfColours)
02906 {
02907
02908 if (pSourcePalette == NULL || pDestPalette == NULL || NumberOfColours == 0)
02909 return TRUE;
02910
02911 for (UINT32 i = 0; i < NumberOfColours; i++)
02912 {
02913 pDestPalette->rgbBlue = pSourcePalette->rgbBlue;
02914 pDestPalette->rgbGreen = pSourcePalette->rgbGreen;
02915 pDestPalette->rgbRed = pSourcePalette->rgbRed;
02916 pDestPalette->rgbReserved = pSourcePalette->rgbReserved;
02917 pDestPalette++;
02918 pSourcePalette++;
02919 }
02920
02921 return TRUE;
02922 }
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956 KernelBitmap *DIBUtil::CopyKernelBitmap(KernelBitmap *pKernelBitmap, BOOL IsTemp)
02957 {
02958 OILBitmap *pOilBitmap = pKernelBitmap->ActualBitmap;
02959 ERROR3IF(pOilBitmap == NULL, "Unattached kernel bitmap found!");
02960 CWxBitmap* pWBitmap = (CWxBitmap*)pOilBitmap;
02961 LPBITMAPINFO Info = pWBitmap->BMInfo;
02962 LPBYTE Bytes = pWBitmap->BMBytes;
02963 ERROR3IF(Info == NULL, "Bitmap info is null - oh god !");
02964 ERROR3IF(Info->bmiHeader.biSizeImage == 0, "Bitmap data size is zero - I'm about to screw up");
02965
02966 LPBITMAPINFO NewInfo = NULL;
02967
02968 LPBYTE NewBytes = NULL;
02969 NewInfo = AllocDIB(Info->bmiHeader.biWidth, Info->bmiHeader.biHeight, Info->bmiHeader.biBitCount, &NewBytes);
02970
02971 if (NewInfo == NULL || NewBytes == NULL)
02972 {
02973 ERROR3("Couldn't allocate enough memory for new CWxBitmap");
02974 return(NULL);
02975 }
02976
02977 UINT32 PalSize = CalcPaletteSize(pWBitmap->GetBPP(), Info->bmiHeader.biCompression == BI_BITFIELDS);
02978 DWORD HeaderSize = Info->bmiHeader.biSize + PalSize;
02979 DWORD BitmapSize = Info->bmiHeader.biSizeImage;
02980
02981
02982
02983 memcpy(NewInfo, Info, HeaderSize);
02984 memcpy(NewBytes, Bytes, BitmapSize);
02985
02986 CWxBitmap *NewCWxBitmap = new CWxBitmap(NewInfo, NewBytes);
02987 ERROR3IF(NewCWxBitmap == NULL, "NULL CWxBitmap created");
02988
02989
02990 KernelBitmap *TheKBToReturn = new KernelBitmap((OILBitmap *)NewCWxBitmap, IsTemp);
02991
02992 return TheKBToReturn;
02993 }
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026 BOOL DIBUtil::CopyBitmapSection(LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits,
03027 LPBITMAPINFO pDestInfo, LPBYTE pDestBits,
03028 INT32 SourceTop, INT32 SourceLeft)
03029 {
03030
03031
03032 if (pSourceInfo == NULL || pSourceBits == NULL ||
03033 pDestInfo == NULL || pDestBits == NULL)
03034 {
03035 ERROR3("One of the input pointers is NULL");
03036 return FALSE;
03037 }
03038
03039 if (pSourceInfo->bmiHeader.biBitCount<8 || pDestInfo->bmiHeader.biBitCount<8)
03040 {
03041 ERROR3("This routine can't handle bit depths < 1 byte per pixel (no masking)");
03042 return FALSE;
03043 }
03044
03045 if (pSourceInfo->bmiHeader.biBitCount != pDestInfo->bmiHeader.biBitCount)
03046 {
03047 ERROR3("This routine can't handle differing src and dest bit depths");
03048 return FALSE;
03049 }
03050
03051
03052 INT32 CopyWidth = pDestInfo->bmiHeader.biWidth;
03053 INT32 CopyHeight = pDestInfo->bmiHeader.biHeight;
03054 LPBYTE pDest = pDestBits;
03055 if (SourceLeft<0)
03056 {
03057 CopyWidth += SourceLeft;
03058 pDest += ScanlineBytes(-SourceLeft, pDestInfo->bmiHeader.biBitCount);
03059 SourceLeft = 0;
03060 }
03061 if (SourceTop<0)
03062 {
03063 CopyHeight += SourceTop;
03064 pDest += ScanlineSize(pDestInfo->bmiHeader.biWidth, pDestInfo->bmiHeader.biBitCount) * -SourceTop;
03065 SourceTop = 0;
03066 }
03067 if ((SourceLeft+CopyWidth) > pSourceInfo->bmiHeader.biWidth)
03068 {
03069 CopyWidth = (pSourceInfo->bmiHeader.biWidth - SourceLeft);
03070 }
03071 if ((SourceTop+CopyHeight) > pSourceInfo->bmiHeader.biHeight)
03072 {
03073 CopyHeight = (pSourceInfo->bmiHeader.biHeight - SourceTop);
03074 }
03075
03076
03077 if (CopyWidth<=0 || CopyHeight<=0)
03078 {
03079 TRACEUSER("Phil", wxT("CopyBitmapSection clipped to NULL rectangle\n") );
03080 return TRUE;
03081 }
03082
03083
03084 INT32 LeftOffset = ScanlineBytes(SourceLeft, pSourceInfo->bmiHeader.biBitCount);
03085 INT32 SourceScanlineBytes = ScanlineSize(pSourceInfo->bmiHeader.biWidth, pSourceInfo->bmiHeader.biBitCount);
03086
03087 LPBYTE pSource = pSourceBits + LeftOffset;
03088 pSource += SourceScanlineBytes * SourceTop;
03089
03090
03091
03092
03093 INT32 DestScanlineBytes = ScanlineSize(pDestInfo->bmiHeader.biWidth, pDestInfo->bmiHeader.biBitCount);
03094 INT32 CopyBytes = ScanlineBytes(CopyWidth, pSourceInfo->bmiHeader.biBitCount);
03095 for (INT32 Count = 0; Count < CopyHeight; Count++)
03096 {
03097 memcpy(pDest, pSource, CopyBytes);
03098
03099
03100 pDest += DestScanlineBytes;
03101 pSource += SourceScanlineBytes;
03102 }
03103
03104
03105
03106
03107 if (pDestInfo->bmiHeader.biCompression == BI_RGB && pDestInfo->bmiHeader.biBitCount==32)
03108 {
03109 LPDWORD pBits = (LPDWORD) pDestBits;
03110 for (UINT32 i=0; i<pDestInfo->bmiHeader.biSizeImage; i+=sizeof(DWORD))
03111 {
03112 *pBits &= 0x00FFFFFF;
03113 pBits++;
03114 }
03115 }
03116
03117
03118 if (pDestInfo->bmiHeader.biBitCount == 8 &&
03119 pSourceInfo->bmiHeader.biBitCount == 8)
03120 {
03121 for (INT32 i = 0; i < 256; i++)
03122 pDestInfo->bmiColors[i] = pSourceInfo->bmiColors[i];
03123 }
03124
03125 return TRUE;
03126 }
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140 BOOL DIBUtil::CountColoursUsed(BITMAPINFO* pInfo, BYTE* pBits, UINT32** pResultsArray)
03141 {
03142 ERROR2IF(pInfo==NULL || pBits==NULL, FALSE, "NULL entry param");
03143 ERROR3IF(*pResultsArray != NULL, "pResultsArray was not NULL (are you leaking memory?)");
03144
03145
03146 const UINT32 NumColours = 1 << pInfo->bmiHeader.biBitCount;
03147 ERROR2IF(NumColours>256, FALSE, "DIBUtil::CountColoursUsed only handles palletted DIBs");
03148 *pResultsArray = (UINT32*) CCMalloc(NumColours*sizeof(UINT32));
03149 if (*pResultsArray == NULL)
03150 return FALSE;
03151 memset(*pResultsArray, 0, NumColours*sizeof(UINT32));
03152
03153
03154 UINT32 ScanLineLength = 0;
03155 switch (pInfo->bmiHeader.biBitCount)
03156 {
03157 case 8:
03158 ScanLineLength = ((pInfo->bmiHeader.biWidth+3)/4)*4;
03159 break;
03160 case 4:
03161 ScanLineLength = ((pInfo->bmiHeader.biWidth+7)/8)*4;
03162 break;
03163 case 1:
03164 ScanLineLength = ((pInfo->bmiHeader.biWidth+31)/32)*4;
03165 break;
03166 default:
03167 ERROR2(FALSE, "Unknown depth");
03168 }
03169
03170
03171 for (INT32 y = 0; y < pInfo->bmiHeader.biHeight; y++)
03172 {
03173 BYTE* pCurrentPixel = pBits + y*ScanLineLength;
03174 BYTE CurrentBitMask = 0x80;
03175
03176 for (INT32 x = 0; x < pInfo->bmiHeader.biWidth; x++)
03177 {
03178 switch (pInfo->bmiHeader.biBitCount)
03179 {
03180 case 8:
03181
03182 (*pResultsArray)[(*pCurrentPixel)]++;
03183 pCurrentPixel++;
03184 break;
03185
03186 case 4:
03187
03188 if (x%2 == 0)
03189 {
03190 (*pResultsArray)[((*pCurrentPixel) >> 4)]++;
03191 }
03192 else
03193 {
03194 (*pResultsArray)[((*pCurrentPixel) & 0xF)]++;
03195 pCurrentPixel++;
03196 }
03197 break;
03198
03199 case 1:
03200
03201 if ((*pCurrentPixel) & CurrentBitMask)
03202 (*pResultsArray)[1]++;
03203 else
03204 (*pResultsArray)[0]++;
03205
03206 if (CurrentBitMask == 1)
03207 {
03208 CurrentBitMask = 0x80;
03209 pCurrentPixel++;
03210 }
03211 else
03212 CurrentBitMask = CurrentBitMask >> 1;
03213 break;
03214
03215 default:
03216 ERROR2(FALSE, "Unknown depth");
03217 }
03218 }
03219 }
03220
03221 return TRUE;
03222 }
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239 INT32 DIBUtil::FindLeastUsedColour(BITMAPINFO* pInfo, UINT32* pResultsArray)
03240 {
03241 ERROR2IF(pInfo == NULL || pResultsArray == NULL, -1, "NULL entry param");
03242 INT32 TransIndex = -1;
03243
03244 INT32 MinIndex = 0;
03245
03246
03247 INT32 Bpp = pInfo->bmiHeader.biBitCount;
03248 INT32 MaxColours = 1 << Bpp;
03249 for (INT32 loop = 0; loop < MaxColours; loop++)
03250 {
03251 if (pResultsArray[loop] == 0 && TransIndex == -1)
03252 TransIndex = loop;
03253 if (pResultsArray[loop] < pResultsArray[MinIndex])
03254 MinIndex = loop;
03255 }
03256
03257 if (TransIndex == -1)
03258 {
03259
03260 if (Bpp == 1)
03261 TransIndex = 1;
03262 else
03263 TransIndex = MinIndex;
03264 }
03265
03266 return TransIndex;
03267 }
03268
03269 #if !defined(EXCLUDE_FROM_RALPH)
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292 size_t DIBUtil::GetOptimalPaletteWorkspaceSize()
03293 {
03294
03295 ASSERT(FALSE);
03296 return 0;
03297 }
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323 BOOL DIBUtil::OptimalPaletteInitialise( void* Stats )
03324 {
03325 ERROR3IF(Stats == NULL, "NULL pointer passed to DIBUtil::OptimalPaletteInitialise");
03326 if (Stats == NULL)
03327 return FALSE;
03328
03329
03330
03331 ASSERT(FALSE);
03332 return TRUE;
03333 }
03334
03335
03336 BOOL DIBUtil::ExactPaletteInitialise( LPLOGPALETTE pExactPalette )
03337 {
03338 ERROR3IF(pExactPalette == NULL, "NULL pointer passed to DIBUtil::ExactPaletteInitialise");
03339 if (pExactPalette == NULL)
03340 return FALSE;
03341
03342
03343
03344 ASSERT(0);
03345 return FALSE;
03346
03347 }
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379 BOOL DIBUtil::GenOptimalPaletteStats( void* Stats, RGBQUAD* pBitmap, size_t Size )
03380 {
03381 ERROR3IF(Stats == NULL, "NULL Stats pointer passed to DIBUtil::GenOptimalPaletteStats");
03382 if (Stats == NULL)
03383 return FALSE;
03384
03385 ERROR3IF(pBitmap == NULL, "NULL Bitmap pointer passed to DIBUtil::GenOptimalPaletteStats");
03386 if (pBitmap == NULL)
03387 return FALSE;
03388
03389 ERROR3IF(Size == 0, "Bad size passed to DIBUtil::GenOptimalPaletteStats");
03390 if (Size == 0)
03391 return FALSE;
03392
03393
03394 ASSERT(FALSE);
03395
03396 return TRUE;
03397 }
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453 BOOL DIBUtil::GenOptimalPalette( void* Stats, PLOGPALETTE pPalette, const size_t MaxColours )
03454 {
03455 ERROR3IF(Stats == NULL, "NULL Stats pointer passed to DIBUtil::GenOptimalPalette");
03456 if (Stats == NULL)
03457 return FALSE;
03458
03459 ERROR3IF(pPalette == NULL, "NULL Palette pointer passed to DIBUtil::GenOptimalPalette");
03460 if (pPalette == NULL)
03461 return FALSE;
03462
03463
03464
03465
03466
03467
03468
03469
03470 ASSERT(FALSE);
03471
03472 return TRUE;
03473 }
03474
03475
03476 BOOL DIBUtil::CalculateNumberOfColoursInBitmap( LPLOGPALETTE pExactPalette, RGBQUAD* pBitmap, size_t Size )
03477 {
03478 ERROR3IF(pExactPalette == NULL, "NULL palette pointer passed to DIBUtil::CalculateNumberOfColoursInBitmap");
03479 if (pExactPalette == NULL)
03480 return FALSE;
03481
03482 ERROR3IF(pBitmap == NULL, "NULL Bitmap pointer passed to DIBUtil::CalculateNumberOfColoursInBitmap");
03483 if (pBitmap == NULL)
03484 return FALSE;
03485
03486 ERROR3IF(Size == 0, "Bad size passed to DIBUtil::CalculateNumberOfColoursInBitmap");
03487 if (Size == 0)
03488 return FALSE;
03489
03490
03491 ASSERT(0);
03492 return FALSE;
03493 }
03494
03495
03496
03497 BOOL DIBUtil::Optimal4bppPaletteInitialise_1stPass()
03498 {
03499
03500
03501 return TRUE;
03502 }
03503
03504 BOOL DIBUtil::Optimal4bppPaletteInitialise_2ndPass()
03505 {
03506
03507
03508 return TRUE;
03509 }
03510
03511 BOOL DIBUtil::GenOptimal4bppPaletteStats_1stPass( RGBQUAD* pBitmap, size_t Size )
03512 {
03513
03514
03515 return TRUE;
03516 }
03517
03518 BOOL DIBUtil::GenOptimal4bppPaletteStats_2ndPass( RGBQUAD* pBitmap, size_t Size )
03519 {
03520
03521
03522 return TRUE;
03523 }
03524
03525 BOOL DIBUtil::GenOptimal4bppPalette( PLOGPALETTE pPalette, const size_t MaxColours )
03526 {
03527
03528
03529 return TRUE;
03530 }
03531
03532
03533 size_t DIBUtil::GetOptimal8bppPaletteWorkspaceSize()
03534 {
03535
03536 ASSERT(FALSE);
03537 return 0;
03538 }
03539
03540 BOOL DIBUtil::Optimal8bppPaletteInitialise( INT32* Stats )
03541 {
03542 ERROR3IF(Stats == NULL, "NULL pointer passed to DIBUtil::OptimalPaletteInitialise");
03543 if (Stats == NULL)
03544 return FALSE;
03545
03546
03547 ASSERT(FALSE);
03548
03549 return TRUE;
03550 }
03551
03552 BOOL DIBUtil::GenOptimal8bppPaletteStats( INT32* Stats, RGBQUAD* pBitmap, size_t Size )
03553 {
03554
03555 ASSERT(FALSE);
03556
03557 return TRUE;
03558 }
03559
03560 BOOL DIBUtil::GenOptimal8bppPalette( INT32* Stats, PLOGPALETTE pPalette, const size_t MaxColours )
03561 {
03562
03563 ASSERT(FALSE);
03564
03565 return TRUE;
03566 }
03567
03568 #endif // EXCLUDE_FROM_RALPH
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585 BOOL DIBUtil::GenGreyscalePalette(LPRGBQUAD lpPalette, const size_t PaletteSize)
03586 {
03587 ERROR2IF(lpPalette == NULL,FALSE,"PNGUtil::GenerateGreyPalette no lpPalette present");
03588 ERROR2IF(PaletteSize <= 0,FALSE,"PNGUtil::GenerateGreyPalette no PNG palette entries present");
03589
03590
03591
03592
03593 INT32 inc = INT32(256 / PaletteSize);
03594 INT32 value = 0;
03595 for( size_t i = 0; i < PaletteSize; i++ )
03596 {
03597 lpPalette->rgbBlue = value;
03598 lpPalette->rgbGreen = value;
03599 lpPalette->rgbRed = value;
03600 lpPalette->rgbReserved = 0;
03601 lpPalette++;
03602 value += inc;
03603 if (value > 255)
03604 value = 255;
03605 }
03606
03607 return TRUE;
03608 }
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627 BOOL DIBUtil::GenGreyscalePaletteTriple(RGBTRIPLE* pPalette, const size_t PaletteSize)
03628 {
03629 ERROR2IF(pPalette == NULL,FALSE,"PNGUtil::GenerateGreyPalette no pPalette present");
03630 ERROR2IF(PaletteSize <= 0,FALSE,"PNGUtil::GenerateGreyPalette no PNG palette entries present");
03631
03632
03633
03634
03635 INT32 inc = INT32(256/PaletteSize);
03636 INT32 value = 0;
03637 for (size_t i = 0; i < PaletteSize; i++ )
03638 {
03639 pPalette->rgbtBlue = value;
03640 pPalette->rgbtGreen = value;
03641 pPalette->rgbtRed = value;
03642 pPalette++;
03643 value += inc;
03644 if (value > 255)
03645 value = 255;
03646 }
03647
03648 return TRUE;
03649 }
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671 BOOL DIBUtil::Convert24to8( LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits,
03672 LPBITMAPINFO *pDestInfo, LPBYTE *pDestBits,
03673 RGBTRIPLE *pPalette, UINT32 NumberOfPaletteEntries )
03674 {
03675
03676 *pDestInfo = NULL;
03677 *pDestBits = NULL;
03678
03679 ERROR2IF(pSourceInfo == NULL || pSourceBits == NULL, FALSE, "DIBUtil::Convert24to8 bad source bitmap");
03680 ERROR2IF(pPalette == NULL || NumberOfPaletteEntries == 0, FALSE, "DIBUtil::Convert24to8 bad palette info");
03681
03682
03683
03684 LPBITMAPINFOHEADER pSourceInfoHeader = &(pSourceInfo->bmiHeader);
03685
03686 ERROR2IF(pSourceInfoHeader->biBitCount != 24,FALSE,"DIBUtil::Convert24to8 bad source depth");
03687
03688
03689 *pDestInfo = AllocDIB( pSourceInfoHeader->biWidth, pSourceInfoHeader->biHeight,
03690 8, pDestBits );
03691
03692
03693 if (*pDestInfo == NULL || *pDestBits == NULL )
03694 return FALSE;
03695
03696 LPBITMAPINFOHEADER pDestInfoHeader = &((*pDestInfo)->bmiHeader);
03697
03698
03699
03700
03701 LPLOGPALETTE pLogPalette = NULL;
03702 const UINT32 MaxColours = 256;
03703 pLogPalette = DIBUtil::AllocateLogPalette(MaxColours);
03704 if (pLogPalette == NULL)
03705 return FALSE;
03706
03707
03708
03709 LPRGBQUAD lpPalette = NULL;
03710 lpPalette = &((*pDestInfo)->bmiColors[0]);
03711
03712 pLogPalette->palNumEntries = NumberOfPaletteEntries;
03713 RGBTRIPLE *pPal = pPalette;
03714 for (UINT32 i = 0; i < NumberOfPaletteEntries; i++)
03715 {
03716 lpPalette->rgbRed = pPal->rgbtRed;
03717 pLogPalette->palPalEntry[i].peRed = pPal->rgbtRed;
03718 lpPalette->rgbGreen = pPal->rgbtGreen;
03719 pLogPalette->palPalEntry[i].peGreen = pPal->rgbtGreen;
03720 lpPalette->rgbBlue = pPal->rgbtBlue;
03721 pLogPalette->palPalEntry[i].peBlue = pPal->rgbtBlue;
03722 pLogPalette->palPalEntry[i].peFlags = 0x00;
03723 lpPalette->rgbReserved = 0x00;
03724 lpPalette++;
03725 pPal++;
03726 }
03727
03728 for (UINT32 i = NumberOfPaletteEntries; i < MaxColours; i++)
03729 {
03730 pLogPalette->palPalEntry[i].peRed = 0x00;
03731 pLogPalette->palPalEntry[i].peGreen = 0x00;
03732 pLogPalette->palPalEntry[i].peBlue = 0x00;
03733 pLogPalette->palPalEntry[i].peFlags = 0xFF;
03734 lpPalette->rgbRed = 0x00;
03735 lpPalette->rgbGreen = 0x00;
03736 lpPalette->rgbBlue = 0x00;
03737 lpPalette->rgbReserved = 0xFF;
03738 lpPalette++;
03739 }
03740
03741 UINT32 DitherType = XARADITHER_NONE;
03742 DIBConvert *pDoConvert = NULL;
03743
03744
03745 pDoConvert = DIBConvert::Create( pSourceInfoHeader->biBitCount, pDestInfoHeader->biBitCount,
03746 pSourceInfoHeader->biWidth, pLogPalette, DitherType);
03747
03748 if (pDoConvert == NULL)
03749 {
03750 if (pLogPalette)
03751 CCFree(pLogPalette);
03752 return FALSE;
03753 }
03754
03755
03756 INT32 ChunkHeight = 16;
03757 INT32 Height = pSourceInfoHeader->biHeight;
03758 INT32 SourceWidth = DIBUtil::ScanlineSize( pSourceInfoHeader->biWidth, pSourceInfoHeader->biBitCount ) * ChunkHeight;
03759 INT32 DestWidth = DIBUtil::ScanlineSize( pDestInfoHeader->biWidth, pDestInfoHeader->biBitCount ) * ChunkHeight;
03760 BOOL IsFirstStrip = TRUE;
03761 INT32 CurrentYPos = 0;
03762 LPBYTE SourceData = pSourceBits;
03763 LPBYTE DestData = *pDestBits;
03764 while (CurrentYPos < Height)
03765 {
03766
03767
03768 const UINT32 ThisBit = min( UINT32(Height - CurrentYPos), (UINT32)ChunkHeight );
03769 if (!pDoConvert->Convert( SourceData, DestData, ThisBit, IsFirstStrip ))
03770 return FALSE;
03771
03772 IsFirstStrip = FALSE;
03773 SourceData += SourceWidth;
03774 DestData += DestWidth;
03775 CurrentYPos += INT32(ThisBit);
03776 }
03777
03778
03779 if (pDoConvert)
03780 {
03781 delete pDoConvert;
03782 pDoConvert = NULL;
03783 }
03784
03785 if (pLogPalette)
03786 {
03787 CCFree(pLogPalette);
03788 pLogPalette = NULL;
03789 }
03790
03791
03792 return TRUE;
03793 }
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812
03813
03814
03815
03816
03817 BOOL DIBUtil::Convert32to8( LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits,
03818 LPBITMAPINFO *pDestInfo, LPBYTE *pDestBits,
03819 RGBTRIPLE *pPalette, UINT32 NumberOfPaletteEntries )
03820 {
03821
03822 *pDestInfo = NULL;
03823 *pDestBits = NULL;
03824
03825 ERROR2IF(pSourceInfo == NULL || pSourceBits == NULL, FALSE, "DIBUtil::Convert32to8 bad source bitmap");
03826 ERROR2IF(pPalette == NULL || NumberOfPaletteEntries == 0, FALSE, "DIBUtil::Convert32to8 bad palette info");
03827
03828
03829
03830 LPBITMAPINFOHEADER pSourceInfoHeader = &(pSourceInfo->bmiHeader);
03831
03832 ERROR2IF(pSourceInfoHeader->biBitCount != 32,FALSE,"DIBUtil::Convert32to8 bad source depth");
03833
03834
03835 *pDestInfo = AllocDIB( pSourceInfoHeader->biWidth, pSourceInfoHeader->biHeight,
03836 8, pDestBits );
03837
03838
03839 if (*pDestInfo == NULL || *pDestBits == NULL )
03840 return FALSE;
03841
03842 LPBITMAPINFOHEADER pDestInfoHeader = &((*pDestInfo)->bmiHeader);
03843
03844
03845
03846
03847 LPLOGPALETTE pLogPalette = NULL;
03848 const UINT32 MaxColours = 256;
03849 pLogPalette = DIBUtil::AllocateLogPalette(MaxColours);
03850 if (pLogPalette == NULL)
03851 return FALSE;
03852
03853
03854
03855 LPRGBQUAD lpPalette = NULL;
03856 lpPalette = &((*pDestInfo)->bmiColors[0]);
03857
03858 pLogPalette->palNumEntries = NumberOfPaletteEntries;
03859 RGBTRIPLE *pPal = pPalette;
03860 for (UINT32 i = 0; i < NumberOfPaletteEntries; i++)
03861 {
03862 lpPalette->rgbRed = pPal->rgbtRed;
03863 pLogPalette->palPalEntry[i].peRed = pPal->rgbtRed;
03864 lpPalette->rgbGreen = pPal->rgbtGreen;
03865 pLogPalette->palPalEntry[i].peGreen = pPal->rgbtGreen;
03866 lpPalette->rgbBlue = pPal->rgbtBlue;
03867 pLogPalette->palPalEntry[i].peBlue = pPal->rgbtBlue;
03868 pLogPalette->palPalEntry[i].peFlags = 0x00;
03869 lpPalette->rgbReserved = 0x00;
03870 lpPalette++;
03871 pPal++;
03872 }
03873
03874 for (UINT32 i = NumberOfPaletteEntries; i < MaxColours; i++)
03875 {
03876 pLogPalette->palPalEntry[i].peRed = 0x00;
03877 pLogPalette->palPalEntry[i].peGreen = 0x00;
03878 pLogPalette->palPalEntry[i].peBlue = 0x00;
03879 pLogPalette->palPalEntry[i].peFlags = 0xFF;
03880 lpPalette->rgbRed = 0x00;
03881 lpPalette->rgbGreen = 0x00;
03882 lpPalette->rgbBlue = 0x00;
03883 lpPalette->rgbReserved = 0xFF;
03884 lpPalette++;
03885 }
03886
03887 UINT32 DitherType = XARADITHER_NONE;
03888 DIBConvert *pDoConvert = NULL;
03889
03890
03891 pDoConvert = DIBConvert::Create( pSourceInfoHeader->biBitCount, pDestInfoHeader->biBitCount,
03892 pSourceInfoHeader->biWidth, pLogPalette, DitherType);
03893
03894 if (pDoConvert == NULL)
03895 {
03896 if (pLogPalette)
03897 CCFree(pLogPalette);
03898 return FALSE;
03899 }
03900
03901
03902 INT32 ChunkHeight = 16;
03903 INT32 Height = pSourceInfoHeader->biHeight;
03904 INT32 SourceWidth = DIBUtil::ScanlineSize( pSourceInfoHeader->biWidth, pSourceInfoHeader->biBitCount ) * ChunkHeight;
03905 INT32 DestWidth = DIBUtil::ScanlineSize( pDestInfoHeader->biWidth, pDestInfoHeader->biBitCount ) * ChunkHeight;
03906 BOOL IsFirstStrip = TRUE;
03907 INT32 CurrentYPos = 0;
03908 LPBYTE SourceData = pSourceBits;
03909 LPBYTE DestData = *pDestBits;
03910 while (CurrentYPos < Height)
03911 {
03912
03913
03914 const UINT32 ThisBit = min( UINT32(Height - CurrentYPos), (UINT32)ChunkHeight );
03915 if (!pDoConvert->Convert( SourceData, DestData, ThisBit, IsFirstStrip ))
03916 return FALSE;
03917
03918 IsFirstStrip = FALSE;
03919 SourceData += SourceWidth;
03920 DestData += DestWidth;
03921 CurrentYPos += INT32(ThisBit);
03922 }
03923
03924
03925 if (pDoConvert)
03926 {
03927 delete pDoConvert;
03928 pDoConvert = NULL;
03929 }
03930
03931 if (pLogPalette)
03932 {
03933 CCFree(pLogPalette);
03934 pLogPalette = NULL;
03935 }
03936
03937
03938 return TRUE;
03939 }
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966 BOOL DIBUtil::Convert8to32(LPBITMAPINFO pSourceInfo, LPBYTE pSourceBits, RGBQUAD* pPalette,
03967 LPBITMAPINFO pDestInfo, LPBYTE pDestBits)
03968 {
03969 ERROR2IF(pSourceBits == NULL, FALSE, "NULL source bitmap");
03970 ERROR2IF(pSourceInfo == NULL, FALSE, "NULL source info");
03971 ERROR2IF(pDestInfo == NULL, FALSE, "NULL destination info");
03972 ERROR2IF(pDestBits == NULL, FALSE, "Null destination bitmap");
03973
03974
03975
03976
03977
03978 pDestInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
03979 pDestInfo->bmiHeader.biWidth = pSourceInfo->bmiHeader.biWidth;
03980 pDestInfo->bmiHeader.biHeight = pSourceInfo->bmiHeader.biHeight;
03981 pDestInfo->bmiHeader.biPlanes = pSourceInfo->bmiHeader.biPlanes;
03982 pDestInfo->bmiHeader.biCompression = pSourceInfo->bmiHeader.biCompression;
03983 pDestInfo->bmiHeader.biXPelsPerMeter = pSourceInfo->bmiHeader.biXPelsPerMeter;
03984 pDestInfo->bmiHeader.biYPelsPerMeter = pSourceInfo->bmiHeader.biYPelsPerMeter;
03985 pDestInfo->bmiHeader.biClrImportant = 0;
03986
03987
03988 INT32 size = pDestInfo->bmiHeader.biWidth * pDestInfo->bmiHeader.biHeight * 4;
03989
03990
03991 pDestInfo->bmiHeader.biBitCount = 32;
03992 pDestInfo->bmiHeader.biSizeImage = size;
03993 pDestInfo->bmiHeader.biClrUsed = 0;
03994
03995
03996
03997 INT32 bmpsize = pSourceInfo->bmiHeader.biWidth * pSourceInfo->bmiHeader.biHeight;
03998 INT32 padding = pSourceInfo->bmiHeader.biWidth % 4;
03999 if (padding)
04000 padding = 4 - padding;
04001
04002 LPBYTE pSource = pSourceBits;
04003 LPBYTE pDest = pDestBits;
04004 for (INT32 i = 0; i < bmpsize; i ++)
04005 {
04006 if (i && i % pSourceInfo->bmiHeader.biWidth == 0)
04007 pSource += padding;
04008 *pDest = pPalette[*pSource].rgbBlue;
04009 pDest++;
04010 *pDest = pPalette[*pSource].rgbGreen;
04011 pDest++;
04012 *pDest = pPalette[*pSource].rgbRed;
04013 pDest++;
04014 *pDest = pPalette[*pSource].rgbReserved;
04015 pDest++;
04016 pSource++;
04017 }
04018 return TRUE;
04019
04020 }
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039 BOOL DIBUtil::ConvertTo8Greyscale(LPBITMAPINFO pSourceInfo,LPBYTE pSourceBits,
04040 LPBITMAPINFO *ppDestInfo, LPBYTE *ppDestBits)
04041 {
04042 if (pSourceInfo == NULL || pSourceBits == NULL || ppDestInfo == NULL || ppDestBits == NULL)
04043 {
04044 ERROR3("Null parameters");
04045 return FALSE;
04046 }
04047
04048
04049 UINT32 Width = pSourceInfo->bmiHeader.biWidth;
04050 UINT32 Height = pSourceInfo->bmiHeader.biHeight;
04051 UINT32 Depth = pSourceInfo->bmiHeader.biBitCount;
04052
04053
04054 UINT32 NumCols = 0;
04055 switch (Depth)
04056 {
04057 case 1: NumCols = 2; break;
04058 case 4: NumCols = 16; break;
04059 case 8: NumCols = 256; break;
04060 case 16: break;
04061 case 24: break;
04062 case 32: break;
04063 default:
04064 ERROR3("Routine can't cope");
04065 return FALSE;
04066 break;
04067 }
04068
04069
04070 *ppDestInfo = AllocDIB(Width,Height, 8, ppDestBits);
04071 if (*ppDestInfo == NULL || *ppDestBits == NULL)
04072 return FALSE;
04073
04074
04075 BYTE LookUp[256];
04076
04077 if (NumCols > 0)
04078 {
04079
04080 for (UINT32 i=0;i < NumCols;i++)
04081 {
04082
04083 double R = pSourceInfo->bmiColors[i].rgbRed;
04084 double G = pSourceInfo->bmiColors[i].rgbGreen;
04085 double B = pSourceInfo->bmiColors[i].rgbBlue;
04086
04087
04088 BYTE C = BYTE((R * 0.305) + (G * 0.586) + (B * 0.109));
04089
04090
04091 LookUp[i] = C;
04092 }
04093 }
04094
04095
04096 UINT32 SourceScanLineLength = DIBUtil::ScanlineSize(Width,Depth);
04097 UINT32 DestScanLineLength = DIBUtil::ScanlineSize(Width,8);
04098
04099
04100 UINT32 x,y ;
04101 BYTE* pSourcePixel = pSourceBits ;
04102 BYTE* pDestPixel = *ppDestBits ;
04103 switch (Depth)
04104 {
04105 case 1:
04106 for ( y = 0; y < Height; y++ )
04107 {
04108 BYTE* pSource = pSourcePixel ;
04109 BYTE Pixel;
04110 BYTE SourceBitMask = 0x80;
04111 for ( x = 0; x < Width; x++ )
04112 {
04113
04114 if (*pSource & SourceBitMask)
04115 Pixel = 1;
04116 else
04117 Pixel = 0;
04118
04119 pDestPixel[x] = LookUp[Pixel];
04120 SourceBitMask >>= 1;
04121 if (SourceBitMask==0)
04122 {
04123
04124 SourceBitMask = 0x80;
04125 pSource++;
04126 }
04127 }
04128 pSourcePixel += SourceScanLineLength ;
04129 pDestPixel += DestScanLineLength ;
04130 }
04131 break ;
04132
04133 case 4:
04134 for ( y = 0; y < Height; y++ )
04135 {
04136 BYTE* pSource = pSourcePixel ;
04137 for ( x=0 ; x<Width ; x+=2 )
04138 {
04139
04140 pDestPixel[x ] = LookUp[*pSource >> 4] ;
04141 pDestPixel[x+1] = LookUp[*pSource & 0xF] ;
04142 pSource++;
04143 }
04144 pSourcePixel += SourceScanLineLength ;
04145 pDestPixel += DestScanLineLength ;
04146 }
04147 break ;
04148
04149 case 8:
04150 for ( y=0 ; y<Height ; y++ )
04151 {
04152
04153 for ( x=0 ; x<Width ; x++ )
04154 pDestPixel[x] = LookUp[pSourcePixel[x]];
04155 pSourcePixel += SourceScanLineLength ;
04156 pDestPixel += DestScanLineLength ;
04157 }
04158 break ;
04159
04160 case 16:
04161 for ( y=0 ; y<Height ; y++ )
04162 {
04163 WORD* pSrc = (WORD*)pSourcePixel;
04164
04165 for ( x=0 ; x<Width ; x++ )
04166 {
04167
04168 BYTE Grey = 0xFF;
04169 pDestPixel[x] = Grey;
04170 pSrc++;
04171 }
04172 pSourcePixel += SourceScanLineLength ;
04173 pDestPixel += DestScanLineLength ;
04174 }
04175 break;
04176
04177 case 24:
04178 for ( y=0 ; y<Height ; y++ )
04179 {
04180 BYTE* pSrc = pSourcePixel;
04181
04182 for ( x=0 ; x<Width ; x++ )
04183 {
04184
04185 BYTE Grey = (pSrc[2] * 78 + pSrc[1] * 150 + pSrc[0] * 28) >> 8;
04186 pDestPixel[x] = Grey;
04187 pSrc += 3;
04188 }
04189 pSourcePixel += SourceScanLineLength ;
04190 pDestPixel += DestScanLineLength ;
04191 }
04192 break;
04193
04194 case 32:
04195 for ( y=0 ; y<Height ; y++ )
04196 {
04197
04198
04199 BGRT* pSrc = (BGRT*)pSourcePixel;
04200 for ( x=0 ; x<Width ; x++ )
04201 {
04202 const BYTE Trans = pSrc->Transparency;
04203 const BYTE Alpha = 255 - Trans;
04204 BYTE Grey = (pSrc->Red * 78 + pSrc->Green * 150 + pSrc->Blue * 28) >> 8;
04205 pDestPixel[x] = ((Grey * Alpha) + (255 * Trans)) / 255;
04206 pSrc++;
04207 }
04208 pSourcePixel += SourceScanLineLength ;
04209 pDestPixel += DestScanLineLength ;
04210 }
04211 break;
04212 }
04213
04214
04215
04216 return TRUE;
04217 }
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236 OILBitmap* DIBUtil::Create8bppGreyscaleBitmap(KernelBitmap* pSrcBitmap)
04237 {
04238 OILBitmap* pOilBitmap = pSrcBitmap->GetActualBitmap();
04239 ERROR2IF(pOilBitmap == NULL,NULL,"null OIL bitmap present!");
04240
04241
04242 CWxBitmap* pCWxBitmap = (CWxBitmap*)pOilBitmap;
04243 ERROR2IF(pCWxBitmap == NULL,NULL,"null WINOIL bitmap present!");
04244
04245 LPBITMAPINFO pSourceInfo = pCWxBitmap->BMInfo;
04246 LPBYTE pSourceBits = pCWxBitmap->BMBytes;
04247
04248 LPBITMAPINFO pDestInfo = NULL;
04249 LPBYTE pDestBits = NULL;
04250
04251 BOOL ok = FALSE;
04252
04253 switch (pSrcBitmap->GetBPP())
04254 {
04255 case 1:
04256 case 4:
04257 case 8:
04258 case 24:
04259 case 32:
04260 ok = ConvertTo8Greyscale(pSourceInfo, pSourceBits, &pDestInfo, &pDestBits);
04261 break;
04262
04263 default:
04264 ERROR3("How many bits? No chance mate");
04265 return NULL;
04266 break;
04267 }
04268
04269 OILBitmap* pResultBitmap = NULL;
04270
04271 if (ok)
04272 {
04273
04274 pResultBitmap = (OILBitmap*) new CWxBitmap(pDestInfo, pDestBits);
04275 if (pResultBitmap == NULL)
04276 FreeDIB( pDestInfo, pDestBits );
04277 }
04278
04279 return pResultBitmap;
04280 }
04281
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310 BOOL DIBUtil::GenerateDifferenceBitmap(LPBITMAPINFO pPreviousInfo,LPBYTE pPreviousBits,
04311 LPBITMAPINFO pCurrentInfo,LPBYTE pCurrentBits,
04312 LPBITMAPINFO *ppDestInfo, LPBYTE *ppDestBits, INT32 TransColour,
04313 BOOL * pFoundBadOverlay)
04314 {
04315 ERROR2IF(pPreviousInfo == NULL || pPreviousBits == NULL,FALSE,"GenerateDifferenceBitmap Bad previous pointers!" );
04316 ERROR2IF(pCurrentInfo == NULL || pCurrentBits == NULL,FALSE,"GenerateDifferenceBitmap Bad current pointers!" );
04317 ERROR2IF(ppDestInfo == NULL || ppDestBits == NULL,FALSE,"GenerateDifferenceBitmap Bad destination pointers!" );
04318
04319 if (TransColour < 0 || TransColour > 256)
04320 {
04321 TRACEUSER( "Neville", wxT("GenerateDifferenceBitmap Bad transparent colour\n") );
04322
04323 return TRUE;
04324 }
04325
04326
04327 UINT32 Width = pPreviousInfo->bmiHeader.biWidth;
04328 UINT32 Height = pPreviousInfo->bmiHeader.biHeight;
04329 UINT32 Depth = pPreviousInfo->bmiHeader.biBitCount;
04330
04331
04332 UINT32 CurrentWidth = pCurrentInfo->bmiHeader.biWidth;
04333 UINT32 CurrentHeight = pCurrentInfo->bmiHeader.biHeight;
04334 UINT32 CurrentDepth = pCurrentInfo->bmiHeader.biBitCount;
04335
04336
04337 if (Width != CurrentWidth || Height != CurrentHeight || Depth != CurrentDepth)
04338 {
04339 TRACEUSER("Neville", wxT("GenerateDifferenceBitmap Source and destination bitmaps different sizes and/or depths\n") );
04340
04341 return TRUE;
04342 }
04343
04344
04345 if (Depth != 8)
04346 {
04347 TRACEUSER( "Neville", wxT("GenerateDifferenceBitmap Bitmap colour depth is not supported\n") );
04348
04349 return TRUE;
04350 }
04351
04352
04353
04354 BOOL ok = DIBUtil::CopyEntireBitmap(pCurrentInfo, pCurrentBits, ppDestInfo, ppDestBits);
04355
04356 if (!ok || *ppDestInfo == NULL || *ppDestBits == NULL)
04357 return FALSE;
04358
04359 UINT32 ScanLineSize = DIBUtil::ScanlineSize( Width, Depth );
04360 LPBYTE pPreviousData = pPreviousBits;
04361 LPBYTE pCurrentData = pCurrentBits;
04362 LPBYTE pDestData = *ppDestBits;
04363 BOOL BadOverlay = FALSE;
04364 for (UINT32 y = 0; y < Height && !BadOverlay; y++)
04365 {
04366 for (UINT32 x = 0; x < Width && !BadOverlay; x++)
04367 {
04368
04369
04370 if (pPreviousData[x] == pCurrentData[x])
04371 pDestData[x] = TransColour & 0xFF;
04372
04373
04374
04375 else if (pCurrentData[x] == (TransColour & 0xFF))
04376 {
04377 BadOverlay = TRUE;
04378 break;
04379 }
04380 }
04381
04382
04383 pPreviousData += ScanLineSize;
04384 pCurrentData += ScanLineSize;
04385 pDestData += ScanLineSize;
04386 }
04387
04388
04389 if (pFoundBadOverlay)
04390 {
04391 *pFoundBadOverlay = BadOverlay;
04392
04393 if (BadOverlay)
04394 {
04395
04396 if (*ppDestInfo && *ppDestBits)
04397 {
04398 FreeDIB(*ppDestInfo, *ppDestBits);
04399 *ppDestInfo = NULL;
04400 *ppDestBits = NULL;
04401 }
04402 }
04403 }
04404
04405
04406 return TRUE;
04407 }
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435 BOOL DIBUtil::GenerateSubRegionBitmap(LPBITMAPINFO pSourceInfo,LPBYTE pSourceBits,
04436 LPBITMAPINFO *ppDestInfo, LPBYTE *ppDestBits, INT32 TransColour,
04437 UINT32 *pLeftOffset, UINT32 *pTopOffset)
04438 {
04439 ERROR2IF(pSourceInfo == NULL || pSourceBits == NULL,FALSE,"GenerateSubRegionBitmap Bad source pointers!" );
04440 ERROR2IF(ppDestInfo == NULL || ppDestBits == NULL,FALSE,"GenerateSubRegionBitmap Bad destination pointers!" );
04441 ERROR2IF(pLeftOffset == NULL || pTopOffset == NULL,FALSE,"GenerateSubRegionBitmap Bad offset pointers!" );
04442
04443 if (TransColour < 0 || TransColour > 255)
04444 {
04445 TRACEUSER( "Neville", wxT("GenerateSubRegionBitmap Bad transparent colour\n") );
04446
04447 return TRUE;
04448 }
04449
04450
04451 UINT32 Width = pSourceInfo->bmiHeader.biWidth;
04452 UINT32 Height = pSourceInfo->bmiHeader.biHeight;
04453 UINT32 Depth = pSourceInfo->bmiHeader.biBitCount;
04454
04455
04456 if (Depth != 8)
04457 {
04458 TRACEUSER( "Neville", wxT("GenerateSubRegionBitmap Bitmap colour depth is not supported\n") );
04459
04460 return TRUE;
04461 }
04462
04463 UINT32 ScanLineSize = DIBUtil::ScanlineSize( Width, Depth );
04464
04465
04466
04467
04468 INT32 LeftMostData = -1;
04469 LPBYTE pSourceData = pSourceBits;
04470 LPBYTE pPixel = NULL;
04471 BOOL FoundClearColumn = TRUE;
04472 for (UINT32 x = 0; x < Width; x++)
04473 {
04474 for (UINT32 y = 0; y < Height; y++)
04475 {
04476
04477 pPixel = pSourceData + y * ScanLineSize + x;
04478
04479 if (*pPixel != (TransColour & 0xFF))
04480 {
04481 FoundClearColumn = FALSE;
04482 break;
04483 }
04484 }
04485
04486
04487
04488 if (FoundClearColumn)
04489 LeftMostData = x;
04490 else
04491 break;
04492 }
04493
04494
04495
04496
04497 UINT32 RightMostData = Width;
04498 pSourceData = pSourceBits;
04499 FoundClearColumn = TRUE;
04500 for( UINT32 x = Width - 1; x >= 0 ; x-- )
04501 {
04502 for (UINT32 y = 0; y < Height; y++)
04503 {
04504
04505 pPixel = pSourceData + y * ScanLineSize + x;
04506
04507 if (*pPixel != (TransColour & 0xFF))
04508 {
04509 FoundClearColumn = FALSE;
04510 break;
04511 }
04512 }
04513
04514
04515
04516 if (FoundClearColumn)
04517 RightMostData = x;
04518 else
04519 break;
04520 }
04521
04522
04523
04524
04525
04526 INT32 TopMostData = -1;
04527 pSourceData = pSourceBits + (Height - 1) * ScanLineSize;
04528 BOOL FoundClearRow = TRUE;
04529 for (UINT32 y = 0; y < Height; y++)
04530 {
04531 for (UINT32 x = 0; x < Width; x++)
04532 {
04533
04534 if (pSourceData[x] != (TransColour & 0xFF))
04535 {
04536 FoundClearRow = FALSE;
04537 break;
04538 }
04539 }
04540
04541
04542
04543 if (FoundClearRow)
04544 TopMostData = y;
04545 else
04546 break;
04547
04548
04549 pSourceData -= ScanLineSize;
04550 }
04551
04552
04553
04554
04555 UINT32 BottomMostData = Height;
04556 pSourceData = pSourceBits;
04557 FoundClearRow = TRUE;
04558 for (UINT32 y = Height - 1; y >= 0; y--)
04559 {
04560 for (UINT32 x = 0; x < Width; x++)
04561 {
04562
04563 if (pSourceData[x] != (TransColour & 0xFF))
04564 {
04565 FoundClearRow = FALSE;
04566 break;
04567 }
04568 }
04569
04570
04571
04572 if (FoundClearRow)
04573 BottomMostData = y;
04574 else
04575 break;
04576
04577
04578 pSourceData += ScanLineSize;
04579 }
04580
04581 TRACEUSER("Neville", wxT("width = %d, left offset = %d, right offset = %d\n"), Width, LeftMostData,RightMostData);
04582 TRACEUSER("Neville", wxT("height = %d, top offset = %d, bottom offset = %d\n"), Height, TopMostData,BottomMostData);
04583
04584
04585 if (LeftMostData >= 0 || RightMostData < Width || TopMostData >= 0 || BottomMostData < Height)
04586 {
04587 UINT32 LeftOffset = 0;
04588 if (LeftMostData > 0)
04589 LeftOffset = LeftMostData;
04590 UINT32 RightOffset = Width - 1;
04591 if (RightMostData < Width - 1)
04592 RightOffset = RightMostData;
04593
04594 if (RightOffset < LeftOffset)
04595 RightOffset = LeftOffset;
04596
04597 UINT32 TopOffset = 0;
04598 if (TopMostData > 0)
04599 TopOffset = TopMostData;
04600 UINT32 BottomOffset = Height - 1;
04601 if (BottomMostData < Height - 1)
04602 BottomOffset = BottomMostData;
04603
04604 if (BottomOffset < TopOffset)
04605 BottomOffset = TopOffset;
04606
04607 UINT32 NewWidth = RightOffset - LeftOffset + 1;
04608 UINT32 NewHeight = BottomOffset - TopOffset + 1;
04609
04610 TRACEUSER("Neville", wxT("Creating sub-region bitmap new height = %d, new width = %d\n"), NewWidth,NewHeight);
04611
04612
04613 LPBYTE pBits = NULL;
04614 LPBITMAPINFO pInfo = AllocDIB(NewWidth, NewHeight, Depth, &pBits);
04615 if (pInfo == NULL || pBits == NULL)
04616 return FALSE;
04617
04618
04619 LPBITMAPINFOHEADER pSourceInfoHeader = &(pSourceInfo->bmiHeader);
04620 LPBITMAPINFOHEADER pDestInfoHeader = &(pInfo->bmiHeader);
04621 pDestInfoHeader->biPlanes = pSourceInfoHeader->biPlanes;
04622 pDestInfoHeader->biCompression = pSourceInfoHeader->biCompression;
04623 pDestInfoHeader->biXPelsPerMeter = pSourceInfoHeader->biXPelsPerMeter;
04624 pDestInfoHeader->biYPelsPerMeter = pSourceInfoHeader->biYPelsPerMeter;
04625 pDestInfoHeader->biClrImportant = pSourceInfoHeader->biClrImportant;
04626 pDestInfoHeader->biClrUsed = pSourceInfoHeader->biClrUsed;
04627
04628
04629 LPRGBQUAD pSourcePalette = &(pSourceInfo->bmiColors[0]);
04630 LPRGBQUAD pDestPalette = &(pInfo->bmiColors[0]);
04631 UINT32 NumberOfColours = pSourceInfoHeader->biClrUsed;
04632
04633
04634 if (pSourceInfoHeader->biBitCount <= 8 && NumberOfColours == 0)
04635 NumberOfColours = 1 << pSourceInfoHeader->biBitCount;
04636 CopyPalette(pSourcePalette, pDestPalette, NumberOfColours);
04637
04638
04639 UINT32 DestScanLineSize = DIBUtil::ScanlineSize(NewWidth, Depth);
04640
04641 LPBYTE pSourceData = pSourceBits + (Height - 1) * ScanLineSize;
04642 LPBYTE pDestData = pBits + (NewHeight - 1) * DestScanLineSize;
04643 for (UINT32 y = TopOffset; y <= BottomOffset; y++)
04644 {
04645 LPBYTE pThisSourceData = pSourceData - (y * ScanLineSize) + LeftOffset;
04646 LPBYTE pThisDestData = pDestData - ((y - TopOffset) * DestScanLineSize);
04647 memcpy(pThisDestData, pThisSourceData, NewWidth);
04648 }
04649
04650
04651 if (*ppDestInfo && *ppDestBits)
04652 FreeDIB(*ppDestInfo, *ppDestBits);
04653
04654
04655 *ppDestInfo = pInfo;
04656 *ppDestBits = pBits;
04657
04658
04659 *pLeftOffset = LeftOffset;
04660 *pTopOffset = TopOffset;
04661 TRACEUSER( "Neville",wxT("Creating sub-region bitmap left offset = %d, top offset = %d\n"),LeftOffset,TopOffset);
04662 }
04663
04664 return TRUE;
04665 }
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681 LPLOGPALETTE DIBUtil::AllocateLogPalette(const UINT32 PaletteSize)
04682 {
04683 ERROR2IF(PaletteSize == 0 || PaletteSize > 256,NULL,"AllocateLogPalette Bad PaletteSize");
04684
04685 LPLOGPALETTE pPalette = NULL;
04686 const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PaletteSize );
04687 pPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
04688 if (pPalette == NULL)
04689 return NULL;
04690
04691 pPalette->palNumEntries = PaletteSize;
04692 pPalette->palVersion = 0x300;
04693 return pPalette;
04694 }
04695
04696
04697
04698
04699
04700
04701
04702
04703
04704
04705
04706
04707
04708
04709
04710 LPLOGPALETTE DIBUtil::CopyBitmapPaletteIntoLogPalette(KernelBitmap * pBitmap)
04711 {
04712 ERROR2IF(pBitmap == NULL,NULL,"CopyBitmapPaletteIntoLogPalette Bad bitmap");
04713
04714 LPRGBQUAD pPal = pBitmap->GetPaletteForBitmap();
04715 UINT32 Bpp = pBitmap->GetBPP();
04716 UINT32 PaletteSize = 1U<<Bpp;
04717 LPLOGPALETTE pLogPal = NULL;
04718
04719
04720 if (Bpp > 8 || pPal == NULL)
04721 {
04722 ERROR2(NULL,"CopyBitmapPaletteIntoLogPalette bitmap has no palette");
04723
04724 }
04725
04726 pLogPal = DIBUtil::AllocateLogPalette(PaletteSize);
04727 if (pLogPal == NULL)
04728 return NULL;
04729
04730 UINT32 ColoursInPal = pBitmap->GetNumPaletteEntries();
04731 UINT32 ColoursInLogPal = pLogPal->palNumEntries;
04732 PALETTEENTRY* pPaletteEntry = pLogPal->palPalEntry;
04733 for (UINT32 i = 0; i < ColoursInLogPal; i++)
04734 {
04735 if (i > ColoursInPal)
04736 {
04737
04738 pPaletteEntry[i].peBlue = 0;
04739 pPaletteEntry[i].peGreen = 0;
04740 pPaletteEntry[i].peRed = 0;
04741
04742 pPaletteEntry[i].peFlags = 0xFF;
04743 }
04744 else
04745 {
04746 pPaletteEntry[i].peBlue = pPal[i].rgbBlue;
04747 pPaletteEntry[i].peGreen = pPal[i].rgbGreen;
04748 pPaletteEntry[i].peRed = pPal[i].rgbRed;
04749
04750 pPaletteEntry[i].peFlags = 0x00;
04751 }
04752 }
04753
04754
04755
04756
04757 pLogPal->palNumEntries = ColoursInPal;
04758
04759 return pLogPal;
04760 }
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782 BOOL DIBUtil::IsGreyscaleBitmap(KernelBitmap * pKB)
04783 {
04784 if ( (!pKB) || (!pKB->ActualBitmap) )
04785 return FALSE;
04786
04787 return IsGreyscaleBitmap(pKB->ActualBitmap);
04788 }
04789
04790
04791
04792
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810 BOOL DIBUtil::IsGreyscaleBitmap(OILBitmap * pOilBmp)
04811 {
04812 if ( (!pOilBmp) || (!pOilBmp->IsKindOf(CC_RUNTIME_CLASS(CWxBitmap))) )
04813 return FALSE;
04814
04815 BITMAPINFOHEADER * pBMI=&(((CWxBitmap *)pOilBmp)->BMInfo->bmiHeader);
04816 if ((pBMI->biBitCount!=8) || (pBMI->biClrUsed!=0x100)) return FALSE;
04817 DWORD * pPal = (DWORD *)(void *)(pBMI +1 );
04818 for (DWORD x=0; x<0x100; x++) if ((pPal[x]&0x00ffffff) != (x|(x<<8)|(x<<16))) return FALSE;
04819 return TRUE;
04820 }
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836
04837 void DIBUtil::InvertAlpha(LPBITMAPINFO lpBitmapInfo, LPBYTE lpBits)
04838 {
04839
04840 if ( lpBitmapInfo->bmiHeader.biBitCount == 32 )
04841 {
04842
04843 DWORD *lpRGBA = reinterpret_cast<DWORD*> ( lpBits );
04844
04845
04846
04847 for ( UINT32 i = 0; i < lpBitmapInfo->bmiHeader.biSizeImage; i+=4 )
04848 {
04849
04850
04851 *lpRGBA ^= 0xff000000;
04852 lpRGBA ++;
04853 }
04854 }
04855 }
04856
04857
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871 void DIBUtil::MakeAlphaIntoGreyscale(LPBITMAPINFO lpBitmapInfo, LPBYTE lpBits)
04872 {
04873
04874 if ( lpBitmapInfo->bmiHeader.biBitCount == 32 )
04875 {
04876
04877 DWORD *lpRGBA = reinterpret_cast<DWORD*> ( lpBits );
04878
04879
04880
04881 for ( UINT32 i = 0; i < lpBitmapInfo->bmiHeader.biSizeImage; i+=4 )
04882 {
04883
04884 *lpRGBA = 0x010101 * (*lpRGBA>>24);
04885 lpRGBA ++;
04886 }
04887 }
04888 }
04889
04890
04891 #ifdef _DEBUG
04892 void DIBUtil::FillColour24(LPBITMAPINFO lpBitmapInfo, LPBYTE lpBits)
04893 {
04894 srand((unsigned)time(NULL));
04895 DWORD colour = (rand() % 0xff)<<16 | (rand() % 0xff)<<8 | (rand() % 0xff)<<0;
04896
04897
04898 if ( lpBitmapInfo->bmiHeader.biBitCount == 32 )
04899 {
04900
04901 DWORD *lpRGBA = reinterpret_cast<DWORD*> ( lpBits );
04902
04903 for ( UINT32 i = 0; i < lpBitmapInfo->bmiHeader.biSizeImage; i+=4 )
04904 {
04905 if ((*lpRGBA & 0xffffff) == 0xffffff)
04906 *lpRGBA = colour;
04907 lpRGBA ++;
04908 }
04909 }
04910 }
04911 #endif