void PLSGIDecoder::Open (PLDataSource * pDataSrc) { Trace (2, "Decoding SGI.\n"); PLPixelFormat pf; readHeader (&m_Header, pDataSrc); bool bGreyscale = (m_Header.ZSize == 1 && static_cast<int>(m_Header.Colormap) == CMAP_NORMAL); switch (m_Header.ZSize) { case 1: if (bGreyscale) { pf = PLPixelFormat::L8; } else { pf = PLPixelFormat::I8; } break; case 2: throw PLTextException (PL_ERRFORMAT_NOT_SUPPORTED, "Two-channel SGI RGB files are not supported."); break; case 3: pf = PLPixelFormat::X8R8G8B8; break; case 4: // Image has alpha channel pf = PLPixelFormat::A8R8G8B8; } if (m_Header.Dimension == 1) { throw PLTextException (PL_ERRFORMAT_NOT_SUPPORTED, "One-dimensional SGI RGB files are not supported."); } SetBmpInfo (PLPoint (m_Header.XSize, m_Header.YSize), PLPoint(0, 0), pf); }
void PLBmpDecoder::Open (PLDataSource * pDataSrc) { m_pBMI = getInfoHeader (pDataSrc, &m_Pal[0]); PLPixelFormat pf; if (m_pBMI->biBitCount <= 8) { pf = PLPixelFormat::L8; } else { if (m_pBMI->biBitCount == 32) { pf = PLPixelFormat::A8R8G8B8; } else { pf = PLPixelFormat::X8R8G8B8; } } PLPoint DPI(0,0); if (m_pBMI->biXPelsPerMeter > 0) DPI.x = (int)((float)m_pBMI->biXPelsPerMeter / 39.37f+0.5); if (DPI.x <= 1) DPI.x = 0; if (m_pBMI->biYPelsPerMeter > 0) DPI.y = (int)((float)m_pBMI->biYPelsPerMeter / 39.37f+0.5); if (DPI.y <= 1) DPI.y = 0; SetBmpInfo (PLPoint (m_pBMI->biWidth, m_pBMI->biHeight), DPI, pf); }
void CDemoDib::CreateDibSection(CDC* pDC, CImage* pImage) { SetBmpInfo(pImage); m_hBmp = ::CreateDIBSection( pDC->GetSafeHdc(), GetBmpInfo(), DIB_RGB_COLORS, (void**)(&m_pBits), NULL, 0); }
void PLPGMDecoder::Open (PLDataSource * pDataSrc) { Trace (2, "Decoding PGM.\n"); readPgmHeader(&m_PGMHeader, pDataSrc); SetBmpInfo (PLPoint(m_PGMHeader.ImageWidth, m_PGMHeader.ImageHeight), PLPoint (0,0), PLPixelFormat::L8); }
void PLPCXDecoder::Open(PLDataSource * pDataSrc) { // Check if the file is a valid PCX file or not Trace (2, "Decoding PCX.\n"); m_PcxHeader.Manufacturer = ReadByte (pDataSrc); m_PcxHeader.Version = ReadByte (pDataSrc); m_PcxHeader.Encoding = ReadByte (pDataSrc); m_PcxHeader.BitsPerPixel = ReadByte (pDataSrc); m_PcxHeader.Xmin = ReadIWord (pDataSrc); m_PcxHeader.Ymin = ReadIWord (pDataSrc); m_PcxHeader.Xmax = ReadIWord (pDataSrc); m_PcxHeader.Ymax = ReadIWord (pDataSrc); m_PcxHeader.Hres = ReadIWord (pDataSrc); m_PcxHeader.Vres = ReadIWord (pDataSrc); memcpy (m_PcxHeader.ColorMap, pDataSrc->ReadNBytes (16*3),16*3); m_PcxHeader.Reserved = ReadByte (pDataSrc); m_PcxHeader.ColorPlanes = ReadByte (pDataSrc); m_PcxHeader.BytesPerLine = ReadIWord (pDataSrc); m_PcxHeader.PaletteType = ReadIWord (pDataSrc); memcpy (m_PcxHeader.Filter, pDataSrc->ReadNBytes (58), 58); if (m_PcxHeader.Manufacturer != PCX_MAGIC) { raiseError (PL_ERRWRONG_SIGNATURE, "Error decoding pcx: Not a PCX file."); } // Check for PCX run length encoding if (m_PcxHeader.Encoding != 1) { raiseError (PL_ERRWRONG_SIGNATURE, "File has unknown encoding scheme."); } // Check that we can handle this image format switch (m_PcxHeader.BitsPerPixel) { case 1: if (m_PcxHeader.ColorPlanes > 4) { raiseError(PL_ERRFORMAT_UNKNOWN, "Can't handle image with more than 4 planes."); } break; case 2: case 4: case 8: if (m_PcxHeader.ColorPlanes == 1 || m_PcxHeader.ColorPlanes == 3) break; default: raiseError(PL_ERRFORMAT_UNKNOWN, "Can't handle bits per pixel image with planes."); break; } int Width = (m_PcxHeader.Xmax - m_PcxHeader.Xmin) + 1; int Height = (m_PcxHeader.Ymax - m_PcxHeader.Ymin) + 1; SetBmpInfo (PLPoint(Width, Height), PLPoint (m_PcxHeader.Hres, m_PcxHeader.Vres), PLPixelFormat::X8R8G8B8); }
void ImageLoader::removeUnusedAlpha() { if (!_isI60 && GetBitsPerPixel() == 32 && !HasAlpha()) { // Compress unused fourth channel AC_DEBUG << "ImageLoader removing unused fourth channel"; unsigned myHeight = GetHeight(); unsigned myWidth = GetWidth(); //unsigned myLineStride = GetBytesPerLine(); asl::Ptr<Block> myDestinationBlock = asl::Ptr<Block>(new Block()); myDestinationBlock->resize(myHeight * myWidth * 3); unsigned char ** myLineArray = GetLineArray(); unsigned char * myDestination = myDestinationBlock->begin(); for (unsigned i = 0; i < myHeight; ++i) { unsigned char * mySource = *myLineArray; for (unsigned j = 0; j < myWidth; ++j) { myDestination[0] = mySource[0]; myDestination[1] = mySource[1]; myDestination[2] = mySource[2]; mySource += 4; myDestination += 3; } myLineArray++; } // Update internal representation switch (_myEncoding) { case RGBA : _myEncoding = RGB; break; case BGRA : _myEncoding = BGR; break; default: throw ImageLoaderException("Unsupported pixel encoding", PLUS_FILE_LINE); } _myData = myDestinationBlock; PLPixelFormat myPixelFormat; mapPixelEncodingToFormat(_myEncoding, myPixelFormat); SetBmpInfo(GetSize(), GetResolution(), myPixelFormat); updateLineArray(); } }
void PLTIFFDecoder::Open (PLDataSource * pDataSrc) { PLASSERT (m_pTif == 0); m_pTif = TIFFOpenMem (pDataSrc->ReadEverything(), pDataSrc->GetFileSize(), NULL); if (!m_pTif) raiseError (PL_ERRWRONG_SIGNATURE, m_szLastErr); uint16 BitsPerSample; uint16 SamplesPerPixel; uint32 ImageHeight; uint32 ImageWidth; // get tagged image parameters TIFFGetFieldDefaulted(m_pTif, TIFFTAG_IMAGEWIDTH, &ImageWidth); TIFFGetFieldDefaulted(m_pTif, TIFFTAG_IMAGELENGTH, &ImageHeight); TIFFGetFieldDefaulted(m_pTif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample); TIFFGetFieldDefaulted(m_pTif, TIFFTAG_SAMPLESPERPIXEL, &SamplesPerPixel); int16 PhotometricInterpretation; TIFFGetFieldDefaulted(m_pTif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation); PLPixelFormat pf = PLPixelFormat::X8R8G8B8; if (!TIFFIsTiled(m_pTif)) { if (SamplesPerPixel == 1 && BitsPerSample ==1) pf = PLPixelFormat::L1; else if (SamplesPerPixel < 3 && BitsPerSample <= 8) if (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE || PhotometricInterpretation == PHOTOMETRIC_MINISBLACK) pf = PLPixelFormat::L8; else pf = PLPixelFormat::I8; else if (SamplesPerPixel < 3 && BitsPerSample <= 16) pf = PLPixelFormat::L16; } if (SamplesPerPixel == 4 && (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE || PhotometricInterpretation == PHOTOMETRIC_MINISBLACK || PhotometricInterpretation == PHOTOMETRIC_RGB || PhotometricInterpretation == PHOTOMETRIC_PALETTE)) pf = PLPixelFormat::A8R8G8B8; SetBmpInfo (PLPoint (ImageWidth, ImageHeight), getResolution (m_pTif), pf); }
void ImageLoader::loadI60File(asl::Ptr<ReadableBlockHandle> theImageBlock) { _myImageMatrix.makeIdentity(); I60Header myHeader; theImageBlock->getBlock().readData(myHeader, 0); if (!myHeader.checkMagicNumber()) { throw ImageLoaderException(string("Image ") + _myFilename + " has a wrong magic number. '" + I60_MAGIC_NUMBER + "' expeced.", PLUS_FILE_LINE); } if (!myHeader.checkVersion()) { throw ImageLoaderException(string("Image ") + _myFilename + " file format version: " + as_string(myHeader.version) + " does not match current reader version: " + as_string(CURRENT_IMAGE_FORMAT_VERSION), PLUS_FILE_LINE); } _myHeaderSize = myHeader.headersize; _myEncoding = PixelEncoding(myHeader.encoding); _isI60 = true; unsigned myWidthPowerOfTwo = asl::nextPowerOfTwo(myHeader.width); unsigned myHeightPowerOfTwo = asl::nextPowerOfTwo(myHeader.height); _myImageMatrix.scale(Vector3f(float(myHeader.width) / myWidthPowerOfTwo, float(myHeader.height) / myHeightPowerOfTwo, 1.0f)); // maybe we should cut off the i60 header here? unsigned myBlockSize = theImageBlock->getBlock().size(); _myData = asl::Ptr<Block>(new Block()); _myData->resize(myBlockSize - sizeof(I60Header)); std::copy(theImageBlock->getBlock().begin()+sizeof(I60Header), theImageBlock->getBlock().end(), _myData->begin()); // TODO: Add support for other compression formats SetBmpInfo(PLPoint(myWidthPowerOfTwo, myHeightPowerOfTwo * myHeader.layercount), GetResolution(), PLPixelFormat::L1 /* only correct for DXT5 */); }
void PLWEMFDecoder::Open (PLDataSource * pDataSrc) { PLASSERT_VALID(this); PLASSERT(m_bm == 0); PLASSERT(m_memdc == 0); PLASSERT(m_hemf == 0); SAPMFILEHEADER* pplaceablehdr = NULL; bool isadobe = false; bool isemf; // Get the type of the file (WMF or EMF) from the file name if (pDataSrc->NameIsWide()){ wchar_t* strname = _wcsdup(pDataSrc->GetNameW()); PLASSERT(strname); if (strname == NULL) { // This should never happen under 32-Bit, but who knows? PLASSERT(false); raiseError (PL_ERRNO_MEMORY,"Out of memory during strdup."); } _wcsupr(strname); isemf = wcsstr(strname,L".EMF") != NULL; free(strname); } else{ char* strname = _strdup(pDataSrc->GetName()); PLASSERT(strname); if (strname == NULL) { // This should never happen under 32-Bit, but who knows? PLASSERT(false); raiseError (PL_ERRNO_MEMORY,"Out of memory during strdup."); } _strupr(strname); bool isemf = strstr(strname,".EMF") != NULL; free(strname); } // Get a DC for the display m_dc = ::GetDC(NULL); PLASSERT(m_dc); if (m_dc == NULL) { PLASSERT(false); raiseError (PL_ERRNO_MEMORY,"Cannot allocate device context."); } if (isemf) { // We have an enhanced meta file which makes it alot easier m_hemf = SetEnhMetaFileBits(pDataSrc->GetFileSize(),pDataSrc->ReadEverything()); } else { // Buh, old 16-Bit WMF, Convert it to an enhanced metafile before proceeding. // Also, check if this is a placeable metafile with an Adobe Placeable header pplaceablehdr = (SAPMFILEHEADER*)pDataSrc->ReadEverything(); PLBYTE* p = NULL; UINT size; // If we have an adobe header, skip it to use only the real windows-conform data if (pplaceablehdr->key == ALDUSKEY) { isadobe = true; p = pDataSrc->ReadEverything()+sizeof(SAPMFILEHEADER); size = pDataSrc->GetFileSize() - sizeof(SAPMFILEHEADER); } else { // Else use the whole file contents as the metafile and assume // a native 16-Bit Windows-conform WMF p = pDataSrc->ReadEverything(); size = pDataSrc->GetFileSize(); } #ifdef _MFC_VER PLASSERT(AfxIsValidAddress(p,size,false)); #endif m_hemf = SetWinMetaFileBits(size,p,m_dc,NULL); } // If m_hemf is NULL, windows refused to load the metafile. If this is // the case, we're done. Notify the caller if (m_hemf == NULL) { raiseError (PL_ERRFORMAT_NOT_SUPPORTED,"Windows Metafile functions failed to load this image."); } // Get the header from the enhanced metafile, It contains some // useful information which will aid us during constuction of // the bitmap. // The header is of variable length. First get the amount of // memory required for the header UINT sizeneeded = GetEnhMetaFileHeader(m_hemf,0,NULL); if (sizeneeded == 0) { raiseError (PL_ERRFORMAT_UNKNOWN,"No header information in metafile"); } // Allocate storage for the header and read it in m_phdr = (LPENHMETAHEADER) new PLBYTE[sizeneeded]; if (m_phdr == NULL) { PLASSERT(false); raiseError (PL_ERRNO_MEMORY,"Out of memory during allocation of header."); } m_phdr->iType = EMR_HEADER; m_phdr->nSize = sizeneeded; #ifdef _MFC_VER PLASSERT(AfxIsValidAddress(m_phdr,sizeneeded,true)); #endif GetEnhMetaFileHeader(m_hemf,sizeneeded,m_phdr); int bpp = GetDeviceCaps(m_dc,BITSPIXEL); // Calculate the dimensions of the final bitmap. If we have // a placeable header in the WMF, we use the dimensions of // that image, else we use the calculated dimensions in the // EMF int width,height; if (isadobe) { PLASSERT(pplaceablehdr); int lpx = GetDeviceCaps(m_dc,LOGPIXELSX); int lpy = GetDeviceCaps(m_dc,LOGPIXELSY); // Calculate the absolute with and height and transform from twips to pixel width = (int) (pplaceablehdr->Right-pplaceablehdr->Left) * lpx / pplaceablehdr->inch; height = (int) (pplaceablehdr->Bottom-pplaceablehdr->Top) * lpy / pplaceablehdr->inch; } else { // Use the rclFrame of the header because it is the true device independent // information and also some applications (e.g. Corel) don't fill the // rclBounds correctly // Using: // MetaPixelsX = MetaWidthMM * MetaPixels / (MetaMM * 100); // where: // MetaWidthMM = metafile width in 0.01mm units // MetaPixels = width in pixels of the reference device // MetaMM = width in millimeters of the reference device // Same applies to the Y axis width = ((m_phdr->rclFrame.right - m_phdr->rclFrame.left) * m_phdr->szlDevice.cx) / (m_phdr->szlMillimeters.cx*100); height = ((m_phdr->rclFrame.bottom - m_phdr->rclFrame.top) * m_phdr->szlDevice.cy) / (m_phdr->szlMillimeters.cy*100); } // If this is a very old WMF without a PLACEABLE info, // we use somewhat meaningful defaults. Also, if the header was // not written correctly, we use this as a fallback if (width <= 0) { width = 320; } if (height <= 0) { height = 200; } // Create a device content for the screen, and a memory device // content to play the metafile to m_memdc = CreateCompatibleDC(m_dc); PLASSERT(m_memdc); if (m_memdc == NULL) { PLASSERT(false); raiseError (PL_ERRNO_MEMORY,"Cannot allocate device context."); } m_bm = CreateCompatibleBitmap(m_dc,width,height); if (m_bm == NULL) { PLASSERT(false); raiseError (PL_ERRNO_MEMORY,"Cannot allocate memory bitmap."); } m_holdbm = SelectObject(m_memdc,m_bm); // If the metafile has a palette, read it in UINT pe = GetEnhMetaFilePaletteEntries(m_hemf, 0, NULL); // pe is the real number of palette entries. To make the resulting // bitmap more useful, we always setup a 256 color palette if the // metafile has a palette if (pe>0 && pe<256) { SetBmpInfo (PLPoint (width, height), PLPoint(0,0), PLPixelFormat::L8); } else { SetBmpInfo (PLPoint (width, height), PLPoint(0,0), PLPixelFormat::B8G8R8A8); } }
void PLPNGDecoder::Open(PLDataSource *pDataSrc) { png_uint_32 width, height; m_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, user_error_fn, user_warning_fn); PLASSERT(m_png_ptr); m_info_ptr = png_create_info_struct(m_png_ptr); PLASSERT(m_info_ptr); png_set_read_fn(m_png_ptr, (void*)pDataSrc, my_read_data); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(m_png_ptr, m_info_ptr); #ifdef DUMP_PNG_DATA debugLog("%s", toString(*m_png_ptr).cstr()); #endif png_get_IHDR(m_png_ptr, m_info_ptr, &width, &height, &m_bit_depth ,&m_color_type, NULL, NULL, NULL); if( (m_color_type != PNG_COLOR_TYPE_RGB_ALPHA) && (m_color_type != PNG_COLOR_TYPE_GRAY_ALPHA) && ((m_color_type != PNG_COLOR_TYPE_RGB) || (m_bit_depth < 16)) ) { #ifdef PNG_READ_16_TO_8_SUPPORTED if(m_bit_depth == 16) { #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED png_set_scale_16(png_ptr); #else png_set_strip_16(png_ptr); #endif } #endif if(m_color_type == PNG_COLOR_TYPE_PALETTE) { png_set_expand(m_png_ptr); } if(m_bit_depth < 8) { png_set_expand(m_png_ptr); } if(png_get_valid(m_png_ptr, m_info_ptr, PNG_INFO_tRNS)) { png_set_expand(m_png_ptr); } if((m_color_type == PNG_COLOR_TYPE_GRAY) || (m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { png_set_gray_to_rgb(m_png_ptr); } /* set the background color to draw transparent and alpha images over */ png_color_16 *pBackground; png_color bkgColor = {127, 127, 127}; if(png_get_bKGD(m_png_ptr, m_info_ptr, &pBackground)) { png_set_background(m_png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); bkgColor.red = (png_byte)pBackground->red; bkgColor.green = (png_byte)pBackground->green; bkgColor.blue = (png_byte)pBackground->blue; #ifdef DUMP_PNG_DATA debugLog(" Background : (%d,%d,%d)\n", bkgColor.red, bkgColor.green, bkgColor.blue); #endif } /* if required set gamma conversion */ double dGamma; if(png_get_gAMA(m_png_ptr, m_info_ptr, &dGamma)) { png_set_gamma(m_png_ptr, (double)2.2, dGamma); } /* after the transformations are registered, update info_ptr data */ png_read_update_info(m_png_ptr, m_info_ptr); png_get_IHDR(m_png_ptr, m_info_ptr, &width, &height, &m_bit_depth ,&m_color_type, NULL, NULL, NULL); } PLPixelFormat pf; switch(m_color_type) { case PNG_COLOR_TYPE_RGB: pf = PLPixelFormat::R8G8B8; break; case PNG_COLOR_TYPE_RGB_ALPHA: pf = PLPixelFormat::A8R8G8B8; break; case PNG_COLOR_TYPE_GRAY: pf = PLPixelFormat::L8; break; case PNG_COLOR_TYPE_GRAY_ALPHA: png_set_gray_to_rgb(m_png_ptr); png_set_expand(m_png_ptr); pf = PLPixelFormat::A8R8G8B8; break; case PNG_COLOR_TYPE_PALETTE: if(m_bit_depth != 16) { pf = PLPixelFormat::I8; } else { // 16-bit palette image png_set_expand(m_png_ptr); pf = PLPixelFormat::R8G8B8; } break; } if((pf.GetBitsPerPixel() == 32) || (pf.GetBitsPerPixel() == 24)) { png_set_bgr(m_png_ptr); } SetBmpInfo(PLPoint(width, height), PLPoint(0,0), pf); png_uint_32 XRes, YRes; int UnitType; png_get_pHYs(m_png_ptr, m_info_ptr, &XRes, &YRes, &UnitType); if(UnitType == PNG_RESOLUTION_METER) { m_Resolution = PLPoint(int (XRes/39.37f+0.5), int (YRes/39.37f+0.5)); } }
void PLIFF85Decoder::Open(PLDataSource * pDataSrc) { // Check if the file is a valid IFF-85 file or not Trace(2, "Decoding IFF-85 header.\n"); PLIFF85::Chunk chunk; if (PLIFF85::MakeID(reinterpret_cast<const char*> (pDataSrc->GetBufferPtr(sizeof chunk))) != PLIFF85::ID_FORM) { raiseError(PL_ERRWRONG_SIGNATURE, "File is not a single-form IFF."); } readChunkHeader(chunk, pDataSrc); size_t totalSize = chunk.ckSize + sizeof chunk; size_t lumpIndex = sizeof chunk; // Now read the form type - we only know how to handle PBM and ILBM. chunk.ckID = ReadMLong(pDataSrc); if (chunk.ckID == PLIFF85::ID_PBM) { Trace(2, "Form type: PBM\n"); } else if (chunk.ckID == PLIFF85::ID_ILBM) { Trace(2, "Form type: ILBM\n"); } else { raiseError(PL_ERRFORMAT_UNKNOWN, "Unknown form type."); } m_formType = chunk.ckID; lumpIndex += sizeof chunk.ckID; int numCMapElements = 0; m_viewMode = 0; // Now loop through the chunks, processing the header and cmap. // Stop when we find the body, so the data source is left in the correct // position to read it. bool readBitmapHeader = false; bool readPalette = false; bool foundBody = false; bool done = false; PLIFF85::LONG bodySize = 0; while (!done) { readChunkHeader(chunk, pDataSrc); lumpIndex += sizeof chunk; if (chunk.ckID == PLIFF85::ID_BMHD) { if (size_t(chunk.ckSize) != sizeof m_bitmapHeader) { raiseError(PL_ERRFORMAT_UNKNOWN, "Unexpected header size."); } m_bitmapHeader.w = ReadMWord(pDataSrc); m_bitmapHeader.h = ReadMWord(pDataSrc); m_bitmapHeader.x = ReadMWord(pDataSrc); m_bitmapHeader.y = ReadMWord(pDataSrc); m_bitmapHeader.nPlanes = ReadByte(pDataSrc); m_bitmapHeader.masking = ReadByte(pDataSrc); m_bitmapHeader.compression = ReadByte(pDataSrc); m_bitmapHeader.pad1 = ReadByte(pDataSrc); m_bitmapHeader.transparentColor = ReadMWord(pDataSrc); m_bitmapHeader.xAspect = ReadByte(pDataSrc); m_bitmapHeader.yAspect = ReadByte(pDataSrc); m_bitmapHeader.pageWidth = ReadMWord(pDataSrc); m_bitmapHeader.pageHeight = ReadMWord(pDataSrc); switch (m_bitmapHeader.masking) { case PLIFF85::mskNone: Trace(2, "No masking.\n"); break; case PLIFF85::mskHasMask: Trace(2, "Has mask plane.\n"); break; case PLIFF85::mskHasTransparentColor: Trace(2, "Has transparent colour.\n"); break; case PLIFF85::mskLasso: Trace(2, "Lasso"); break; default: raiseError(PL_ERRFORMAT_UNKNOWN, "Unknown masking technique."); break; } switch (m_bitmapHeader.compression) { case PLIFF85::cmpNone: Trace(2, "No compression.\n"); break; case PLIFF85::cmpByteRun1: Trace(2, "Byte run encoding.\n"); break; default: raiseError(PL_ERRFORMAT_UNKNOWN, "Unknown compression method."); break; } readBitmapHeader = true; } else if (chunk.ckID == PLIFF85::ID_CMAP) { // The palette. PLCOMPILER_ASSERT(sizeof(PLIFF85::ColorRegister) == 3); numCMapElements = chunk.ckSize / 3; for (int i = 0; i < numCMapElements; ++i) { const PLIFF85::ColorRegister * pElement = reinterpret_cast<const PLIFF85::ColorRegister *> (pDataSrc->ReadNBytes(3)); m_pal[i].Set(pElement->red, pElement->green, pElement->blue, 0xFF); } readPalette = true; } else if (chunk.ckID == PLIFF85::ID_CAMG) { // The viewport mode. if (size_t(chunk.ckSize) != sizeof m_viewMode) { raiseError(PL_ERRFORMAT_UNKNOWN, "Unexpected CAMG size."); } m_viewMode = ReadMLong(pDataSrc); #if DETAILED_TRACE std::ostringstream strTrace; strTrace << "View mode " << std::hex << std::showbase << m_viewMode << ".\n"; Trace(2, strTrace.str().c_str()); #endif } else if (chunk.ckID == PLIFF85::ID_BODY) { bodySize = chunk.ckSize; foundBody = true; done = true; } else { // Some other chunk type - ignore it. pDataSrc->Skip(chunk.ckSize); } if (!done) { lumpIndex += chunk.ckSize; } if (lumpIndex >= totalSize - 1) { done = true; } } // We must have seen a header, cmap and body at this point. if (!readBitmapHeader) { raiseError(PL_ERRFORMAT_UNKNOWN, "Header not found."); } if ((!readPalette) && (m_bitmapHeader.nPlanes <= 8)) { raiseError(PL_ERRFORMAT_UNKNOWN, "Palette not found."); } if (!foundBody) { raiseError(PL_ERRFORMAT_UNKNOWN, "Body not found."); } // Check the body is the expected size ... if (m_bitmapHeader.compression == PLIFF85::cmpNone) { if (bodySize != getBytesPerRow() * m_bitmapHeader.h) { raiseError(PL_ERRFORMAT_UNKNOWN, "Unexpected body size."); } } // ... and that it does not extend beyond the end of the form. if (lumpIndex + bodySize > totalSize) { raiseError(PL_ERRFORMAT_UNKNOWN, "Body extends beyond form."); } // Too many CMAP entries probably indicates an error. const int maxExpectedCMapElements = int(((m_viewMode & PLIFF85::viewHAM) != 0) ? pow(2.0, m_bitmapHeader.nPlanes - 2) : pow(2.0, m_bitmapHeader.nPlanes)); if (numCMapElements > maxExpectedCMapElements) { raiseError(PL_ERRFORMAT_UNKNOWN, "Too many CMAP entries."); } PLPixelFormat pf; int DestBPP = m_bitmapHeader.nPlanes; bool bAlpha = (m_bitmapHeader.masking == PLIFF85::mskHasTransparentColor); if ((DestBPP > 8) || ((m_viewMode & PLIFF85::viewHAM) != 0) || (m_bitmapHeader.masking == PLIFF85::mskHasTransparentColor)) { if (bAlpha) { pf = PLPixelFormat::A8R8G8B8; } else { pf = PLPixelFormat::X8R8G8B8; } } else { pf = PLPixelFormat::I8; } SetBmpInfo(PLPoint(m_bitmapHeader.w, m_bitmapHeader.h), PLPoint(0, 0), pf); } // Open
void PLPPMDecoder::Open (PLDataSource *pDataSrc) { Trace (2, "Decoding PPM.\n"); readPpmHeader(&m_PPMHead, pDataSrc); SetBmpInfo(PLPoint(m_PPMHead.ImageWidth, m_PPMHead.ImageHeight), PLPoint (0,0), PLPixelFormat::X8R8G8B8); }