ai_bmp.cpp

Go to the documentation of this file.
00001 // $Id: ai_bmp.cpp 1313 2006-06-13 16:55:22Z alex $
00002 // ai_bmp.cpp: implementation of the AIBitmapProcessor class.
00003 //
00005 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00006 ================================XARAHEADERSTART===========================
00007  
00008                Xara LX, a vector drawing and manipulation program.
00009                     Copyright (C) 1993-2006 Xara Group Ltd.
00010        Copyright on certain contributions may be held in joint with their
00011               respective authors. See AUTHORS file for details.
00012 
00013 LICENSE TO USE AND MODIFY SOFTWARE
00014 ----------------------------------
00015 
00016 This file is part of Xara LX.
00017 
00018 Xara LX is free software; you can redistribute it and/or modify it
00019 under the terms of the GNU General Public License version 2 as published
00020 by the Free Software Foundation.
00021 
00022 Xara LX and its component source files are distributed in the hope
00023 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00024 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00025 See the GNU General Public License for more details.
00026 
00027 You should have received a copy of the GNU General Public License along
00028 with Xara LX (see the file GPL in the root directory of the
00029 distribution); if not, write to the Free Software Foundation, Inc., 51
00030 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00031 
00032 
00033 ADDITIONAL RIGHTS
00034 -----------------
00035 
00036 Conditional upon your continuing compliance with the GNU General Public
00037 License described above, Xara Group Ltd grants to you certain additional
00038 rights. 
00039 
00040 The additional rights are to use, modify, and distribute the software
00041 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00042 library and any other such library that any version of Xara LX relased
00043 by Xara Group Ltd requires in order to compile and execute, including
00044 the static linking of that library to XaraLX. In the case of the
00045 "CDraw" library, you may satisfy obligation under the GNU General Public
00046 License to provide source code by providing a binary copy of the library
00047 concerned and a copy of the license accompanying it.
00048 
00049 Nothing in this section restricts any of the rights you have under
00050 the GNU General Public License.
00051 
00052 
00053 SCOPE OF LICENSE
00054 ----------------
00055 
00056 This license applies to this program (XaraLX) and its constituent source
00057 files only, and does not necessarily apply to other Xara products which may
00058 in part share the same code base, and are subject to their own licensing
00059 terms.
00060 
00061 This license does not apply to files in the wxXtra directory, which
00062 are built into a separate library, and are subject to the wxWindows
00063 license contained within that directory in the file "WXXTRA-LICENSE".
00064 
00065 This license does not apply to the binary libraries (if any) within
00066 the "libs" directory, which are subject to a separate license contained
00067 within that directory in the file "LIBS-LICENSE".
00068 
00069 
00070 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00071 ----------------------------------------------
00072 
00073 Subject to the terms of the GNU Public License (see above), you are
00074 free to do whatever you like with your modifications. However, you may
00075 (at your option) wish contribute them to Xara's source tree. You can
00076 find details of how to do this at:
00077   http://www.xaraxtreme.org/developers/
00078 
00079 Prior to contributing your modifications, you will need to complete our
00080 contributor agreement. This can be found at:
00081   http://www.xaraxtreme.org/developers/contribute/
00082 
00083 Please note that Xara will not accept modifications which modify any of
00084 the text between the start and end of this header (marked
00085 XARAHEADERSTART and XARAHEADEREND).
00086 
00087 
00088 MARKS
00089 -----
00090 
00091 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00092 designs are registered or unregistered trademarks, design-marks, and/or
00093 service marks of Xara Group Ltd. All rights in these marks are reserved.
00094 
00095 
00096       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00097                         http://www.xara.com/
00098 
00099 =================================XARAHEADEREND============================
00100  */
00101 
00102 #include "camtypes.h"
00103 #include "ai_bmp.h"
00104 
00105 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 #include "page.h"
00107 
00108 #include "ai5_eps.h"
00109 #include "progress.h"
00110 //#include "tim.h"
00111 
00112 #include "nodebmp.h"
00113 
00114 DECLARE_SOURCE("$Revision");
00115 
00116 #define new CAM_DEBUG_NEW
00117 
00118 
00120 // Construction/Destruction
00122 
00123 AIBitmapProcessor::AIBitmapProcessor() :
00124     mpNewBitmap(0),
00125     mLastIndex(0)
00126 {
00127 
00128 }
00129 
00130 AIBitmapProcessor::~AIBitmapProcessor()
00131 {
00132     delete mpNewBitmap;
00133     mpNewBitmap = 0;
00134 }
00135 
00136 /********************************************************************************************
00137 
00138 >   BOOL AIBitmapProcessor::BeginRaster()
00139 
00140     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00141     Created:    23/03/00
00142 
00143     Purpose:    Allows the bitmap process to intialize itself for a new bitmap
00144                 signalled by the %BeginRaster comment.
00145 
00146     Returns:    TRUE if the definition was processed, 
00147                 FALSE if not used by this filter..
00148 
00149 ********************************************************************************************/
00150 BOOL AIBitmapProcessor::BeginRaster()
00151 {
00152     ENSURE(mpNewBitmap == NULL, "mpNewBitmap is not NULL");
00153 
00154     return TRUE;
00155 }
00156 
00157 
00158 /********************************************************************************************
00159 
00160 >   BOOL AIBitmapProcessor::DecodeXI( AI5EPSFilter& filter )
00161 
00162     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00163     Created:    23/03/00
00164     Returns:    TRUE if the definition was processed, 
00165                 FALSE if not used by this filter..
00166     Purpose:    Decodes the EPS XI, bitmap definition in an Illustrator 5 file
00167 
00168     The format of the operator is:
00169 
00170     [ a b c d tx ty ] llx lly urx ury h w bits ImageType AlphaChannelCount reserved bin-ascii ImageMask XI
00171 
00172 ********************************************************************************************/
00173 BOOL AIBitmapProcessor::DecodeXI( AI5EPSFilter& filter )
00174 {
00175     // Graeme (18/4/00) - This code isn't very pretty, but it's necessary because of the way
00176     // in which the bitmap is stored. If I try a GetCoordPair () to get the bitmap positions,
00177     // the image will be misrendered because the transformation should take place due to the
00178     // tx and ty components of the matrix. Note also that the bitmap's position in Adobe
00179     // Illustrator is taken from the top left corner, whilst we use the bottom left.
00180 
00182     // Get the page origin.
00184 
00185     // Graeme (18/4/00) - Declare variables to get the origin of the page within Camelot's
00186     // co-ordinate space.
00187     Document    *pDocument  = filter.GetDocument ();
00188     Spread      *pSpread    = pDocument->FindFirstSpread ();
00189     Page        *pPage      = pSpread->FindFirstPageInSpread ();
00190     DocCoord    Origin      = pPage->GetPageRect ().lo;
00191 
00193     // decode the bitmap parameters
00195 
00196     Matrix ImageMatrix;
00197     DocCoord Translation;
00198 
00199     INT32 h, w, bits, ImageType, AlphaChannelCount, reserved, bin_ascii, ImageMask;
00200     INT32 llx, lly, urx, ury;
00201 
00202     INT32 nLength = 0;
00203     INT32 nLineLength = 0;
00204     INT32 nMaxLineOffset = 0;
00205 
00206     INT32 nChannels = 0;
00207 
00208     NodeBitmap* pNodeBitmap = NULL;
00209     DocCoord p;
00210 
00211     // Graeme (18/4/00) - I've replaced the Pop with PopCoordPair for extracting the
00212     // bounding co-ordinates of the bitmap. This means that they will be scaled up
00213     // into the Xara co-ordinate space. I've also reversed the popping of h and w
00214     // from the stack - their order is incorrect in the AI documentation.
00215     if (    !filter.GetStack().Pop(&ImageMask)    || 
00216             !filter.GetStack().Pop(&bin_ascii) || 
00217             !filter.GetStack().Pop(&reserved) || 
00218             !filter.GetStack().Pop(&AlphaChannelCount) || 
00219             !filter.GetStack().Pop(&ImageType) || 
00220             !filter.GetStack().Pop(&bits) || 
00221             !filter.GetStack().Pop(&h) || 
00222             !filter.GetStack().Pop(&w) || 
00223             !filter.GetStack().PopCoord(&ury) || 
00224             !filter.GetStack().PopCoord(&urx) || 
00225             !filter.GetStack().PopCoord(&lly) || 
00226             !filter.GetStack().PopCoord(&llx) || 
00227             !filter.GetStack().Pop( &ImageMatrix, TRUE )
00228         )
00229         goto EPSError;
00230 
00232     // create space for the tentative bitmap
00234 
00236     //  ImageType gives the number of channels per pixel
00237     //  bits is the bits per channel
00238     //  However we will convert CMYK bitmaps to RGB
00240 
00241     switch ( ImageType )
00242     {
00243         case 1: // greyscale
00244             nChannels = 1;
00245             break;
00246         case 3: // rgb
00247             nChannels = 3;
00248             break;
00249         case 4: // CMYK
00250             nChannels = 3;
00251             break;
00252         default: // unknown
00253             goto EPSError;
00254     }
00255 
00256     mpNewBitmap = new KernelBitmap( w, h, bits * nChannels, 96 );
00257     if ( !mpNewBitmap )
00258         goto EPSError;
00259 
00261     //  We can import greyscale bitmaps as well
00263 
00264     if ( ImageType == 1 )
00265         mpNewBitmap->SetAsGreyscale();
00266 
00267 
00269     // get the binary data
00271 
00272     nLength = mpNewBitmap->GetActualBitmap()->GetBitmapSize();
00273     nLineLength = mpNewBitmap->GetActualBitmap()->GetScanlineSize();
00274     nMaxLineOffset = (( w * mpNewBitmap->GetActualBitmap()->GetBPP() ) / 8) - 1;
00275 
00276     if ( !ReadImageData( filter, ImageType, mpNewBitmap->GetBitmapBits(), nLength, nLineLength, nMaxLineOffset ) )
00277         goto EPSError;
00278 
00280     //  insert the image into the document
00282 
00283     // Get a new NodeBitmap object to import into. Don't know what the 12,12 bit does
00284     pNodeBitmap = new NodeBitmap;
00285 
00286     if ( !pNodeBitmap || !pNodeBitmap->SetUpPath(12,12) )
00287         goto EPSError;
00288 
00289     pNodeBitmap->GetBitmapRef()->Attach( mpNewBitmap, filter.GetDocument() );
00290 
00292     //  set up the bounds of the shape containing the bitmap
00294 
00295     // Graeme (18/4/00) - Adjust the values of lly and ury before they're transformed.
00296     lly -= h * EPSScaleFactor;
00297     ury -= h * EPSScaleFactor;
00298 
00299     // Graeme (18/4/00) - Modify the matrix to place the bitmap in the correct place.
00300     ImageMatrix.GetTranslation ( Translation );     // Extract the translation component.
00301     Translation += Origin;                          // Add the page origin to it.
00302     ImageMatrix.SetTranslation ( Translation );     // And reset the value in the matrix.
00303 
00304     // Graeme (17/4/00) - Colin overlooked setting up the bounding parallelogram when he
00305     // wrote this code, and I've just added this.
00306     p.x = llx;
00307     p.y = ury;
00308     ImageMatrix.transform( &p );
00309     pNodeBitmap->InkPath.InsertMoveTo( p );
00310     pNodeBitmap->Parallel [0] = p;
00311 
00312     p.x = urx;
00313     p.y = ury;
00314     ImageMatrix.transform( &p );
00315     pNodeBitmap->InkPath.InsertLineTo( p );
00316     pNodeBitmap->Parallel [1] = p;
00317 
00318     p.x = urx;
00319     p.y = lly;
00320     ImageMatrix.transform( &p );
00321     pNodeBitmap->InkPath.InsertLineTo( p );
00322     pNodeBitmap->Parallel [2] = p;
00323 
00324     p.x = llx;
00325     p.y = lly;
00326     ImageMatrix.transform( &p );
00327     pNodeBitmap->InkPath.InsertLineTo( p );
00328     pNodeBitmap->Parallel [3] = p;
00329 
00330     p.x = llx;
00331     p.y = ury;
00332     ImageMatrix.transform( &p );
00333     pNodeBitmap->InkPath.InsertLineTo( p );
00334 
00335     pNodeBitmap->InkPath.CloseSubPath();
00336 
00337     // Graeme (18/4/00) - It is necessary to set the default attributes up for a
00338     // new node bitmap before inserting it into the tree. Otherwise it's rendered
00339     // as a greyscale image, even if it is colour, because there's a start colour
00340     // value set.
00341     pNodeBitmap->ApplyDefaultBitmapAttrs ( NULL );
00342 
00343     filter.AddNewNode( pNodeBitmap );
00344 
00345     return TRUE;
00346 
00347 EPSError:
00348     if ( mpNewBitmap )
00349     {
00350         delete mpNewBitmap;
00351         mpNewBitmap = 0;
00352     }
00353 
00354     return FALSE;
00355 }
00356 
00357 /********************************************************************************************
00358 
00359 >   BOOL AIBitmapProcessor::EndRaster()
00360 
00361     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00362     Created:    23/03/00
00363 
00364     Purpose:    Allows the bitmap processor to complete the bitmap
00365                 signalled by the %EndRaster comment.
00366 
00367     Returns:    TRUE if the definition was processed, 
00368                 FALSE if not used by this filter..
00369 
00370 ********************************************************************************************/
00371 BOOL AIBitmapProcessor::EndRaster()
00372 {
00373     ENSURE(mpNewBitmap != NULL, "mpNewBitmap is NULL");
00374 
00376     // add bitmap to tentative bitmap list, giving an index number
00378 
00379     mBitmaps.AddBitmap( mpNewBitmap, mLastIndex );
00380 
00381     // up the index number
00382     ++mLastIndex;
00383 
00384     // We're done with this bitmap.
00385     mpNewBitmap     = NULL;
00386 
00387     return TRUE;
00388 }
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00397 
00398 /********************************************************************************************
00399 
00400 >   BOOL AIBitmapProcessor::ReadImageData( AI5EPSFilter* const pFilter, const INT32 ImageType, ADDR pData, INT32 nLength ) const
00401 
00402     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00403     Created:    23/03/00
00404     Returns:    TRUE if the image was read correctly
00405                 FALSE if the data length differed from the expected given in nLength
00406     in,out:     pData:      A pointer to an allocated block of memory to hold the decoded
00407                             hexadecimal data.
00408     in:         nLength:    The expected number of bytes decoded from the stream
00409                 ImageType:  The AI ImageType given in the XI definition
00410 
00411     Purpose:    Decodes the hex string style data following an image (XI) operator
00412                 placing it in the given buffer. This allows the bitmap data to be read into
00413                 a bitmap.
00414 
00415                 Each line begins %XXXX where XXXX are hex numbers.
00416 
00417                 Assumes that the first % token has not yet been read.
00418 
00419 ********************************************************************************************/
00420 BOOL AIBitmapProcessor::ReadImageData( AI5EPSFilter& filter, const INT32 ImageType, ADDR pDataStart, INT32 nLength, INT32 nLineLength, INT32 nMaxLineOffset )
00421 {
00423     // ignore the whitespace (EOL)
00425 
00426     filter.GetEPSFile()->GetToken();
00427 
00429     // read the first % line
00431     filter.GetEPSFile()->GetToken();
00432 
00434     //  We need some running values
00436     BYTE ColourVal[4] = {0,0,0,0};
00437     UINT32 nShift = 0;              // which colour component is being read
00438 
00440     //  start with last line
00442 
00443     ADDR pCurrentLine = pDataStart + nLength - nLineLength;
00444     INT32 nLineOffset = 0;
00445 
00446     while ( pCurrentLine >= pDataStart && !filter.GetEPSFile()->eof() )
00447     {
00448         // the data ends with a comment
00449         if ( camStrncmp( filter.GetTokenBuf(), _T("%%EndData"), 9 ) == 0 )
00450             break;
00451 
00453         // update progress
00455         const INT32 nCharsRead = filter.GetEPSFile()->GetCharsRead();
00456         if ( nCharsRead > (filter.GetLastProgressUpdate() + 2048) )
00457         {
00458             if ( !ContinueSlowJob( nCharsRead ) )
00459             {
00460                 // Abort operation - make sure nodes are deleted and not added to the tree.
00461                 ERROR(_R(IDT_IMPORT_USERABORT), FALSE);
00462             }
00463             else
00464             {
00465                 filter.GetLastProgressUpdate() = nCharsRead;
00466             }
00467         }
00468 
00470         // Decode the token into hex data (starting after the %)
00472 
00473         INT32 nBytes = 0;
00474 
00475         switch ( ImageType )
00476         {
00477             case 1: // greyscale
00478                 nBytes = filter.DecodeHexString( pCurrentLine, nLength, 1 );
00479                 break;
00480 
00481             case 3: // rgb
00482                 nBytes = DecodeHexStringAsRGB( filter, pCurrentLine, nLineOffset, nLineLength, nMaxLineOffset, 1, ColourVal, nShift );
00483                 break;
00484 
00485             case 4: // CMYK
00486                 nBytes = DecodeHexStringAsCMYK( filter, pCurrentLine, nLineOffset, nLineLength, nMaxLineOffset, 1, ColourVal, nShift );
00487                 break;
00488         }
00489 
00490         if ( nBytes == -1 )
00491         {
00492             // Error
00493             TRACE( _T("Error in AI5 image data\n") );
00494             break;
00495         }
00496 
00498         //  get the next token
00500         filter.GetEPSFile()->GetToken();
00501     }
00502 
00503     return ( pDataStart - pCurrentLine  == nLineLength ) ? TRUE : FALSE;
00504 }
00505 
00506 
00507 /********************************************************************************************
00508 
00509 >   bool inline CharToHex( const char& cDigit, BYTE& lNum )
00510 
00511     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00512     Created:    23/03/00
00513 
00514     Purpose:    Converts a hex character to a numeric byte.
00515 
00516     Inputs:     cDigit - the hex character (0-9,A-F)
00517     Outputs:    nNum    the original value with the hex character ORred into it
00518 
00519     Returns:    true if the character were valid
00520                 false otherwise
00521 
00522 ********************************************************************************************/
00523 bool inline CharToHex( const char& cDigit, BYTE& nNum )
00524 {
00525     char ch = camToupper(cDigit);
00526 
00527     if ( (ch >= '0') && (ch <= '9') )
00528     {
00529         nNum |= (BYTE) (ch - '0');
00530     }
00531     else if ((ch >= 'A') && (ch <= 'F'))
00532     {
00533         nNum |= (BYTE) (ch - 'A') + 10;
00534     }
00535     else
00536     {
00537         // Error in hex data
00538         return false;
00539     }
00540     return true;
00541 }
00542 
00543 /********************************************************************************************
00544 
00545 >   BYTE ColourValueToByte(const double& Value)
00546 
00547     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00548     Created:    23/03/00
00549 
00550 
00551     Inputs:     Value   - The colour value, as a double.
00552     Returns:    BYTE    - The colour value, as a byte.
00553 
00554     Purpose:    Converts a colour value from a double to a BYTE.
00555 
00556 ********************************************************************************************/
00557 
00558 BYTE ColourValueToByte(const double& Value)
00559 {
00560     return BYTE(floor(Value * double(255) + 0.5));
00561 }
00562 
00563 /********************************************************************************************
00564 
00565 >   INT32 AIBitmapProcessor::DecodeHexStringAsCMYK( AI5EPSFilter& filter, ADDR& pCurrentLine, 
00566         INT32& nLineOffset, INT32 nLineLength, INT32 nMaxLineOffset, UINT32 nStart, BYTE CMYKval[], UINT32& nShift )
00567 
00568     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00569     Created:    23/03/00
00570 
00571     Purpose:    Treat the current token as a hex string, and decode it into a BGR bitmap.
00572 
00573     Inputs:     filter          the filter doing the import
00574                 nLineLength     the maximum number of bytes to read from the hex string.
00575                 nMaxLineOffset  the width of the bitmap - 1
00576                 nStart          where in TokenBuf (the member that contains the semantic value of
00577                                 the token) to start the decoding
00578 
00579     in,out:     pCurrentLine    the line in the bitmap to place the binary data into
00580                 nLineOffset     the offset into the current line that will be read next
00581                 CMYKval         the accumulated CMYK value
00582                 nShift          the index into CMYKVal giving the next value to read
00583 
00584     Returns:    If an error occurs (i.e. invalid hex data) then -1 is returned.
00585 
00586                 This is way too complicated but I copied the code from the base class and
00587                 worked from there.
00588                 How about read the bitmap line by line getting an RGB value from the appropriate
00589                 "BitmapParser", say.
00590 
00591 ********************************************************************************************/
00592 INT32 AIBitmapProcessor::DecodeHexStringAsCMYK( AI5EPSFilter& filter, ADDR& pCurrentLine, INT32& nLineOffset, INT32 nLineLength, INT32 nMaxLineOffset, UINT32 nStart, BYTE CMYKval[], UINT32& nShift )
00593 {
00594     UINT32 nTokenLen = camStrlen(filter.GetTokenBuf() + nStart);
00595 
00596     // Assume hex strings are even-numbered in length for the moment
00597     if ( (nTokenLen & 1) != 0 )
00598     {
00599         TRACE( _T("Bad hex string length in DecodeHexString\n") );
00600         return -1;
00601     }
00602 
00604     // Decode the string two characters at a time keeping a running CMYK value
00606 
00607     double dRed, dGreen, dBlue;
00608     double dKey;
00609 
00610     UINT32 i;
00611     for ( i = nStart; i < nTokenLen; i += 2 )
00612     {
00614         //  read in the CMYK value one component at at time
00615         //  first clear the next value
00617         CMYKval[nShift] = 0;
00618 
00619         if ( !CharToHex( filter.GetTokenBuf()[i], CMYKval[nShift] ) )
00620             return -1;
00621 
00622         CMYKval[nShift] <<= 4;
00623 
00624         if ( !CharToHex( filter.GetTokenBuf()[i + 1], CMYKval[nShift] ) )
00625             return -1;
00626 
00627         ++nShift;
00628 
00630         //  once we have a complete CMYK value, stick it in the bitmap
00632         if ( nShift > 3 )
00633         {
00635             // Convert the colour into an RGB format.
00637 
00638             dKey    = double(CMYKval[3]) / 255.0;
00639 
00640             dRed    = 1.0 - (min(1.0, (double(CMYKval[0]) / 255.0 + dKey )));
00641             dGreen  = 1.0 - (min(1.0, (double(CMYKval[1]) / 255.0 + dKey )));
00642             dBlue   = 1.0 - (min(1.0, (double(CMYKval[2]) / 255.0 + dKey )));
00643 
00645             // Set the value for the current pixel in the bitmap.
00647 
00648             pCurrentLine[nLineOffset++] = ColourValueToByte( dBlue );
00649             pCurrentLine[nLineOffset++] = ColourValueToByte( dGreen );
00650             pCurrentLine[nLineOffset++] = ColourValueToByte( dRed );
00651 
00652             if ( nLineOffset > nMaxLineOffset )
00653             {
00654                 pCurrentLine -= nLineLength;
00655                 nLineOffset = 0;
00656             }
00657 
00659             // start the next CMYK value
00661 
00662             nShift = 0;
00663         }
00664     }
00665 
00666     // How much data did we read?
00667     return i;
00668 }
00669 
00670 
00671 /********************************************************************************************
00672 
00673 >   INT32 AIBitmapProcessor::DecodeHexStringAsRGB( AI5EPSFilter& filter, ADDR& pCurrentLine, 
00674             INT32& nLineOffset, INT32 nLineLength, INT32 nMaxLineOffset, UINT32 nStart, BYTE RGBVal[], UINT32& nShift )
00675 
00676     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00677     Created:    23/03/00
00678 
00679     Purpose:    Treat the current token as a hex string, and decode it into a BGR bitmap.
00680 
00681     Inputs:     filter          the filter doing the import
00682                 nLineLength     the maximum number of bytes to read from the hex string.
00683                 nMaxLineOffset  the width of the bitmap - 1
00684                 nStart          where in TokenBuf (the member that contains the semantic value of
00685                                 the token) to start the decoding
00686 
00687     in,out:     pCurrentLine    the line in the bitmap to place the binary data into
00688                 nLineOffset     the offset into the current line that will be read next
00689                 RGBVal          the accumulated RGB value
00690                 nShift          the index into RGBVal giving the next value to read
00691 
00692     Returns:    If an error occurs (i.e. invalid hex data) then -1 is returned.
00693 
00694                 This is way too complicated but I copied the code from the base class and
00695                 worked from there.
00696                 How about read the bitmap line by line getting an RGB value from the appropriate
00697                 "BitmapParser", say.
00698 
00699 ********************************************************************************************/
00700 INT32 AIBitmapProcessor::DecodeHexStringAsRGB( AI5EPSFilter& filter, ADDR& pCurrentLine, INT32& nLineOffset, INT32 nLineLength, INT32 nMaxLineOffset, UINT32 nStart, BYTE RGBVal[], UINT32& nShift )
00701 {
00702     UINT32 nTokenLen = camStrlen(filter.GetTokenBuf() + nStart);
00703 
00704     // Assume hex strings are even-numbered in length for the moment
00705     if ( (nTokenLen & 1) != 0 )
00706     {
00707         TRACE( _T("Bad hex string length in DecodeHexString\n") );
00708         return -1;
00709     }
00710 
00712     // Decode the string two characters at a time 
00714 
00715     UINT32 i;
00716     for ( i = nStart; i < nTokenLen; i += 2 )
00717     {
00718         RGBVal[nShift] = 0;
00719 
00720         if ( !CharToHex( filter.GetTokenBuf()[i], RGBVal[nShift] ) )
00721             return -1;
00722 
00723         RGBVal[nShift] <<= 4;
00724             
00725         if ( !CharToHex( filter.GetTokenBuf()[i + 1], RGBVal[nShift] ) )
00726             return -1;
00727 
00728         ++nShift;
00729 
00731         //  once we have a complete RGB value, stick it in the bitmap
00732         //  reversing it to BGR
00734 
00735         if ( nShift > 2 )
00736         {
00737             pCurrentLine[nLineOffset++] = RGBVal[2];
00738             pCurrentLine[nLineOffset++] = RGBVal[1];
00739             pCurrentLine[nLineOffset++] = RGBVal[0];
00740 
00741             if ( nLineOffset > nMaxLineOffset )
00742             {
00743                 pCurrentLine -= nLineLength;
00744                 nLineOffset = 0;
00745             }
00746 
00747             nShift = 0;
00748         }
00749     }
00750 
00751     // How much data did we read?
00752     return i;
00753 }

Generated on Sat Nov 10 03:44:08 2007 for Camelot by  doxygen 1.4.4