com.twelvemonkeys.imageio.plugins.pict.plpictdec.cpp Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of imageio-pict Show documentation
Show all versions of imageio-pict Show documentation
ImageIO plugin for Apple Mac Paint Picture (PICT) format.
The newest version!
/*
http://www.koders.com/cpp/fidEBFA7988680615CF80EF7DA28116F3E423B56E7A.aspx
http://www.paintlib.de/paintlib/copyright.html
/--------------------------------------------------------------------
|
| $Id: plpictdec.cpp,v 1.14 2004/10/02 22:23:12 uzadow Exp $
| Macintosh pict Decoder Class
|
| This class decodes macintosh PICT files with 1,2,4,8,16 and 32
| bits per pixel as well as PICT/JPEG. If an alpha channel is
| present in a 32-bit-PICT, it is decoded as well.
| The PICT format is a general picture file format and can
| contain a lot of other elements besides bitmaps. These elements
| are ignored.
|
| Copyright (c) 1996-2002 Ulrich von Zadow
|
\--------------------------------------------------------------------
*/
#include "config.h"
#include "plpictdec.h"
#ifdef PL_SUPPORT_JPEG
#include "pljpegdec.h"
#endif
#include "ploptable.h"
#include "plexcept.h"
#include
PLPictDecoder::PLPictDecoder
( PLJPEGDecoder * pJPEGDecoder
)
: PLPicDecoder(),
m_pJPEGDecoder (pJPEGDecoder)
// Creates a decoder
{
}
PLPictDecoder::~PLPictDecoder
()
{
}
void PLPictDecoder::Open (PLDataSource * pDataSrc)
{
Trace (2, "Decoding mac pict.\n");
// Skip empty 512 byte header.
pDataSrc->Skip (512);
// Read PICT header
int Version;
readHeader (pDataSrc, Version);
interpretOpcodes (pDataSrc, Version);
}
//! Fills the bitmap with the image.
void PLPictDecoder::GetImage (PLBmpBase & Bmp)
{
switch (m_PictType)
{
case op9a:
DecodeOp9a (&Bmp, m_pDataSrc);
break;
case jpeg:
DecodeJPEG (&Bmp, m_pDataSrc);
break;
case pixmap:
DecodePixmap (&Bmp, m_pDataSrc);
break;
case bitmap:
DecodeBitmap (&Bmp, m_pDataSrc);
break;
default:
PLASSERT (false);
}
m_PictType = none;
}
void PLPictDecoder::readHeader
( PLDataSource * pDataSrc,
int& Version
)
// Decodes header and version information.
// Performs checks to make sure the data is really a pict file.
{
PLBYTE ch;
PLWORD PicSize; // Version 1 picture size. Ignored in version 2.
char sz[256];
MacRect Frame;
PicSize = ReadMWord (pDataSrc);
readRect (&Frame, pDataSrc);
while ((ch = ReadByte(pDataSrc)) == 0);
if (ch != 0x11)
raiseError (PL_ERRWRONG_SIGNATURE,
"Error decoding pict: Version number missing.");
switch (ReadByte(pDataSrc))
{
case 1:
Version = 1;
break;
case 2:
if (ReadByte(pDataSrc) != 0xff)
raiseError (PL_ERRWRONG_SIGNATURE,
"Illegal version number.");
Version = 2;
break;
default:
raiseError (PL_ERRWRONG_SIGNATURE,
"Illegal version number.");
}
sprintf (sz, "PICT version %d found.\n", Version);
Trace (2, sz);
}
void PLPictDecoder::interpretOpcodes
( PLDataSource * pDataSrc,
int& Version
)
// This is the main decoder loop. The functions reads opcodes,
// skips some, and hands the rest to opcode-specific functions.
// It stops decoding after the first opcode containing bitmapped
// data.
{
PLWORD Opcode;
char sz[256];
bool bDone = false;
while (!bDone)
{
Opcode = readOpcode(Version, pDataSrc);
if (Opcode == 0xFF || Opcode == 0xFFFF)
{
bDone = true;
Trace (2, "Opcode: End of pict.\n");
raiseError (PL_ERRFORMAT_NOT_SUPPORTED,
"PICT contained only vector data!\n");
}
else if (Opcode < 0xa2)
{
if (!strcmp(optable[Opcode].name, "reserved"))
sprintf (sz, "Opcode: reserved=0x%x\n", Opcode);
else
sprintf (sz, "Opcode: %s\n", optable[Opcode].name);
Trace (2, sz);
switch (Opcode)
{
case 0x01: // Clip
clip (pDataSrc);
break;
case 0x12:
case 0x13:
case 0x14:
pixPat (pDataSrc);
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
skipPolyOrRegion (pDataSrc);
break;
case 0x90:
case 0x98:
bitsRect (pDataSrc);
bDone = true;
break;
case 0x91:
case 0x99:
bitsRegion (pDataSrc);
bDone = true;
break;
case 0x9a:
opcode9a (pDataSrc);
bDone = true;
break;
case 0xa1:
longComment (pDataSrc);
break;
default:
// No function => skip to next Opcode
if (optable[Opcode].len == WORD_LEN)
pDataSrc->Skip(ReadMWord(pDataSrc));
else
pDataSrc->Skip(optable[Opcode].len);
}
}
else if (Opcode == 0xc00)
{
Trace (2, "Opcode: Header.\n");
headerOp (pDataSrc);
}
else if (Opcode == 0x8200)
{
Trace (2, "Opcode: JPEG.\n");
jpegOp (pDataSrc);
bDone = true;
}
else if (Opcode >= 0xa2 && Opcode <= 0xaf)
{
sprintf (sz, "Opcode: reserved 0x%x.\n", Opcode);
Trace (2, sz);
pDataSrc->Skip(ReadMWord(pDataSrc));
}
else if ((Opcode >= 0xb0 && Opcode <= 0xcf) ||
(Opcode >= 0x8000 && Opcode <= 0x80ff))
{
// just a reserved Opcode, no data
sprintf (sz, "Opcode: reserved 0x%x.\n", Opcode);
Trace (2, sz);
}
else if ((Opcode >= 0xd0 && Opcode <= 0xfe) ||
Opcode >= 8100)
{
sprintf (sz, "Opcode: reserved 0x%x.\n", Opcode);
Trace (2, sz);
pDataSrc->Skip(ReadMLong(pDataSrc));
}
else if (Opcode >= 0x100 && Opcode <= 0x7fff)
{
sprintf (sz, "Opcode: reserved 0x%x.\n", Opcode);
Trace (2, sz);
pDataSrc->Skip((Opcode >> 7) & 255);
}
else
{
char sz[256];
sprintf (sz, "Can't handle Opcode %x.\n", Opcode);
raiseError (PL_ERRFORMAT_UNKNOWN, sz);
}
}
}
PLWORD PLPictDecoder::readOpcode
( int Version,
PLDataSource * pDataSrc
)
// moves to an even byte position in the file and returns the
// opcode found.
{
if (Version == 2)
pDataSrc->AlignToWord();
if (Version == 1)
return ReadByte (pDataSrc);
else
return ReadMWord (pDataSrc);
}
/////////////////////////////////////////////////////////////////////
// Opcode functions
void PLPictDecoder::clip
( PLDataSource * pDataSrc
)
// skips clipping rectangle or region.
{
MacRect ClipRect;
PLWORD len = ReadMWord(pDataSrc);
if (len == 0x000a)
{ /* null rgn */
readRect(&ClipRect, pDataSrc);
}
else
pDataSrc->Skip(len - 2);
}
void PLPictDecoder::pixPat
( PLDataSource * pDataSrc
)
// skips pattern definition.
{
PLWORD PatType;
PLWORD rowBytes;
MacpixMap p;
PLWORD NumColors;
PatType = ReadMWord(pDataSrc);
switch (PatType)
{
case 2:
pDataSrc->Skip(8);
pDataSrc->Skip(5);
break;
case 1:
{
pDataSrc->Skip(8);
rowBytes = ReadMWord(pDataSrc);
readRect(&p.Bounds, pDataSrc);
readPixmap(&p, pDataSrc);
PLPixel32 CT[256];
readColourTable(&NumColors, pDataSrc, CT);
skipBits(&p.Bounds, rowBytes, p.pixelSize, pDataSrc);
}
break;
default:
raiseError (PL_ERRFORMAT_UNKNOWN,
"Unknown pattern type in pixPat.");
}
}
void PLPictDecoder::skipPolyOrRegion
( PLDataSource * pDataSrc
)
{
Trace (3, "Skipping polygon or region.\n");
pDataSrc->Skip (ReadMWord (pDataSrc) - 2);
}
void PLPictDecoder::bitsRect
( PLDataSource * pDataSrc
)
// Bitmap/pixmap data clipped by a rectangle.
{
m_rowBytes = ReadMWord(pDataSrc); // Bytes per row in source when
// uncompressed.
m_bIsRegion = false;
if (m_rowBytes & 0x8000)
doPixmap (pDataSrc);
else
doBitmap (pDataSrc);
}
void PLPictDecoder::bitsRegion
( PLDataSource * pDataSrc
)
// Bitmap/pixmap data clipped by a region.
{
m_rowBytes = ReadMWord(pDataSrc); // Bytes per row in source when
// uncompressed.
m_bIsRegion = true;
if (m_rowBytes & 0x8000)
doPixmap (pDataSrc);
else
doBitmap (pDataSrc);
}
void PLPictDecoder::opcode9a
( PLDataSource * pDataSrc
)
// DirectBitsRect.
{
pDataSrc->Skip(4); // Skip fake len and fake EOF.
ReadMWord(pDataSrc); // bogus row bytes.
// Read in the PixMap fields.
readRect(&m_PixMap.Bounds, pDataSrc);
readPixmap (&m_PixMap, pDataSrc);
// Ignore source & destination rectangle as well as transfer mode.
MacRect TempRect;
readRect (&TempRect, pDataSrc);
readRect (&TempRect, pDataSrc);
PLWORD mode = ReadMWord(pDataSrc);
// Create empty DIB
setBmpInfo (m_PixMap);
m_PictType=op9a;
}
void PLPictDecoder::DecodeOp9a
( PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
{
// Do the actual unpacking.
switch (m_PixMap.pixelSize)
{
case 32:
unpack32bits (&m_PixMap.Bounds, 0, m_PixMap.cmpCount, pBmp, pDataSrc);
break;
case 8:
unpack8bits (&m_PixMap.Bounds, 0, pBmp, pDataSrc);
break;
default:
unpackbits (&m_PixMap.Bounds, 0, m_PixMap.pixelSize, pBmp, pDataSrc);
}
}
void PLPictDecoder::longComment
( PLDataSource * pDataSrc
)
{
PLWORD type;
PLWORD len;
type = ReadMWord(pDataSrc);
len = ReadMWord(pDataSrc);
if (len > 0)
pDataSrc->Skip (len);
}
void PLPictDecoder::headerOp
( PLDataSource * pDataSrc
)
{
int Version = ReadMWord (pDataSrc);
m_Resolution.x = ReadMLong(pDataSrc);
m_Resolution.y = ReadMLong(pDataSrc);
MacRect Dummy;
readRect (&Dummy, pDataSrc);
ReadMWord (pDataSrc);
}
void PLPictDecoder::jpegOp
( PLDataSource * pDataSrc
)
// Invoke the JPEG decoder for this PICT.
{
long OpLen = ReadMLong(pDataSrc);
bool bFound = false;
int i = 0;
// skip to JPEG header.
while (!bFound && i < OpLen)
{
PLBYTE * pData = pDataSrc->GetBufferPtr (3);
if (pData[0] == 0xFF && pData[1] == 0xD8 && pData[2] == 0xFF)
bFound = true;
else
{
ReadByte(pDataSrc);
i++;
}
}
if (bFound)
// Pass the data to the JPEG decoder.
if (m_pJPEGDecoder)
#ifdef PL_SUPPORT_JPEG
{
m_pJPEGDecoder->Open (pDataSrc);
SetBmpInfo (*m_pJPEGDecoder);
m_PictType = jpeg;
}
#else
raiseError (PL_ERRFORMAT_NOT_SUPPORTED,
"Library not compiled for PICT/JPEG.");
#endif
else
raiseError (PL_ERRFORMAT_NOT_SUPPORTED,
"Library not compiled for PICT/JPEG.");
else
raiseError (PL_ERRFORMAT_NOT_SUPPORTED,
"PICT file contains unrecognized quicktime data.\n");
}
void PLPictDecoder::DecodeJPEG
( PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
{
#ifdef PL_SUPPORT_JPEG
m_pJPEGDecoder->GetImage(*pBmp);
#else
raiseError (PL_ERRFORMAT_NOT_SUPPORTED,
"Library not compiled for PICT/JPEG.");
#endif
}
/////////////////////////////////////////////////////////////////////
// Bitmap & Pixmap functions
void PLPictDecoder::setBmpInfo
( MacpixMap PixMap
)
{
PLPixelFormat pf;
if (PixMap.pixelSize > 8)
if (PixMap.cmpCount == 4)
pf = PLPixelFormat::A8R8G8B8;
else
pf = PLPixelFormat::X8R8G8B8;
else
pf = PLPixelFormat::I8;
SetBmpInfo (PLPoint (PixMap.Bounds.right - PixMap.Bounds.left,
PixMap.Bounds.bottom - PixMap.Bounds.top),
PLPoint (PixMap.hRes, PixMap.vRes), pf);
}
void PLPictDecoder::doBitmap
( PLDataSource * pDataSrc
)
// Decode version 1 bitmap: 1 bpp.
{
MacRect SrcRect;
MacRect DstRect;
PLWORD width; // Width in pixels
PLWORD height; // Height in pixels
Trace (2, "Reading version 1 bitmap.\n");
readRect(&m_Bounds, pDataSrc);
dumpRect (" Bounds", &m_Bounds);
readRect(&SrcRect, pDataSrc);
readRect(&DstRect, pDataSrc);
width = m_Bounds.right - m_Bounds.left;
height = m_Bounds.bottom - m_Bounds.top;
SetBmpInfo (PLPoint (width, height), PLPoint (0,0), PLPixelFormat::I8);
m_PictType = bitmap;
}
void PLPictDecoder::DecodeBitmap
( PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
{
PLWORD mode = ReadMWord(pDataSrc);
if (m_bIsRegion)
skipPolyOrRegion (pDataSrc);
pBmp->SetPaletteEntry (0, 0, 0, 0, 255);
pBmp->SetPaletteEntry (1, 255, 255, 255, 255);
unpackbits (&m_Bounds, m_rowBytes, 1, pBmp, pDataSrc);
}
void PLPictDecoder::doPixmap
( PLDataSource * pDataSrc
)
// Decode version 2 pixmap
{
readRect(&m_PixMap.Bounds, pDataSrc);
readPixmap(&m_PixMap, pDataSrc);
setBmpInfo (m_PixMap);
m_PictType = pixmap;
}
void PLPictDecoder::DecodePixmap
( PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
{
// Read mac colour table into windows palette.
PLWORD NumColors; // Palette size.
PLPixel32 Pal[256];
readColourTable (&NumColors, pDataSrc, Pal);
if (pBmp->GetBitsPerPixel() == 8)
pBmp->SetPalette (Pal);
// Ignore source & destination rectangle as well as transfer mode.
MacRect TempRect;
readRect (&TempRect, pDataSrc);
readRect (&TempRect, pDataSrc);
PLWORD mode = ReadMWord(pDataSrc);
if (m_bIsRegion)
skipPolyOrRegion (pDataSrc);
switch (m_PixMap.pixelSize)
{
case 32:
unpack32bits (&m_PixMap.Bounds, m_rowBytes, m_PixMap.cmpCount, pBmp, pDataSrc);
break;
case 8:
unpack8bits (&m_PixMap.Bounds, m_rowBytes, pBmp, pDataSrc);
break;
default:
unpackbits (&m_PixMap.Bounds, m_rowBytes, m_PixMap.pixelSize,
pBmp, pDataSrc);
}
}
void PLPictDecoder::unpack32bits
( MacRect* pBounds,
PLWORD rowBytes,
int NumBitPlanes, // 3 if RGB, 4 if RGBA
PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
// This routine decompresses BitsRects with a packType of 4 (and
// 32 bits per pixel). In this format, each line is separated
// into 8-bit-bitplanes and then compressed via RLE. To decode,
// the routine decompresses each line & then juggles the bytes
// around to get pixel-oriented data.
{
int i,j;
PLWORD BytesPerRow; // bytes per row when uncompressed.
PLPixel32 * pDestLine;
PLBYTE * pLinebuf; // Temporary buffer for line data. In
// this buffer, pixels are uncompressed
// but still plane-oriented.
PLPixel32 ** pLineArray = pBmp->GetLineArray32();
int Height = pBounds->bottom - pBounds->top;
int Width = pBounds->right - pBounds->left;
BytesPerRow = Width*NumBitPlanes;
if (rowBytes == 0)
rowBytes = Width*4;
// Allocate temporary line buffer.
pLinebuf = new PLBYTE [BytesPerRow];
try
{
for (i = 0; i < Height; i++)
{ // for each line do...
int linelen; // length of source line in bytes.
if (rowBytes > 250)
linelen = ReadMWord(pDataSrc);
else
linelen = ReadByte(pDataSrc);
PLBYTE * pBuf = unpackPictRow (pLinebuf, pDataSrc, Width, rowBytes, linelen);
// Convert plane-oriented data into pixel-oriented data &
// copy into destination bitmap.
pDestLine = pLineArray[i];
if (NumBitPlanes == 3)
for (j = 0; j < Width; j++)
{ // For each pixel in line...
pDestLine->SetB (*(pBuf+Width*2)); // Blue
pDestLine->SetG (*(pBuf+Width)); // Green
pDestLine->SetR (*pBuf); // Red
pDestLine->SetA (0xFF);
pDestLine++;
pBuf++;
}
else
for (j = 0; j < Width; j++)
{ // For each pixel in line...
pDestLine->SetB (*(pBuf+Width*3)); // Blue
pDestLine->SetG (*(pBuf+Width*2)); // Green
pDestLine->SetR (*(pBuf+Width)); // Red
pDestLine->SetA (*pBuf);
pDestLine++;
pBuf++;
}
}
}
catch (PLTextException)
{
delete [] pLinebuf;
throw;
}
catch(...)
{
delete [] pLinebuf;
throw;
}
delete [] pLinebuf;
}
void PLPictDecoder::unpack8bits
( MacRect* pBounds,
PLWORD rowBytes,
PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
// Decompression routine for 8 bpp. rowBytes is the number of
// bytes each source row would take if it were uncompressed.
// This _isn't_ equal to the number of pixels in the row - it
// seems apple pads the data to a word boundary and then
// compresses it. Of course, we have to decompress the excess
// data and then throw it away.
{
int i;
PLBYTE ** pLineArray = pBmp->GetLineArray();
int Height = pBounds->bottom - pBounds->top;
int Width = pBounds->right - pBounds->left;
// High bit of rowBytes is flag.
rowBytes &= 0x7fff;
if (rowBytes == 0)
rowBytes = Width;
PLBYTE * pLineBuf = new PLBYTE [rowBytes];
try
{
for (i = 0; i < Height; i++)
{
int linelen; // length of source line in bytes.
if (rowBytes > 250)
linelen = ReadMWord(pDataSrc);
else
linelen = ReadByte(pDataSrc);
PLBYTE * pRawLine = unpackPictRow (pLineBuf, pDataSrc, Width, rowBytes, linelen);
memcpy (pLineArray[i], pRawLine, Width);
}
}
catch (PLTextException)
{
delete [] pLineBuf;
throw;
}
delete [] pLineBuf;
}
void PLPictDecoder::unpackbits
( MacRect* pBounds,
PLWORD rowBytes,
int pixelSize, // Source bits per pixel.
PLBmpBase * pBmp,
PLDataSource * pDataSrc
)
// Decompression routine for everything but 8 & 32 bpp. This
// routine is slower than the two routines above since it has to
// deal with a lot of special cases :-(.
// It's also a bit chaotic because of these special cases...
// unpack8bits is basically a dumber version of unpackbits.
{
PLBYTE * pSrcLine; // Pointer to source line in file.
int i,j,k;
PLWORD pixwidth; // bytes per row when uncompressed.
int linelen; // length of source line in bytes.
int pkpixsize;
PLBYTE * pDestLine;
PLBYTE FlagCounter;
int len;
int PixelPerRLEUnit;
PLBYTE * pLineBuf;
PLBYTE * pBuf;
PLBYTE ** pLineArray = pBmp->GetLineArray();
int Height = pBounds->bottom - pBounds->top;
int Width = pBounds->right - pBounds->left;
// High bit of rowBytes is flag.
if (pixelSize <= 8)
rowBytes &= 0x7fff;
pixwidth = Width;
pkpixsize = 1; // RLE unit: one byte for everything...
if (pixelSize == 16) // ...except 16 bpp.
{
pkpixsize = 2;
pixwidth *= 2;
}
if (rowBytes == 0)
rowBytes = pixwidth;
try
{
// I allocate the temporary line buffer here. I allocate too
// much memory to compensate for sloppy (& hence fast)
// decompression.
switch (pixelSize)
{
case 1:
PixelPerRLEUnit = 8;
pLineBuf = new PLBYTE [(rowBytes+1) * 32];
break;
case 2:
PixelPerRLEUnit = 4;
pLineBuf = new PLBYTE [(rowBytes+1) * 16];
break;
case 4:
PixelPerRLEUnit = 2;
pLineBuf = new PLBYTE [(rowBytes+1) * 8];
break;
case 8:
PixelPerRLEUnit = 1;
pLineBuf = new PLBYTE [rowBytes * 4];
break;
case 16:
PixelPerRLEUnit = 1;
pLineBuf = new PLBYTE [rowBytes * 2 + 4];
break;
default:
char sz[256];
sprintf (sz,
"Illegal bpp value in unpackbits: %d\n",
pixelSize);
raiseError (PL_ERRFORMAT_UNKNOWN, sz);
}
if (rowBytes < 8)
{ // ah-ha! The bits aren't actually packed. This will be easy.
for (i = 0; i < Height; i++)
{
pDestLine = pLineArray[i];
pSrcLine = pDataSrc->ReadNBytes (rowBytes);
if (pixelSize == 16)
expandBuf(pDestLine, pSrcLine, Width, pixelSize);
else
expandBuf8(pDestLine, pSrcLine, Width, pixelSize);
}
}
else
{
for (i = 0; i < Height; i++)
{ // For each line do...
if (rowBytes > 250)
linelen = ReadMWord(pDataSrc);
else
linelen = ReadByte(pDataSrc);
pSrcLine = pDataSrc->ReadNBytes(linelen);
pBuf = pLineBuf;
// Unpack RLE. The data is packed bytewise - except for
// 16 bpp data, which is packed per pixel :-(.
for (j = 0; j < linelen; )
{
FlagCounter = pSrcLine[j];
if (FlagCounter & 0x80)
{
if (FlagCounter == 0x80)
// Special case: repeat value of 0.
// Apple sais ignore.
j++;
else
{ // Packed data.
len = ((FlagCounter ^ 255) & 255) + 2;
// This is slow for some formats...
if (pixelSize == 16)
{
expandBuf (pBuf, pSrcLine+j+1, 1, pixelSize);
for (k = 1; k < len; k++)
{ // Repeat the pixel len times.
memcpy (pBuf+(k*4*PixelPerRLEUnit), pBuf,
4*PixelPerRLEUnit);
}
pBuf += len*4*PixelPerRLEUnit;
}
else
{
expandBuf8 (pBuf, pSrcLine+j+1, 1, pixelSize);
for (k = 1; k < len; k++)
{ // Repeat the expanded byte len times.
memcpy (pBuf+(k*PixelPerRLEUnit), pBuf,
PixelPerRLEUnit);
}
pBuf += len*PixelPerRLEUnit;
}
j += 1 + pkpixsize;
}
}
else
{ // Unpacked data
len = (FlagCounter & 255) + 1;
if (pixelSize == 16)
{
expandBuf (pBuf, pSrcLine+j+1, len, pixelSize);
pBuf += len*4*PixelPerRLEUnit;
}
else
{
expandBuf8 (pBuf, pSrcLine+j+1, len, pixelSize);
pBuf += len*PixelPerRLEUnit;
}
j += len * pkpixsize + 1;
}
}
pDestLine = pLineArray[i];
if (pixelSize == 16)
memcpy (pDestLine, pLineBuf, 4*Width);
else
memcpy (pDestLine, pLineBuf, Width);
}
}
}
catch (PLTextException)
{
delete [] pLineBuf;
throw;
}
delete [] pLineBuf;
}
void PLPictDecoder::skipBits
( MacRect* pBounds,
PLWORD rowBytes,
int pixelSize, // Source bits per pixel.
PLDataSource * pDataSrc
)
// skips unneeded packbits.
{
int i;
PLWORD pixwidth; // bytes per row when uncompressed.
int linelen; // length of source line in bytes.
int Height = pBounds->bottom - pBounds->top;
int Width = pBounds->right - pBounds->left;
// High bit of rowBytes is flag.
if (pixelSize <= 8)
rowBytes &= 0x7fff;
pixwidth = Width;
if (pixelSize == 16)
pixwidth *= 2;
if (rowBytes == 0)
rowBytes = pixwidth;
if (rowBytes < 8)
{
pDataSrc->Skip (rowBytes*Height);
}
else
{
for (i = 0; i < Height; i++)
{
if (rowBytes > 250)
linelen = ReadMWord(pDataSrc);
else
linelen = ReadByte(pDataSrc);
pDataSrc->Skip (linelen);
}
}
}
void PLPictDecoder::expandBuf
( PLBYTE * pDestBuf,
PLBYTE * pSrcBuf,
int Width, // Width in bytes for 8 bpp or less.
// Width in pixels for 16 bpp.
int bpp // bits per pixel
)
// Expands Width units to 32-bit pixel data.
{
PLBYTE * pSrc;
PLBYTE * pDest;
int i;
pSrc = pSrcBuf;
pDest = pDestBuf;
switch (bpp)
{
case 16:
for (i=0; i> 5) & 31)*8; // Green
*(pDestBuf+PL_RGBA_RED) = ((Src >> 10) & 31)*8; // Red
*(pDestBuf+PL_RGBA_ALPHA) = 0xFF; // Alpha
pSrcBuf += 2;
pDestBuf += 4;
}
break;
default:
raiseError (PL_ERRFORMAT_UNKNOWN,
"Bad bits per pixel in expandBuf.");
}
return;
}
void PLPictDecoder::expandBuf8
( PLBYTE * pDestBuf,
PLBYTE * pSrcBuf,
int Width, // Width in bytes.
int bpp // bits per pixel.
)
// Expands Width units to 8-bit pixel data.
// Max. 8 bpp source format.
{
PLBYTE * pSrc;
PLBYTE * pDest;
int i;
pSrc = pSrcBuf;
pDest = pDestBuf;
switch (bpp)
{
case 8:
memcpy (pDestBuf, pSrcBuf, Width);
break;
case 4:
for (i=0; i> 4) & 15;
*(pDest+1) = (*pSrc & 15);
pSrc++;
pDest += 2;
}
if (Width & 1) // Odd Width?
{
*pDest = (*pSrc >> 4) & 15;
pDest++;
}
break;
case 2:
for (i=0; i> 6) & 3;
*(pDest+1) = (*pSrc >> 4) & 3;
*(pDest+2) = (*pSrc >> 2) & 3;
*(pDest+3) = (*pSrc & 3);
pSrc++;
pDest += 4;
}
if (Width & 3) // Check for leftover pixels
for (i=6; i>8-(Width & 3)*2; i-=2)
{
*pDest = (*pSrc >> i) & 3;
pDest++;
}
break;
case 1:
for (i=0; i> 7) & 1;
*(pDest+1) = (*pSrc >> 6) & 1;
*(pDest+2) = (*pSrc >> 5) & 1;
*(pDest+3) = (*pSrc >> 4) & 1;
*(pDest+4) = (*pSrc >> 3) & 1;
*(pDest+5) = (*pSrc >> 2) & 1;
*(pDest+6) = (*pSrc >> 1) & 1;
*(pDest+7) = (*pSrc & 1);
pSrc++;
pDest += 8;
}
if (Width & 7) // Check for leftover pixels
for (i=7; i>(8-Width & 7); i--)
{
*pDest = (*pSrc >> i) & 1;
pDest++;
}
break;
default:
raiseError (PL_ERRFORMAT_UNKNOWN,
"Bad bits per pixel in expandBuf8.");
}
return;
}
/////////////////////////////////////////////////////////////////////
// Auxillary functions
void PLPictDecoder::readPixmap
( MacpixMap * pPixMap,
PLDataSource * pDataSrc
)
{
pPixMap->version = ReadMWord(pDataSrc);
pPixMap->packType = ReadMWord(pDataSrc);
pPixMap->packSize = ReadMLong(pDataSrc);
pPixMap->hRes = ReadMWord(pDataSrc);
ReadMWord(pDataSrc);
pPixMap->vRes = ReadMWord(pDataSrc);
ReadMWord(pDataSrc);
pPixMap->pixelType = ReadMWord(pDataSrc);
pPixMap->pixelSize = ReadMWord(pDataSrc);
pPixMap->cmpCount = ReadMWord(pDataSrc);
pPixMap->cmpSize = ReadMWord(pDataSrc);
pPixMap->planeBytes = ReadMLong(pDataSrc);
pPixMap->pmTable = ReadMLong(pDataSrc);
pPixMap->pmReserved = ReadMLong(pDataSrc);
tracePixMapHeader (2, pPixMap);
}
void PLPictDecoder::readColourTable
( PLWORD * pNumColors,
PLDataSource * pDataSrc,
PLPixel32 * pPal
)
// Reads a mac colour table into a bitmap palette.
{
PLLONG ctSeed;
PLWORD ctFlags;
PLWORD val;
int i;
Trace (3, "Getting color table info.\n");
ctSeed = ReadMLong(pDataSrc);
ctFlags = ReadMWord(pDataSrc);
*pNumColors = ReadMWord(pDataSrc)+1;
char sz[256];
sprintf (sz, "Palette Size: %d\n", *pNumColors);
Trace (2, sz);
Trace (3, "Reading Palette.\n");
for (i = 0; i < *pNumColors; i++)
{
val = ReadMWord(pDataSrc);
if (ctFlags & 0x8000)
// The indicies in a device colour table are bogus and
// usually == 0, so I assume we allocate up the list of
// colours in order.
val = i;
if (val >= *pNumColors)
{
raiseError (PL_ERRFORMAT_UNKNOWN,
"pixel value greater than colour table size.");
}
// Mac colour tables contain 16-bit values for R, G, and B...
pPal[val].SetR ((PLBYTE) (((PLWORD) (ReadMWord(pDataSrc)) >> 8) & 0xFF));
pPal[val].SetG ((PLBYTE) (((PLWORD) (ReadMWord(pDataSrc)) >> 8) & 0xFF));
pPal[val].SetB ((PLBYTE) (((PLWORD) (ReadMWord(pDataSrc)) >> 8) & 0xFF));
}
}
void PLPictDecoder::readRect
( MacRect * pr,
PLDataSource * pDataSrc
)
{
pr->top = ReadMWord(pDataSrc);
pr->left = ReadMWord(pDataSrc);
pr->bottom = ReadMWord(pDataSrc);
pr->right = ReadMWord(pDataSrc);
}
void PLPictDecoder::dumpRect
( char * psz,
MacRect * pr
)
{
char sz[256];
sprintf (sz, "%s (%d,%d) (%d,%d).\n",
psz, pr->left, pr->top, pr->right, pr->bottom);
Trace (2, sz);
}
void PLPictDecoder::tracePixMapHeader
( int Level,
MacpixMap * pPixMap
)
{
char sz[256];
Trace (Level, "PixMap header info:\n");
dumpRect (" Bounds:", &(pPixMap->Bounds));
sprintf (sz, " version: 0x%x\n", pPixMap->version);
Trace (Level, sz);
sprintf (sz, " packType: %d\n", pPixMap->packType);
Trace (Level, sz);
sprintf (sz, " packSize: %ld\n", pPixMap->packSize);
Trace (Level, sz);
sprintf (sz, " hRes: %ld\n", pPixMap->hRes);
Trace (Level, sz);
sprintf (sz, " vRes: %ld\n", pPixMap->vRes);
Trace (Level, sz);
sprintf (sz, " pixelSize: %d\n", pPixMap->pixelSize);
Trace (Level, sz);
sprintf (sz, " cmpCount: %d\n", pPixMap->cmpCount);
Trace (Level, sz);
sprintf (sz, " cmpSize: %d.\n", pPixMap->cmpSize);
Trace (Level, sz);
sprintf (sz, " planeBytes: %ld.\n", pPixMap->planeBytes);
Trace (Level, sz);
}
/*
/--------------------------------------------------------------------
|
| $Log: plpictdec.cpp,v $
| Revision 1.14 2004/10/02 22:23:12 uzadow
| - configure and Makefile cleanups\n- Pixelformat enhancements for several filters\n- Added PLBmpBase:Dump\n- Added PLBmpBase::GetPixelNn()-methods\n- Changed default unix byte order to BGR
|
| Revision 1.13 2004/09/11 12:41:35 uzadow
| removed plstdpch.h
|
| Revision 1.12 2004/09/09 16:52:49 artcom
| refactored PixelFormat
|
| Revision 1.11 2004/06/19 16:49:07 uzadow
| Changed GetImage so it works with PLBmpBase
|
| Revision 1.10 2002/11/04 21:03:12 uzadow
| Fixed error when PL_SUPPORT_JPEG was turned off.
|
| Revision 1.9 2002/08/04 21:20:41 uzadow
| no message
|
| Revision 1.8 2002/08/04 20:08:01 uzadow
| Added PLBmpInfo class, ability to extract metainformation from images without loading the whole image and proper greyscale support.
|
| Revision 1.7 2002/03/31 13:36:42 uzadow
| Updated copyright.
|
| Revision 1.6 2001/10/21 17:12:40 uzadow
| Added PSD decoder beta, removed BPPWanted from all decoders, added PLFilterPixel.
|
| Revision 1.5 2001/10/16 17:12:26 uzadow
| Added support for resolution information (Luca Piergentili)
|
| Revision 1.4 2001/10/06 22:03:26 uzadow
| Added PL prefix to basic data types.
|
| Revision 1.3 2001/10/06 15:32:22 uzadow
| Removed types LPBYTE, DWORD, UCHAR, VOID and INT from the code.
|
| Revision 1.2 2001/09/16 20:57:17 uzadow
| Linux version name prefix changes
|
| Revision 1.1 2001/09/16 19:03:22 uzadow
| Added global name prefix PL, changed most filenames.
|
| Revision 1.12 2001/02/04 14:31:52 uzadow
| Member initialization list cleanup (Erik Hoffmann).
|
| Revision 1.11 2001/01/21 14:28:21 uzadow
| Changed array cleanup from delete to delete[].
|
| Revision 1.10 2000/12/18 22:42:52 uzadow
| Replaced RGBAPIXEL with PLPixel32.
|
| Revision 1.9 2000/10/24 23:01:42 uzadow
| Fixed bug in ver.1 bitmap decoder
|
| Revision 1.8 2000/08/13 12:11:43 Administrator
| Added experimental DirectDraw-Support
|
| Revision 1.7 2000/05/27 16:28:28 Ulrich von Zadow
| Really fixed bug decoding pixmaps with < 8 bpp.
|
| Revision 1.6 2000/03/15 17:23:20 Ulrich von Zadow
| Fixed bug decoding pixmaps with < 8 bpp.
|
| Revision 1.5 2000/01/16 20:43:14 anonymous
| Removed MFC dependencies
|
| Revision 1.4 1999/11/22 15:00:27 Ulrich von Zadow
| Fixed bug decoding small 24 bpp pict files.
|
| Revision 1.3 1999/10/03 18:50:51 Ulrich von Zadow
| Added automatic logging of changes.
|
|
\--------------------------------------------------------------------
*/