00001 // $Id: outptdib.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 /* 00100 */ 00101 00102 #include "camtypes.h" 00103 //#include "outptdib.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00104 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 //#include "andy.h" 00109 //#include "dibconv.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 #include "progress.h" // For hourglass stuff 00111 #include "bmapprev.h" 00112 00113 #define new CAM_DEBUG_NEW 00114 00115 // Declare the statics that are required as we are using a call back function 00116 LPBITMAPINFO OutputDIB::lpBitmap; // copy of header + palette, can be NULL 00117 LPBITMAPINFOHEADER OutputDIB::lpBitmapInfo; // copy of header, can be NULL 00118 BITMAPINFOHEADER OutputDIB::BitmapInfo; // copy of file header (includes output depth, 00119 // width & height) 00120 // for debug purposes 00121 INT32 OutputDIB::HeightWritten = 0L; // count of the height of the export 00122 INT32 OutputDIB::HeightWanted = 0L; // the actual height of the export required 00123 00124 LPBYTE OutputDIB::ExportBuffer = NULL; // pointer to output buffer, can be NULL 00125 DIBConvert *OutputDIB::DoExportConvert; // the convert DIB 00126 FNPTR_SCANLINE OutputDIB::ExportConvertFn = NULL; // the convert function 00127 size_t OutputDIB::ExportSourceWidth = 0; // width of the source DIB 00128 size_t OutputDIB::ExportDestWidth = 0; // width of the destination DIB 00129 LPBYTE OutputDIB::ExportData = NULL; // pointer to the export data 00130 INT32 OutputDIB::CurrentYPos = 0; // current line number 00131 size_t OutputDIB::ExportChunkHeight = 0; // Chunk height in use 00132 00133 BOOL OutputDIB::OutputForward = FALSE;// start from bottom or top of DIB 00134 UINT32 OutputDIB::CurrentStripSize = 0; // current size of the strip being rendered 00135 00136 BOOL OutputDIB::IsFirstStrip = TRUE; 00137 00138 /******************************************************************************************** 00139 > OutputDIB::OutputDIB() 00140 00141 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> 00142 Created: 4/8/94 00143 Purpose: Default constructor for the class. Just sets up the pointers to our buffers 00144 that may be used to be null so that the TidyUp function can do its job. 00145 SeeAlso: OutputDIB::TidyUp 00146 00147 ********************************************************************************************/ 00148 OutputDIB::OutputDIB() 00149 { 00150 OutputFile = NULL; 00151 lpBitmap = NULL; 00152 ExportBuffer = NULL; 00153 DoExportConvert = NULL; 00154 OutputForward = FALSE; 00155 CurrentStripSize = 0; 00156 IsFirstStrip = TRUE; 00157 OutputPalette = NULL; 00158 } 00159 00160 00161 /******************************************************************************************** 00162 00163 > void OutputDIB::PokePaletteEntry(LPLOGPALETTE Palette, INT32 index, BYTE red, BYTE green, BYTE blue) 00164 00165 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00166 Created: 3/4/95 00167 Inputs: Palette palette to write to. 00168 index address of variable holding palette entry to write to 00169 red red value to enter into palette entry 00170 green green value to enter into palette entry 00171 blue blue value to enter into palette entry 00172 Outputs: index incremented by one 00173 Returns: - 00174 Purpose: Puts the required value of rgb into the specified palette entry. 00175 SeeAlso: OutputDIB::StartFile; 00176 00177 ********************************************************************************************/ 00178 void OutputDIB::PokePaletteEntry(LPLOGPALETTE Palette, INT32 *index, BYTE red, BYTE green, BYTE blue) 00179 { 00180 Palette->palPalEntry[*index].peRed = red; 00181 Palette->palPalEntry[*index].peGreen = green; 00182 Palette->palPalEntry[*index].peBlue = blue; 00183 Palette->palPalEntry[*index].peFlags = 0; 00184 // increment the counter and return it 00185 (*index) ++; 00186 } 00187 00188 00189 /****************************************************************************************** 00190 00191 > void OutputDIB::AlterExportPalette( LPLOGPALETTE pPalette ) 00192 00193 Author: Alex_Price (Xara Group Ltd) <camelotdev@xara.com> 00194 00195 Created: 20/07/99 00196 00197 Inputs: pPalette - Palette information that we want to copy from 00198 00199 Returns: - 00200 00201 Purpose: Copies information from the palette object passed in to OutputPalette. 00202 This is used when the user has changed a colour using the bitmap 00203 preview dialog's palette control 00204 00205 ******************************************************************************************/ 00206 00207 void OutputDIB::AlterExportPalette( LPLOGPALETTE pPalette ) 00208 { 00209 if (pPalette == NULL) 00210 return; 00211 /* 00212 // actually it appears it is safe to let this be filled in later if we havent got 00213 // an output palette yet 00214 00215 // if we dont have an output palette we may as well create one now 00216 if (OutputPalette==NULL) 00217 { 00218 const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 ); 00219 OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); 00220 OutputPalette->palNumEntries = 256; 00221 } 00222 */ if (OutputPalette==NULL) 00223 return; 00224 00225 INT32 PreviousNoOfEntries = OutputPalette->palNumEntries; 00226 00227 INT32 Colours = OutputPalette->palNumEntries; 00228 for( INT32 j=0;j<Colours;j++) 00229 { 00230 // Set all the colours to 'non-renderable' first 00231 OutputPalette->palPalEntry[j].peFlags = 255; 00232 } 00233 00234 Colours = pPalette->palNumEntries; 00235 00236 INT32 i = 0; 00237 for(; i < Colours; i++ ) 00238 { 00239 // Copy the colour over to the correct place in OutputPalette 00240 OutputPalette->palPalEntry[i].peRed = pPalette->palPalEntry[i].peRed; 00241 OutputPalette->palPalEntry[i].peGreen = pPalette->palPalEntry[i].peGreen; 00242 OutputPalette->palPalEntry[i].peBlue = pPalette->palPalEntry[i].peBlue; 00243 00244 // Indicate that we want to use the colour in rendering the image 00245 OutputPalette->palPalEntry[i].peFlags = pPalette->palPalEntry[i].peFlags; 00246 } 00247 00248 for(; i < PreviousNoOfEntries; i++ ) 00249 { 00250 // excess colours are black 00251 OutputPalette->palPalEntry[i].peRed = 0; 00252 OutputPalette->palPalEntry[i].peGreen = 0; 00253 OutputPalette->palPalEntry[i].peBlue = 0; 00254 00255 // Indicate that we dont want to use the colour in rendering the image 00256 OutputPalette->palPalEntry[i].peFlags = 255; 00257 } 00258 } 00259 00260 /****************************************************************************************** 00261 00262 > LPBITMAPINFO OutputDIB::GetDestBitmapInfo ( void ) 00263 00264 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00265 Created: 29/6/00 00266 Inputs: pPalette - Palette information that we want to copy from 00267 Returns: NULL 00268 Purpose: Stub function to complete inheritance hierarchy. 00269 00270 ******************************************************************************************/ 00271 00272 LPBITMAPINFO OutputDIB::GetDestBitmapInfo ( void ) 00273 { 00274 // This function should never be called, so return NULL. 00275 return NULL; 00276 } 00277 00278 /****************************************************************************************** 00279 00280 > LPBYTE OutputDIB::GetDestBitmapBits ( void ) 00281 00282 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00283 Created: 29/6/00 00284 Inputs: pPalette - Palette information that we want to copy from 00285 Returns: NULL 00286 Purpose: Stub function to complete inheritance hierarchy. 00287 00288 ******************************************************************************************/ 00289 00290 LPBYTE OutputDIB::GetDestBitmapBits ( void ) 00291 { 00292 // This function should never be called, so return NULL. 00293 return NULL; 00294 } 00295 00296 /******************************************************************************************** 00297 00298 > void OutputDIB::FixBlackAndWhitePalette(LPLOGPALETTE Palette) 00299 00300 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00301 Created: 5/4/95 00302 Inputs: Palette palette to write to. 00303 Outputs: - 00304 Returns: - 00305 Purpose: Corrects the first two palette entries to be a correct Gavin black and white 00306 palette. 00307 SeeAlso: OutputDIB::StartFile; OutputDIB::StartExport; 00308 00309 ********************************************************************************************/ 00310 void OutputDIB::FixBlackAndWhitePalette(LPLOGPALETTE Palette) 00311 { 00312 Palette->palNumEntries = 2; 00313 00314 INT32 i = 0; 00315 PORTNOTE("BmapPrevDlg", "Removed use of bitmap preview dialog"); 00316 #ifndef EXCLUDE_FROM_XARALX 00317 if( BmapPrevDlg::GetNumberOfTransparentColours() > 0 ) 00318 { 00319 PokePaletteEntry(Palette, &i, 0xff, 0xff, 0xff); 00320 PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x00); 00321 } 00322 else 00323 #endif 00324 { 00325 PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x00); 00326 PokePaletteEntry(Palette, &i, 0xff, 0xff, 0xff); 00327 } 00328 } 00329 00330 /******************************************************************************************** 00331 00332 > void OutputDIB::Fix16ColourPalette(LPLOGPALETTE Palette) 00333 00334 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00335 Created: 5/4/95 00336 Inputs: Palette palette to write to. 00337 Outputs: - 00338 Returns: - 00339 Purpose: Corrects the first 16 palette entries to be a correct Gavin 16 colour palette. 00340 SeeAlso: OutputDIB::StartFile; OutputDIB::StartExport; 00341 00342 ********************************************************************************************/ 00343 void OutputDIB::Fix16ColourPalette(LPLOGPALETTE Palette) 00344 { 00345 Palette->palNumEntries = 16; 00346 00347 INT32 i = 0; 00348 // Bit more tricky this one, Gavin uses a fixed 16 colour palette 00349 PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x00); // black 00350 PokePaletteEntry(Palette, &i, 0x80, 0x00, 0x00); // brown 00351 PokePaletteEntry(Palette, &i, 0x00, 0x80, 0x00); // Half green 00352 PokePaletteEntry(Palette, &i, 0x80, 0x80, 0x00); // Half browny (red/green) 00353 PokePaletteEntry(Palette, &i, 0x00, 0x00, 0x80); // Dark blue 00354 PokePaletteEntry(Palette, &i, 0x80, 0x00, 0x80); // Mauve 00355 PokePaletteEntry(Palette, &i, 0x00, 0x80, 0x80); // greeny/blue 00356 PokePaletteEntry(Palette, &i, 0x80, 0x80, 0x80); // mid grey 00357 00358 PokePaletteEntry(Palette, &i, 0xc0, 0xc0, 0xc0); // light grey 00359 PokePaletteEntry(Palette, &i, 0xff, 0x00, 0x00); // red 00360 PokePaletteEntry(Palette, &i, 0x00, 0xff, 0x00); // green 00361 PokePaletteEntry(Palette, &i, 0xff, 0xff, 0x00); // yellow 00362 PokePaletteEntry(Palette, &i, 0x00, 0x00, 0xff); // blue 00363 PokePaletteEntry(Palette, &i, 0xff, 0x00, 0xff); // magenta 00364 PokePaletteEntry(Palette, &i, 0x00, 0xff, 0xff); // cyan 00365 PokePaletteEntry(Palette, &i, 0xff, 0xff, 0xff); // white 00366 } 00367 00368 /******************************************************************************************** 00369 00370 > BOOL OutputDIB::StartFile( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPRGBQUAD Palette, 00371 UINT32 OutputDepth, DWORD CompressionType, 00372 UINT32 FinalHeight, INT32 SizeOfExport, BOOL SecondPass = FALSE ) 00373 00374 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> 00375 Created: 4/8/94 00376 Inputs: File opened file we can write to. 00377 lpHeader contains width & DPI of source & dest. biHeight & depth ignored. 00378 Palette pointer to bmiColor struct, or NULL if not used (can be temporary) 00379 OutputDepth depth of bitmap required on disk 00380 CompressionType BI_RGB only supported (or CC_BMPTYPE for 32-bit with trans) 00381 FinalHeight output of entire bitmap on disk 00382 ExportSize The set progress bar size 00383 SecondPass Flag for whether it is a second pass export render. (Used by 00384 GIF export only at present). Defaults to False. 00385 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 00386 Purpose: Get ready to write a bmp to disk, maybe in chunks showing a progress bar as we 00387 write it. 00388 Currently supports:- 00389 source depth = 32, destintaiotn depth = 32, 24, 8, 4, 1 00390 source depth = 8, destintaiotn depth = 8 00391 Errors: Calls SetError on FALSE returns. 00392 SeeAlso: OutputDIB::WriteBlock; OutputDIB::TidyUp 00393 SeeAlso: OutputGIF::StartFile; 00394 Scope: Public 00395 00396 ********************************************************************************************/ 00397 00398 BOOL OutputDIB::StartFile( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette, 00399 UINT32 OutputDepth, DWORD CompressionType, 00400 UINT32 FinalHeight, INT32 ExportSize, BOOL SecondPass, 00401 UINT32 DitherType ) 00402 { 00403 // remember input args 00404 OutputFile = File; 00405 StartPos = OutputFile->tell(); // remember where in the file this starts 00406 BitmapInfo = *lpHeader; // take a copy of user's header 00407 OutputPalette = NULL; // our form of the palette, if required 00408 00409 HeightWritten = 0; // our count of the bitmap lines written 00410 CurrentExportSize = ExportSize; // size set up for the progress bar 00411 HeightWanted = FinalHeight; // the actual height of the export required 00412 00413 INT32 PalSize = 0; // how many entries in palette 00414 00415 // Remember which dithering type to use 00416 Dither = DitherType; 00417 00418 IsFirstStrip = TRUE; 00419 00420 // Set up the information header for the dib 00421 if ( !SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, FinalHeight, &PalSize) ) 00422 return FALSE; // SetError already called 00423 00424 // BITMAPFILEHEADER goes first 00425 BITMAPFILEHEADER Header; 00426 00427 Header.bfType = ('M'<<8) | 'B'; 00428 Header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 00429 sizeof(RGBQUAD)*PalSize + BitmapInfo.biSizeImage; 00430 Header.bfReserved1 = 0; 00431 Header.bfReserved2 = 0; 00432 Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 00433 sizeof(RGBQUAD)*PalSize; 00434 00435 OutputFile->write( &Header, sizeof(Header) ); 00436 00437 00438 // then a local BITMAPINFOHEADER 00439 00440 OutputFile->write( &BitmapInfo, sizeof(BITMAPINFOHEADER) ); 00441 00442 // then the RGBQUAD palette 00443 if (PalSize) 00444 { 00445 ERROR2IF(Palette == NULL,FALSE,"StartFile has a NULL Palette when one is required"); 00446 // make a copy of the palette for possible later use 00447 const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize ); 00448 OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); 00449 if (OutputPalette==NULL) 00450 return FALSE; 00451 00452 // Take a copy of that palette 00453 memcpy( OutputPalette, Palette, TotalPal ); 00454 00455 // write it to disk in RGBQUAD format 00456 RGBQUAD TempRGB; 00457 TempRGB.rgbReserved = 0; 00458 for (INT32 i=0; i<PalSize; i++) 00459 { 00460 TempRGB.rgbRed = OutputPalette->palPalEntry[i].peRed; 00461 TempRGB.rgbGreen = OutputPalette->palPalEntry[i].peGreen; 00462 TempRGB.rgbBlue = OutputPalette->palPalEntry[i].peBlue; 00463 OutputFile->write( &TempRGB, sizeof(RGBQUAD) ); 00464 } 00465 } 00466 00467 return !OutputFile->bad(); 00468 } 00469 00470 /******************************************************************************************** 00471 00472 > BOOL OutputDIB::StartFile ( LPBITMAPINFOHEADER lpHeader, 00473 LPLOGPALETTE Palette, 00474 UINT32 OutputDepth, 00475 DWORD CompressionType, 00476 UINT32 FinalHeight, 00477 INT32 ExportSize, 00478 UINT32 DitherType ) 00479 00480 Author: Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com> 00481 Created: 27/6/00 00482 Inputs: All are meaningless. 00483 Returns: FALSE. 00484 Purpose: Stub function to be inherited over. 00485 00486 ********************************************************************************************/ 00487 00488 BOOL OutputDIB::StartFile ( LPBITMAPINFOHEADER lpHeader, 00489 LPLOGPALETTE Palette, 00490 UINT32 OutputDepth, 00491 DWORD CompressionType, 00492 UINT32 FinalHeight, 00493 INT32 ExportSize, 00494 UINT32 DitherType ) 00495 { 00496 return FALSE; 00497 } 00498 00499 /******************************************************************************************** 00500 00501 > BOOL OutputDIB::SetUpInfoHeader(const LPBITMAPINFOHEADER lpHeader, const UINT32 OutputDepth, 00502 const DWORD CompressionType, const UINT32 FinalHeight, 00503 INT32 * pPalSize) 00504 00505 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00506 Created: 9/11/94 00507 Inputs: lpHeader contains width & DPI of source & dest. biHeight & depth ignored. 00508 OutputDepth depth of bitmap required on disk 00509 CompressionType BI_RGB only supported (or CC_BMPTYPE for 32-bit with trans) 00510 FinalHeight output of entire bitmap on disk 00511 Outputs: pPalSize pointer to an integer PalSize variable which is the palette size 00512 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 00513 Purpose: Set up the information header for the DIB. 00514 Errors: Calls SetError on FALSE returns. 00515 SeeAlso: OutputDIB::StartFile; OutputDIB::WriteBlock; OutputDIB::TidyUp 00516 Scope: Public 00517 00518 ********************************************************************************************/ 00519 00520 BOOL OutputDIB::SetUpInfoHeader(const LPBITMAPINFOHEADER lpHeader, const UINT32 OutputDepth, 00521 const DWORD CompressionType, const UINT32 FinalHeight, 00522 INT32 * pPalSize) 00523 { 00524 if ( 00525 (CompressionType != BI_RGB) && // uncompressed is OK 00526 (CompressionType != CC_BMPTYPE) // so is RGBT 00527 ) 00528 { 00529 // cannot do compression yet 00530 Error::SetError( _R(IDE_FORMATNOTSUPPORTED) ); 00531 return FALSE; 00532 } 00533 00534 // Fix up our copy of the header sohat it corresponds to the actual required one 00535 BitmapInfo.biCompression = CompressionType; // fixup compression type 00536 BitmapInfo.biHeight = FinalHeight; // fixup height to be true height 00537 BitmapInfo.biBitCount = OutputDepth; 00538 00539 SourceBitmapDepth = lpHeader->biBitCount; 00540 00541 const WORD DestDepth = BitmapInfo.biBitCount; 00542 UINT32 LineWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, OutputDepth ); 00543 00544 // source bitmap not necessarily same as required file depth 00545 // make sure we can handle conversion 00546 BOOL FormatOK = FALSE; 00547 00548 switch (SourceBitmapDepth) 00549 { 00550 case 32: 00551 { 00552 switch (DestDepth) 00553 { 00554 case 32: 00555 { 00556 // 32->32 might use our special type CC_BMPTYPE 00557 FormatOK = TRUE; 00558 } 00559 break; 00560 case 24: 00561 { 00562 // 32->24 bit is fine 00563 if (CompressionType==BI_RGB) 00564 { 00565 // might be BITFIELDs for rendering purposes 00566 BitmapInfo.biCompression = BI_RGB; 00567 BitmapInfo.biBitCount = 24; 00568 FormatOK = TRUE; 00569 } 00570 } 00571 break; 00572 case 8: 00573 { 00574 // 32->8 is OK 00575 FormatOK = TRUE; 00576 *pPalSize = 256; 00577 } 00578 break; 00579 case 4: 00580 { 00581 // 32->4 is OK 00582 FormatOK = TRUE; 00583 *pPalSize = 16; 00584 } 00585 break; 00586 case 1: 00587 { 00588 // 32->1 is OK 00589 FormatOK = TRUE; 00590 *pPalSize = 2; 00591 } 00592 break; 00593 default: 00594 // other source formats here 00595 break; 00596 } 00597 00598 } 00599 break; 00600 case 8: 00601 if (DestDepth==8) 00602 { 00603 // 8->8 is OK 00604 FormatOK = TRUE; 00605 *pPalSize = 256; 00606 } 00607 break; 00608 default: 00609 // other source formats here 00610 break; 00611 } 00612 00613 if (!FormatOK) 00614 { 00615 Error::SetError( _R(IDE_FORMATNOTSUPPORTED) ); 00616 return FALSE; 00617 } 00618 00619 BitmapInfo.biSizeImage = LineWidth * FinalHeight; 00620 00621 return TRUE; 00622 } 00623 00624 /******************************************************************************************** 00625 00626 > BOOL OutputDIB::WriteBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP = 32, 00627 INT32 ProgressOffset = 0) 00628 00629 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> 00630 Created: 4/8/94 00631 Inputs: YPos pixel co-ord of the chunk of DIB we are about to write out (0=bottom, 00632 increasing as it goes up). 00633 Height height in pixels of this chunk 00634 BlockStart the start address of the bytes of this chunk 00635 (optional) InputBPP BPP of the input image (assumed 32 by default - 8 also works) 00636 ProgressOffset value to add to value passed to ContinueSlowJob (default 0). 00637 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 00638 Purpose: Writes a chunk of bitmap data to the device. 00639 Assumes a progress hourglass is required and the caller has started an hourglass 00640 with a size of 100 and will end it. 00641 Notes: Originally this routine assumed that it was being given a 32bpp bmp, but using 00642 the InputBPP param it will now handle 8bpp bmps as well... 00643 Errors: Calls SetError on FALSE returns. 00644 Scope: Public 00645 00646 ********************************************************************************************/ 00647 00648 BOOL OutputDIB::WriteBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP, 00649 INT32 ProgressOffset) 00650 { 00651 FNPTR_SCANLINE ConvertFn = NULL; 00652 LPBYTE Buffer = NULL; 00653 size_t BufSize = 0L; 00654 size_t ChunkHeight = 1; 00655 DIBConvert *DoConvert = NULL; 00656 00657 // Set up the size and other information for the dib block that we require. This is 00658 // dependent on the export depth or bpp required. 00659 if ( !SetUpBlock( &BufSize, &ChunkHeight, &DoConvert, &ConvertFn ) ) 00660 return FALSE; // Error details already set up 00661 00662 if (BufSize) 00663 { 00664 Buffer = (LPBYTE)CCMalloc( BufSize ); 00665 if (Buffer==NULL) 00666 return FALSE; 00667 } 00668 00669 if ( DoConvert ) 00670 { 00671 // use new classes to do it 00672 // 8bpp, 4bpp and 1bpp conversion 00673 INT32 h = Height; 00674 INT32 count = 0; 00675 LPBYTE Data = BlockStart; 00676 const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP ) * ChunkHeight; 00677 const size_t DestWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, BitmapInfo.biBitCount ); 00678 00679 while (h) 00680 { 00681 ENSURE(h >= 0, "bad looping"); 00682 00683 const size_t ThisBit = min( h, (INT32)ChunkHeight ); 00684 if (!DoConvert->Convert( Data, Buffer, ThisBit, IsFirstStrip )) 00685 break; // stop if conversion failed 00686 00687 IsFirstStrip = FALSE; 00688 00689 OutputFile->write( Buffer, ThisBit * DestWidth ); 00690 if (OutputFile->bad()) 00691 break; // stop if file errored 00692 Data += SourceWidth; 00693 h -= ThisBit; 00694 00695 // now update the progress display, started with CurrentExportSize 00696 // CurrentExport size is now the point to go from in the export 00697 count++; 00698 ContinueSlowJob( (INT32)( ProgressOffset + count )); 00699 //ContinueSlowJob( (INT32)(100*count/(Height)) ); 00700 } 00701 } 00702 // now the bytes (this is crying out for a virtual function or two) 00703 else if ( ConvertFn && Buffer ) 00704 { 00705 // Write via conversion function 00706 // 24 bpp convert 00707 UINT32 h = Height; 00708 INT32 count = 0; 00709 LPBYTE Data = BlockStart; 00710 const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP ); 00711 00712 while (h) 00713 { 00714 ConvertFn( BitmapInfo.biWidth, Data, Buffer ); 00715 OutputFile->write( Buffer, BufSize ); 00716 if (OutputFile->bad()) 00717 break; // stop if file errored 00718 Data += SourceWidth; 00719 h -= ChunkHeight; 00720 00721 // now update the progress display, started with CurrentExportSize 00722 // ProgressOffset size is now the point to go from in the export 00723 count++; 00724 ContinueSlowJob( (INT32)( ProgressOffset + count )); 00725 //ContinueSlowJob( (INT32)((CurrentExportSize * count)/Height) ); 00726 } 00727 } 00728 else 00729 { 00730 // Write it all out in one go 00731 //OutputFile->write( BlockStart, BitmapInfo.biSizeImage ); 00732 // Write the actual bytes out to file. Used to do it in one go but we really 00733 // require some progress bar indication so we will do it in chunks. 00734 DWORD BitsSize = BitmapInfo.biSizeImage; 00735 if (BitsSize > 0) 00736 { 00737 if (BitsSize < 1024) 00738 { 00739 // File very small or no progress bar required, so load in one go 00740 OutputFile->write( BlockStart, BitsSize); 00741 } 00742 else 00743 { 00744 // Load in chunks, for present split into 100 chunks 00745 DWORD ChunkSize = BitsSize/100; 00746 DWORD Position = 0; 00747 LPBYTE pBitInfo = BlockStart; 00748 00749 while (Position < BitsSize) 00750 { 00751 if ( (BitsSize - Position) > ChunkSize) 00752 OutputFile->write( pBitInfo, ChunkSize); 00753 else 00754 { 00755 ChunkSize = BitsSize - Position; 00756 OutputFile->write( pBitInfo, ChunkSize); 00757 } 00758 00759 // Increment our counters/pointers 00760 Position+=ChunkSize; 00761 pBitInfo+=ChunkSize; 00762 // Progress bar started with height of bitmap 00763 ContinueSlowJob( (INT32)(ProgressOffset + (Height * Position)/BitsSize) ); 00764 //ContinueSlowJob( (INT32)((CurrentExportSize * Position)/BitsSize) ); 00765 } 00766 } 00767 } 00768 } 00769 00770 // If present, get rid of our export function 00771 if (DoConvert) 00772 { 00773 delete DoConvert; 00774 DoConvert = NULL; 00775 } 00776 00777 CCFree( Buffer ); 00778 00779 HeightWritten += Height; // remember we wrote this lot 00780 00781 return !OutputFile->bad(); 00782 } 00783 00784 /******************************************************************************************** 00785 // 00786 // These are the forms used by the Accusoft filters and hence do not write out the data 00787 // themselves but get called back to supply the data. 00788 // 00789 ********************************************************************************************/ 00790 00791 // The following function is no longer used but retained for informational reasons 00792 #if 0 00793 /******************************************************************************************** 00794 00795 > BOOL OutputDIB::SetUpExport( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPRGBQUAD Palette, 00796 UINT32 DitherType, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight, 00797 LPBYTE BlockStart, UINT32 StripSize, INT32 ExportSize, BOOL Forward) 00798 00799 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00800 Created: 9/11/94 00801 Inputs: File opened file we can write to. 00802 lpHeader contains width & DPI of source & dest. biHeight & depth ignored. 00803 Palette pointer to bmiColor struct, or NULL if not used (can be temporary) 00804 OutputDepth depth of bitmap required on disk 00805 CompressionType BI_RGB only supported (or CC_BMPTYPE for 32-bit with trans) 00806 FinalHeight output of entire bitmap on disk 00807 BlockStart pointer to the start of the bitmap data 00808 StripSize size of the first strip to be rendered 00809 ExportSize The set progress bar size 00810 Forward dictates whether we are to write the data out forwards or backwards 00811 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 00812 Purpose: Same as OutputDIB::StartFile but does not actually write the data to a file 00813 but instead tries to get ready to write a bmp out to disk via the Accusoft or 00814 other external filters, maybe in chunks showing a progress bar as we write it. 00815 Currently supports:- 00816 source depth = 32, destintaiotn depth = 32, 24, 8, 4, 1 00817 source depth = 8, destintaiotn depth = 8 00818 We need to be able to write data from the bottom to the top of the DIB as well 00819 as from the top to the bottom as it would appear that the Accusoft DLL tries to 00820 be clever and save DIBs forward and everything else backwards. 00821 Errors: Calls SetError on FALSE returns. 00822 SeeAlso: OutputDIB::StartFile; OutputDIB::WriteBlock; OutputDIB::TidyUp; OutputDIB::GetNextBlock 00823 Scope: Public 00824 00825 ********************************************************************************************/ 00826 00827 BOOL OutputDIB::SetUpExport( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette, 00828 UINT32 DitherType, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight, 00829 LPBYTE BlockStart, UINT32 StripSize, INT32 ExportSize, BOOL Forward ) 00830 { 00831 ERROR2IF(File==NULL, FALSE, "OutputDIB::SetUpExport null File specified"); 00832 ERROR2IF(lpHeader==NULL, FALSE, "OutputDIB::SetUpExport null lpHeader specified"); 00833 ERROR2IF(BlockStart==NULL, FALSE, "OutputDIB::SetUpExport null BlockStart specified"); 00834 00835 // remember input args 00836 OutputFile = File; 00837 StartPos = OutputFile->tell(); // remember where in the file this starts 00838 BitmapInfo = *lpHeader; // take a copy of user's header 00839 OutputPalette = NULL; // No palette to start with 00840 HeightWritten = 0; // zero height 00841 OutputForward = Forward; // Note the output direction 00842 CurrentStripSize = StripSize; // Note size of first strip 00843 CurrentExportSize = ExportSize; // size set up for the progress bar 00844 HeightWanted = FinalHeight; // the actual height of the export required 00845 00846 // Remember which dithering type to use 00847 Dither = DitherType; 00848 00849 IsFirstStrip = TRUE; 00850 00851 ExportBuffer = NULL; // Just in case of early random exit set this to NULL 00852 00853 INT32 PalSize = 0; // how many entries in palette 00854 00855 // Set up the information header for the dib 00856 if ( !SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, FinalHeight, &PalSize) ) 00857 return FALSE; // SetError already called 00858 00859 // then the RGBQUAD palette, if required 00860 if (PalSize) 00861 { 00862 ERROR2IF(Palette == NULL,FALSE,"SetUpExport has a NULL Palette when one is required"); 00863 // If we are creating a palette then the Accusoft code requires that we specify an 00864 // bitmap info header which is followed immediately in memory by the palette. 00865 // if we just created a Palette then this would not be true so we must create a 00866 // new copy of the Bitmapinfo and then create the palette next. 00867 // This will not work in debug builds due to memory tracking information stored 00868 // in the allocation so we must allocate one big block and do the info header and 00869 // Palette from these. 00870 const size_t TotalHeader = sizeof(BITMAPINFOHEADER); 00871 const size_t TotalPalSize = (sizeof(RGBQUAD) * PalSize ); 00872 lpBitmap = (LPBITMAPINFO)CCMalloc( TotalHeader + TotalPalSize ); 00873 if (lpBitmap==NULL) 00874 return FALSE; 00875 00876 // make a copy of the palette for possible later use 00877 const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize ); 00878 00879 OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); 00880 if (OutputPalette==NULL) 00881 return FALSE; 00882 memcpy( OutputPalette, Palette, TotalPal ); 00883 00884 // These are all freed in the TidyUp call. 00885 00886 // Take a copy of the bitmap info header 00887 lpBitmapInfo = &(lpBitmap->bmiHeader); // pointer to info header 00888 memcpy( lpBitmapInfo, &BitmapInfo, TotalHeader ); // copy header info across 00889 00890 // Now get a pointer to the palette 00891 LPRGBQUAD lpPalette = NULL; 00892 lpPalette = &(lpBitmap->bmiColors[0]); // pointer to colours table 00893 00894 // Now copy the palette across into the bitmap info structure in RGQUAD form 00895 // OutputPalette should be set up by now so use this instead of Palette so if 00896 // we have bodged it, it will be the correct bodged palette that is put into the file 00897 // and not the 256 entry palette that seems to be supplied always. 00898 00899 // We might want to use the existing palette - e.g. when we are altering the value 00900 // of a single colour. 00901 // Don't want to use the existing palette. 00902 for (INT32 i = 0; i < PalSize; i++) 00903 { 00904 lpPalette->rgbRed = OutputPalette->palPalEntry[i].peRed; 00905 lpPalette->rgbGreen = OutputPalette->palPalEntry[i].peGreen; 00906 lpPalette->rgbBlue = OutputPalette->palPalEntry[i].peBlue; 00907 00908 lpPalette++; 00909 } 00910 00911 } 00912 00913 // Now lets grab the memory and then set up the first block of data ready for output 00914 size_t BufSize = 0L; 00915 ExportChunkHeight = 1; 00916 00917 DoExportConvert = NULL; // Just in case the SetUpBlock fails 00918 ExportConvertFn = NULL; // Just in case the SetUpBlock fails 00919 00920 // Set up the size and other information for the dib block that we require. This is 00921 // dependent on the export depth or bpp required. 00922 if ( !SetUpBlock( &BufSize, &ExportChunkHeight, &DoExportConvert, &ExportConvertFn ) ) 00923 return FALSE; // Error details already set up 00924 00925 //TRACEUSER( "Neville", _T("SetUpExport BufSize = %d\n"),BufSize); 00926 //TRACEUSER( "Neville", _T("SetUpExport ExportChunkHeight = %d\n"),ExportChunkHeight); 00927 //TRACEUSER( "Neville", _T("SetUpExport FinalHeight = %d\n"),FinalHeight); 00928 //TRACEUSER( "Neville", _T("SetUpExport CurrentStripSize = %d\n"),CurrentStripSize); 00929 //TRACEUSER( "Neville", _T("SetUpExport DoExportConvert = %d\n"),DoExportConvert); 00930 //TRACEUSER( "Neville", _T("SetUpExport ExportConvertFn = %d\n"),ExportConvertFn); 00931 00932 // Check for the case where we are exporting a small thin strip which is smaller 00933 // than our normal strip 00934 if (CurrentStripSize < ExportChunkHeight) 00935 { 00936 ExportChunkHeight = CurrentStripSize; 00937 //TRACEUSER( "Neville", _T("New ExportChunkHeight = %d\n"),ExportChunkHeight); 00938 } 00939 00940 if (BufSize) 00941 { 00942 ExportBuffer = (LPBYTE)CCMalloc( BufSize ); 00943 if (ExportBuffer==NULL) 00944 return FALSE; 00945 } 00946 00947 // Now get the actual class variables set up ready for this data 00948 SetUpForNextStrip(BlockStart, CurrentStripSize); 00949 00950 // Now lets start the whole export process off by calling the StartSaveBitmap function 00951 // which will start the actual exporting process off with the supplied information. 00952 // This will then request blocks of data from the DestDIB in its call back routine 00953 // get_dib_data. 00954 00955 // If we have created a palette then use the special header which has a valid palette 00956 // following immediately after it in memory 00957 LPBITMAPINFOHEADER lpSpBitmapInfo = NULL; 00958 if (PalSize) 00959 lpSpBitmapInfo = lpBitmapInfo; // Use our specially create header followed by palette 00960 else 00961 lpSpBitmapInfo = &BitmapInfo; // Use the proper header defined in the class 00962 00963 #ifndef WEBSTER 00964 //WEBSTER-Martin-07/01/97 00965 // no Accusoft stuff in WEBSTER, and I'm not sure it ever gets used in Camelot any 00966 // more (the DIB bits of Accusoft that is) 00967 // TRACEUSER( "Martin", _T("Not allowed to use Accusoft save bitmap\n")); 00968 if (!AccusoftFilters::StartSaveBitmap( OutputFile, // File to use 00969 lpSpBitmapInfo, // pointer to info header 00970 OutputPalette, // pointer to the palette 00971 OutputDepth, // actual file depth 00972 BI_RGB, // compression (BI_RGB = none) 00973 FinalHeight, // all of it 00974 StripSize, // size of the strip, might be FinalHeight 00975 OutputForward) // direction we were told on entry 00976 ) 00977 #endif //WEBSTER 00978 { 00979 return FALSE; //always for WEBSTER 00980 } 00981 00982 return TRUE; 00983 } 00984 #endif 00985 00986 00987 /******************************************************************************************** 00988 00989 > static BOOL OutputDIB::GetNextBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, 00990 LPBYTE *Buffer, UINT32 *CurrentBlockSize, 00991 INT32 *CurrentStartYPos) 00992 00993 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00994 Created: 9/11/94 00995 Inputs: YPos pixel co-ord of the chunk of DIB we are about to write out 00996 (0 = bottom, increasing as it goes up). 00997 Height height in pixels of this chunk 00998 BlockStart the start address of the bytes of this chunk 00999 Outputs: Buffer pointer to the returned buffer filled up with DIB bytes 01000 CurrentBlockSize current size of the block being rendered 01001 CurrentStartYPos current position of the start of this block of data 01002 WrittenSoFar the amount of the bitmap written to date 01003 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 01004 Purpose: Gets the next chunk of bitmap data ready to be written out via the Accusoft or 01005 other external filters. 01006 SetUpExport is used to set up everything before this fucntion is called. 01007 OutputForward determines the direction of export, set up in SetUpExport 01008 Errors: Calls SetError on FALSE returns. 01009 SeeAlso: OutputDIB::WriteBlock; OutputDIB::SetUpExport; 01010 Scope: Public 01011 01012 ********************************************************************************************/ 01013 01014 BOOL OutputDIB::GetNextBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, 01015 LPBYTE *Buffer, INT32 *CurrentBlockSize, 01016 INT32 *CurrentStartYPos, UINT32 *WrittenSoFar) 01017 { 01018 // Get the next block ready for export a line at a time 01019 *Buffer = NULL; // Just in case of early random exit set this to NULL 01020 *CurrentBlockSize = 0; // Just in case of early random exit set this to 0 01021 01022 // Convert the next strip 01023 if ( DoExportConvert ) 01024 { 01025 //TRACEUSER( "Neville", _T("GetNextBlock DoExportConvert\n")); 01026 // 8 bpp, 4bpp and 1bpp export 01027 ERROR2IF(ExportData < BlockStart, FALSE, "GetNextBlock ExportData < BlockStart"); 01028 ERROR2IF(Height - CurrentYPos < 0, FALSE, "GetNextBlock Height - CurrentYPos < 0"); 01029 // Work out the size of the export chunk left, normally ExportChunkHeight but 01030 // if at the end of export may be a small strip left. 01031 const size_t ThisBit = min( (INT32)(Height - CurrentYPos), (INT32)ExportChunkHeight ); 01032 if (!DoExportConvert->Convert( ExportData, ExportBuffer, ThisBit, IsFirstStrip )) 01033 return FALSE; // stop if conversion failed 01034 01035 IsFirstStrip = FALSE; 01036 01037 // We have in ExportData a size of data block = ThisBit * ExportDestWidth 01038 // On last strip may be less than ExportChunkHeight in depth 01039 CurrentYPos += ThisBit; // Move down by a strips worth 01040 01041 if (OutputForward) 01042 { 01043 ExportData += ExportSourceWidth; // Move on by a lines worth 01044 } 01045 else 01046 { 01047 if ((Height - CurrentYPos) < ExportChunkHeight ) 01048 ExportData = BlockStart; // On last strip so do from start 01049 else 01050 ExportData -= ExportSourceWidth; // Move on by a lines worth 01051 if (ExportData < BlockStart) // Just in case test 01052 ExportData = BlockStart; 01053 } 01054 01055 // Set up return variables 01056 *Buffer = ExportBuffer; // return our new buffer to the caller 01057 *CurrentBlockSize = ThisBit; // return size of this block 01058 *CurrentStartYPos = CurrentYPos; // return current start of strip 01059 01060 HeightWritten += ThisBit; // remember we wrote this lot 01061 } 01062 // now the bytes (this is crying out for a virtual function or two) 01063 else if ( ExportConvertFn && ExportBuffer ) 01064 { 01065 // 24 bpp convert 01066 //TRACEUSER( "Neville", _T("GetNextBlock Do export via convert function\n")); 01067 ERROR2IF(ExportData < BlockStart, FALSE, "GetNextBlock ExportData < BlockStart"); 01068 // write data via conversion function 01069 ExportConvertFn( BitmapInfo.biWidth, ExportData, ExportBuffer ); 01070 01071 if (OutputForward) 01072 { 01073 // We have in ExportBuffer an amount of BuffSize worth of data 01074 ExportData += ExportSourceWidth; 01075 CurrentYPos -= ExportChunkHeight; 01076 } 01077 else 01078 { 01079 // We have in ExportBuffer an amount of BuffSize worth of data 01080 ExportData -= ExportSourceWidth; 01081 CurrentYPos += ExportChunkHeight; 01082 } 01083 01084 // Set up return variables 01085 *Buffer = ExportBuffer; // return our new buffer to the caller 01086 *CurrentBlockSize = ExportChunkHeight; // return size of this block 01087 *CurrentStartYPos = CurrentYPos; // return current start of strip 01088 01089 HeightWritten += ExportChunkHeight; // remember we wrote this lot 01090 01091 } 01092 else 01093 { 01094 //TRACEUSER( "Neville", _T("GetNextBlock all in one go\n")); 01095 // Write it all out in one go, 32bpp export 01096 // We have in the DIB at BlockStart an amount of BitmapInfo.biSizeImage worth of data 01097 // Set up return variables 01098 *Buffer = BlockStart; // return our new buffer to the caller 01099 *CurrentBlockSize = BitmapInfo.biSizeImage; // return size of this block 01100 01101 HeightWritten += Height; // remember we wrote this lot 01102 } 01103 01104 // Return the amount of data written so far 01105 *WrittenSoFar = HeightWritten; 01106 01107 return TRUE; 01108 } 01109 01110 /******************************************************************************************** 01111 01112 static BOOL OutputDIB::SetUpForNextStrip(LPBYTE StartOfBytes, UINT32 StripHeight) 01113 01114 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01115 Created: 15/5/95 01116 Inputs: StartOfBytes start of the actual bitmap data (bits) 01117 StripHeight height of this strip 01118 Outputs: - 01119 Returns: TRUE if worked, FALSE if failed 01120 Purpose: Gets the class variables ready for the first/next strip of the render region 01121 as we are rendering in strips. 01122 Scope: Public Static 01123 01124 ********************************************************************************************/ 01125 01126 BOOL OutputDIB::SetUpForNextStrip(LPBYTE StartOfBytes, UINT32 StripHeight) 01127 { 01128 // We have rendered the next strip into the render region so reset everything back 01129 // to start outputting this strip instead of the old one 01130 CurrentStripSize = StripHeight; 01131 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip StripHeight=%d\n"),StripHeight); 01132 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip HeightWritten=%d\n"),HeightWritten); 01133 01134 // Now get the actual data ready 01135 if ( DoExportConvert ) 01136 { 01137 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip DoExportConvert\n")); 01138 // 8bpp, 4bpp and 1bpp conversion 01139 UINT32 LineWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 ); 01140 ExportSourceWidth = LineWidth * ExportChunkHeight; 01141 ExportDestWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, BitmapInfo.biBitCount ); 01142 01143 if (OutputForward) 01144 { 01145 // Set up the pointer to the first block of DIB bytes to export 01146 // In this forward direction it is the start of the first strip of the DIB 01147 ExportData = StartOfBytes; 01148 } 01149 else 01150 { 01151 // Set up the pointer to the first block of DIB bytes to export 01152 // Which is the start of the last strip of the DIB 01153 ExportData = StartOfBytes + ((StripHeight * LineWidth) - ExportSourceWidth); 01154 } 01155 } 01156 // now the bytes (this is crying out for a virtual function or two) 01157 else if ( ExportConvertFn && ExportBuffer ) 01158 { 01159 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip Do via convert function to ExportBuffer\n")); 01160 // 24 bpp convert 01161 ExportSourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 ); 01162 01163 if (OutputForward) 01164 { 01165 // Set up the pointer to the first block of DIB bytes to export 01166 // In this forward direction it is the start of the first strip of the DIB 01167 ExportData = StartOfBytes; 01168 } 01169 else 01170 { 01171 // Set up the pointer to the first block of DIB bytes to export 01172 // Which is the start of the last strip of the DIB 01173 ExportData = StartOfBytes + ((StripHeight - 1) * ExportSourceWidth); 01174 } 01175 } 01176 else 01177 { 01178 //TRACEUSER( "Neville", _T("OutputDIB::SetUpForNextStrip Do all in one go\n")); 01179 // We will write it all in one go 01180 ExportData = StartOfBytes; // pointer to the DIB bytes 01181 } 01182 //TRACEUSER( "Neville", _T("ExportSourceWidth = %d\n"),ExportSourceWidth); 01183 //TRACEUSER( "Neville", _T("ExportDestWidth = %d\n"),ExportDestWidth); 01184 01185 // Just in case the initial block is smaller than the usual output depth and hence 01186 // we will be trying to export data to before the start of the block. A quick check 01187 // is in order. 01188 if (ExportData < StartOfBytes) // Just in case 01189 ExportData = StartOfBytes; 01190 01191 // Set up the starting parameters of the export operation. 01192 // Remember we have to export from the end of the DIB up to the start otherwise 01193 // the output will be upside down. 01194 CurrentYPos = 0; // size of DIB in scan lines 01195 01196 return TRUE; 01197 } 01198 01199 /******************************************************************************************** 01200 01201 > BOOL OutputDIB::SetUpBlock( size_t *pBufSize, size_t *pChunkHeight, DIBConvert **pDoConvert, 01202 FNPTR_SCANLINE *pConvertFn ) 01203 01204 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01205 Created: 9/11/94 01206 Inputs: 01207 Outputs: pBufSize pointer to a size_t which gives the buffer size required for this 01208 output depth. 01209 pChunkHeight pointer to a size_t which gives the size of chunk required for 01210 this output depth. 01211 pDoConvert pointer to a pointer to a dib convert class for this depth. 01212 pConvertFn pointer to a convert function pointer 01213 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 01214 Purpose: Gets the next chunk of bitmap data ready to be written out via the Accusoft or 01215 other external filters. 01216 Notes: This routine will currently handle conversions from 32->32, 32->24, 32->8 and 01217 now 8->8. 01218 Errors: Calls SetError on FALSE returns. 01219 Scope: Public 01220 01221 ********************************************************************************************/ 01222 01223 BOOL OutputDIB::SetUpBlock( size_t *pBufSize, size_t *pChunkHeight, DIBConvert **pDoConvert, 01224 FNPTR_SCANLINE *pConvertFn ) 01225 { 01226 BOOL Problems = FALSE; 01227 01228 switch (SourceBitmapDepth) 01229 { 01230 case 32: 01231 { 01232 switch (BitmapInfo.biBitCount) 01233 { 01234 case 32: 01235 { 01236 // real 32-bit BMPs here 01237 // our 'filter' zeros the transparency bits 01238 *pConvertFn = DIBUtil::Convert32to32; 01239 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 32 ); 01240 } 01241 break; 01242 case 24: 01243 { 01244 // convert 32-bit BMPs to 24-bit ones so things can read them 01245 *pConvertFn = DIBUtil::Convert32to24; // 32->24 01246 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 24 ); // size of 24-bit scanline 01247 } 01248 break; 01249 case 8: 01250 { 01251 // 32->8 we do in bigger chunks because of dithering 01252 *pDoConvert = DIBConvert::Create( SourceBitmapDepth, 8, BitmapInfo.biWidth, OutputPalette, Dither ); 01253 if (*pDoConvert==NULL) 01254 { 01255 ENSURE(FALSE, "DIBConvert::Create returned NULL"); 01256 return FALSE; 01257 } 01258 *pChunkHeight = 16; 01259 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 8 ) * (*pChunkHeight); 01260 } 01261 break; 01262 case 4: 01263 { 01264 // 32->4 we do in bigger chunks because of dithering 01265 *pDoConvert = DIBConvert::Create( SourceBitmapDepth, 4, BitmapInfo.biWidth, OutputPalette, Dither ); 01266 if (*pDoConvert==NULL) 01267 { 01268 ENSURE(FALSE, "DIBConvert::Create returned NULL"); 01269 return FALSE; 01270 } 01271 *pChunkHeight = 16; 01272 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 4 ) * (*pChunkHeight); 01273 } 01274 break; 01275 case 1: 01276 { 01277 // 32->1 we do in bigger chunks because of dithering 01278 *pDoConvert = DIBConvert::Create( SourceBitmapDepth, 1, BitmapInfo.biWidth, OutputPalette, Dither ); 01279 if (*pDoConvert==NULL) 01280 { 01281 ENSURE(FALSE, "DIBConvert::Create returned NULL"); 01282 return FALSE; 01283 } 01284 *pChunkHeight = 16; 01285 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 1 ) * (*pChunkHeight); 01286 } 01287 break; 01288 default: 01289 Problems = TRUE; 01290 break; 01291 } 01292 break; 01293 } 01294 case 8: 01295 if (BitmapInfo.biBitCount==8) 01296 { 01297 // real 8-bit BMPs here 01298 // we basically just do a memory copy from source to dest 01299 *pConvertFn = DIBUtil::Convert8to8; 01300 *pBufSize = DIBUtil::ScanlineSize( BitmapInfo.biWidth, 8 ); 01301 break; 01302 01303 } 01304 Problems = TRUE; 01305 break; 01306 01307 default: 01308 Problems = TRUE; 01309 break; 01310 } 01311 01312 if(Problems) 01313 { 01314 Error::SetError( _R(IDE_FORMATNOTSUPPORTED) ); 01315 return FALSE; 01316 } 01317 01318 return TRUE; 01319 } 01320 01321 /******************************************************************************************** 01322 01323 > BOOL OutputDIB::TidyUp() 01324 01325 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> 01326 Created: 4/8/94 01327 Returns: TRUE if worked, FALSE if failed (error will be set accordingly but not reported) 01328 Purpose: When everything has been done via WriteBlock, call this to update the header 01329 etc. The caller is responsible for closing the file. The class CANNOT be used 01330 for further output until StartFile is called again. 01331 Errors: Calls SetError on FALSE returns. 01332 Scope: Public 01333 01334 ********************************************************************************************/ 01335 01336 BOOL OutputDIB::TidyUp() 01337 { 01338 BOOL Result = TRUE; 01339 01340 if(OutputFile != NULL) 01341 { 01342 // Check that what we wrote was what was required in terms of number of lines 01343 // used to use BitmapInfo.biHeight but this may now be the height of a strip 01344 #ifdef _BATCHING 01345 if ( HeightWritten != HeightWanted ) 01346 { 01347 TRACEUSER( "Martin", _T("OutputDIB::TidyUp HeightReqd = %d HeightWritten = %d\n"), 01348 HeightWanted,HeightWritten); 01349 } 01350 #else //cos this goes off 01351 ERROR3IF( HeightWritten != HeightWanted, "Wrote wrong amount of bitmap to disk"); 01352 #endif 01353 01354 // could do fixups into the header here etc when using compression 01355 Result = !OutputFile->bad(); 01356 01357 OutputFile = NULL; // stop usage until StartFile time 01358 01359 // If 8, 4, 1bpp export then put back the recommended palette by destructing the 01360 // convert function. 01361 if (DoExportConvert) 01362 { 01363 delete DoExportConvert; 01364 DoExportConvert = NULL; 01365 } 01366 } 01367 01368 // Free up the bitmap info if present. 01369 // This contains the info header and palette 01370 if (lpBitmap) 01371 { 01372 CCFree(lpBitmap); 01373 lpBitmap = NULL; 01374 } 01375 01376 // Free up the output palette buffer if present 01377 if (OutputPalette) 01378 { 01379 CCFree(OutputPalette); 01380 OutputPalette = NULL; 01381 } 01382 01383 // Free up the export buffer if present 01384 if (ExportBuffer) 01385 { 01386 CCFree(ExportBuffer); 01387 ExportBuffer = NULL; 01388 } 01389 01390 return Result; 01391 }