AIBitmapProcessor Class Reference

Helps with the import of Adobe Illustrator 8.0 files. (at the time of writing only the version 7.0 documentation was available so some omissions are inevitable). It creates a list of bitmaps from the input stream. More...

#include <ai_bmp.h>

List of all members.

Public Member Functions

 AIBitmapProcessor ()
virtual ~AIBitmapProcessor ()
BOOL BeginRaster ()
 Allows the bitmap process to intialize itself for a new bitmap signalled by the BeginRaster comment.
BOOL DecodeXI (AI5EPSFilter &filter)
 Decodes the EPS XI, bitmap definition in an Illustrator 5 file.
BOOL EndRaster ()
 Allows the bitmap processor to complete the bitmap signalled by the EndRaster comment.

Protected Member Functions

BOOL ReadImageData (AI5EPSFilter &filter, const INT32 ImageType, ADDR pDataStart, INT32 nLength, INT32 nLineLength, INT32 nMaxLineOffset)
 Decodes the hex string style data following an image (XI) operator placing it in the given buffer. This allows the bitmap data to be read into a bitmap.
INT32 DecodeHexStringAsCMYK (AI5EPSFilter &filter, ADDR &pCurrentLine, INT32 &nLineOffset, INT32 nLineLength, INT32 nMaxLineOffset, UINT32 nStart, BYTE CMYKval[], UINT32 &nShift)
 Treat the current token as a hex string, and decode it into a BGR bitmap.
INT32 DecodeHexStringAsRGB (AI5EPSFilter &filter, ADDR &pCurrentLine, INT32 &nLineOffset, INT32 nLineLength, INT32 nMaxLineOffset, UINT32 nStart, BYTE RGBval[], UINT32 &nShift)
 Treat the current token as a hex string, and decode it into a BGR bitmap.

Private Attributes

KernelBitmapmpNewBitmap
ImportedBitmaps mBitmaps
INT32 mLastIndex


Detailed Description

Helps with the import of Adobe Illustrator 8.0 files. (at the time of writing only the version 7.0 documentation was available so some omissions are inevitable). It creates a list of bitmaps from the input stream.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/03/00

Definition at line 124 of file ai_bmp.h.


Constructor & Destructor Documentation

AIBitmapProcessor::AIBitmapProcessor  ) 
 

Definition at line 123 of file ai_bmp.cpp.

00123                                      :
00124     mpNewBitmap(0),
00125     mLastIndex(0)
00126 {
00127 
00128 }

AIBitmapProcessor::~AIBitmapProcessor  )  [virtual]
 

Definition at line 130 of file ai_bmp.cpp.

00131 {
00132     delete mpNewBitmap;
00133     mpNewBitmap = 0;
00134 }


Member Function Documentation

BOOL AIBitmapProcessor::BeginRaster  ) 
 

Allows the bitmap process to intialize itself for a new bitmap signalled by the BeginRaster comment.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..

Definition at line 150 of file ai_bmp.cpp.

00151 {
00152     ENSURE(mpNewBitmap == NULL, "mpNewBitmap is not NULL");
00153 
00154     return TRUE;
00155 }

INT32 AIBitmapProcessor::DecodeHexStringAsCMYK AI5EPSFilter filter,
ADDR pCurrentLine,
INT32 &  nLineOffset,
INT32  nLineLength,
INT32  nMaxLineOffset,
UINT32  nStart,
BYTE  CMYKval[],
UINT32 nShift
[protected]
 

Treat the current token as a hex string, and decode it into a BGR bitmap.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Parameters:
filter the filter doing the import [INPUTS] nLineLength the maximum number of bytes to read from the hex string. nMaxLineOffset the width of the bitmap - 1 nStart where in TokenBuf (the member that contains the semantic value of the token) to start the decoding
in,out: pCurrentLine the line in the bitmap to place the binary data into nLineOffset the offset into the current line that will be read next CMYKval the accumulated CMYK value nShift the index into CMYKVal giving the next value to read

Returns:
If an error occurs (i.e. invalid hex data) then -1 is returned.
This is way too complicated but I copied the code from the base class and worked from there. How about read the bitmap line by line getting an RGB value from the appropriate "BitmapParser", say.

Definition at line 592 of file ai_bmp.cpp.

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 }

INT32 AIBitmapProcessor::DecodeHexStringAsRGB AI5EPSFilter filter,
ADDR pCurrentLine,
INT32 &  nLineOffset,
INT32  nLineLength,
INT32  nMaxLineOffset,
UINT32  nStart,
BYTE  RGBVal[],
UINT32 nShift
[protected]
 

Treat the current token as a hex string, and decode it into a BGR bitmap.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Parameters:
filter the filter doing the import [INPUTS] nLineLength the maximum number of bytes to read from the hex string. nMaxLineOffset the width of the bitmap - 1 nStart where in TokenBuf (the member that contains the semantic value of the token) to start the decoding
in,out: pCurrentLine the line in the bitmap to place the binary data into nLineOffset the offset into the current line that will be read next RGBVal the accumulated RGB value nShift the index into RGBVal giving the next value to read

Returns:
If an error occurs (i.e. invalid hex data) then -1 is returned.
This is way too complicated but I copied the code from the base class and worked from there. How about read the bitmap line by line getting an RGB value from the appropriate "BitmapParser", say.

Definition at line 700 of file ai_bmp.cpp.

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 }

BOOL AIBitmapProcessor::DecodeXI AI5EPSFilter filter  ) 
 

Decodes the EPS XI, bitmap definition in an Illustrator 5 file.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..
The format of the operator is:

[ a b c d tx ty ] llx lly urx ury h w bits ImageType AlphaChannelCount reserved bin-ascii ImageMask XI

Definition at line 173 of file ai_bmp.cpp.

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 }

BOOL AIBitmapProcessor::EndRaster  ) 
 

Allows the bitmap processor to complete the bitmap signalled by the EndRaster comment.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..

Definition at line 371 of file ai_bmp.cpp.

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 }

BOOL AIBitmapProcessor::ReadImageData AI5EPSFilter filter,
const INT32  ImageType,
ADDR  pDataStart,
INT32  nLength,
INT32  nLineLength,
INT32  nMaxLineOffset
[protected]
 

Decodes the hex string style data following an image (XI) operator placing it in the given buffer. This allows the bitmap data to be read into a bitmap.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the image was read correctly FALSE if the data length differed from the expected given in nLength in,out: pData: A pointer to an allocated block of memory to hold the decoded hexadecimal data. in: nLength: The expected number of bytes decoded from the stream ImageType: The AI ImageType given in the XI definition
Each line begins XXXX where XXXX are hex numbers.

Assumes that the first % token has not yet been read.

Definition at line 420 of file ai_bmp.cpp.

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 }


Member Data Documentation

ImportedBitmaps AIBitmapProcessor::mBitmaps [private]
 

Definition at line 142 of file ai_bmp.h.

INT32 AIBitmapProcessor::mLastIndex [private]
 

Definition at line 143 of file ai_bmp.h.

KernelBitmap* AIBitmapProcessor::mpNewBitmap [private]
 

Definition at line 141 of file ai_bmp.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:49:53 2007 for Camelot by  doxygen 1.4.4