ZDCPixmap ZDCPixmap_Asset_BMP::sGetPixmap(const ZAsset& iAsset) { if (!iAsset) return ZDCPixmap(); // Get the data loaded before we call OpenRPos -- if the asset is file-based // then it will create a memory based streamer if the data is already loaded. const void* theData; size_t theSize; iAsset.GetData(&theData, & theSize); ZRef<ZStreamerRPos> theStreamer = iAsset.OpenRPos(); if (!theStreamer) return ZDCPixmap(); const ZStreamRPos& theStream = theStreamer->GetStreamRPos(); // Parse the header uint16 bfType = theStream.ReadUInt16LE(); if (bfType != 0x4D42) throw runtime_error("ZDCPixmap_Asset_BMP::sGetPixmap, invalid BMP file"); // Ignore bfSize, bfReserved1 and bfReserved2. theStream.Skip(8); size_t bfOffBits = theStream.ReadUInt32LE() - 54; uint32 biSize = theStream.ReadUInt32LE(); if (biSize != 0x28) throw runtime_error("ZDCPixmap_Asset_BMP::sGetPixmap, invalid BMP file"); int32 biWidth = theStream.ReadUInt32LE(); int32 biHeight = theStream.ReadUInt32LE(); uint16 biPlanes = theStream.ReadUInt16LE(); // We only handle single planes ZAssertStop(0, biPlanes == 1); uint16 biBitCount = theStream.ReadUInt16LE(); uint32 biCompression = theStream.ReadUInt32LE(); // Ignore biSizeImage, biXPelsPerMeter and biYPelsPerMeter. theStream.Skip(12); uint32 biClrUsed = theStream.ReadUInt32LE(); /*uint32 biClrImportant =*/ theStream.ReadUInt32LE(); bool sourceFlipped = true; if (biHeight < 0) { sourceFlipped = false; biHeight = -biHeight; } if (biClrUsed == 0) { if (biBitCount <= 8) biClrUsed = 1 << biBitCount; } // Read in the color table, if any vector<ZRGBColorPOD> localColorVector; if (biClrUsed > 0) { localColorVector.resize(biClrUsed); const uint8* theColors = static_cast<const uint8*>(theData) + theStream.GetPosition(); theStream.Skip(biClrUsed * 4); for (size_t x = 0; x < biClrUsed; ++x) { ZRGBColorPOD& theColor = localColorVector[x]; theColor.blue = (*theColors++) * 0x101; theColor.green = (*theColors++) * 0x101; theColor.red = (*theColors++) * 0x101; ++theColors; // Ignore rgbReserved theColor.alpha = 0xFFFFU; } } // If we're coming from a BMP file bfOffBits (the munged version) will be non zero, // and might tell us that the pixels are actually at some different offset than // immediately after the color table if (bfOffBits) theStream.Skip(bfOffBits - (biClrUsed * 4)); if (biCompression == BI_RGB) { // Uncompressed pixel data can be used as is -- we just have to set up an // appropriate RasterDesc and PixelDesc, and pass a PixmapRaster_Asset to // ZDCPixmap's constructor. When the raster is no longer in use by the pixmap // (or anyone else) the ZAsset's destructor will be called and the underlying // asset rep will be one step closer to being released. ZDCPixmapNS::RasterDesc theRasterDesc; theRasterDesc.fPixvalDesc.fDepth = biBitCount; theRasterDesc.fPixvalDesc.fBigEndian = true; theRasterDesc.fRowBytes = ((biWidth * biBitCount + 31) / 32) * 4; theRasterDesc.fRowCount = biHeight; theRasterDesc.fFlipped = sourceFlipped; ZDCPixmapNS::PixelDesc thePixelDesc; switch (biBitCount) { case 1: case 4: case 8: { thePixelDesc = ZDCPixmapNS::PixelDesc(&localColorVector[0], localColorVector.size()); break; } case 16: { thePixelDesc = ZDCPixmapNS::PixelDesc(0x7C00, 0x03E0, 0x001F, 0); theRasterDesc.fPixvalDesc.fBigEndian = false; break; } case 24: { thePixelDesc = ZDCPixmapNS::PixelDesc(0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000); break; } case 32: { thePixelDesc = ZDCPixmapNS::PixelDesc(0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000); break; } } ZRef<ZDCPixmapRaster> theRaster = new PixmapRaster_Asset(iAsset, static_cast<const char*>(theData) + theStream.GetPosition(), theRasterDesc); return ZDCPixmap(new ZDCPixmapRep(theRaster, ZRect(biWidth, biHeight), thePixelDesc)); } else { // We've got RLE data and so can't use the pixel data as is -- it has // to be expanded into a real raster. ZAssertStop(2, biBitCount == 1 || biBitCount == 4 || biBitCount == 8); ZDCPixmapNS::RasterDesc sourceRasterDesc; sourceRasterDesc.fPixvalDesc.fDepth = biBitCount; sourceRasterDesc.fPixvalDesc.fBigEndian = true; sourceRasterDesc.fRowBytes = ((biWidth * biBitCount + 31) / 32) * 4; sourceRasterDesc.fRowCount = biHeight; sourceRasterDesc.fFlipped = false; ZDCPixmapNS::PixelDesc sourcePixelDesc(&localColorVector[0], localColorVector.size()); ZDCPixmap thePixmap(sourceRasterDesc, ZPoint(biWidth, biHeight), sourcePixelDesc); if (biCompression == BI_RLE8) { thePixmap.GetRaster()->Fill(0); bool destFlipped = (thePixmap.GetRasterDesc().fFlipped); ::sReadRLE8(theStream, biWidth, biHeight, sourceRasterDesc.fRowBytes, sourceFlipped != destFlipped, reinterpret_cast<uint8*>(thePixmap.GetRaster()->GetBaseAddress())); } else { ZAssertStop(2, biCompression == BI_RLE4); thePixmap.GetRaster()->Fill(0); bool destFlipped = (thePixmap.GetRasterDesc().fFlipped); ::sReadRLE4(theStream, biWidth, biHeight, sourceRasterDesc.fRowBytes, destFlipped, reinterpret_cast<uint8*>(thePixmap.GetRaster()->GetBaseAddress())); } return thePixmap; } }
ZStreamerRPos_PageBuffered::ZStreamerRPos_PageBuffered( size_t iBufferCount, size_t iBufferSize, ZRef<ZStreamerRPos> iStreamerSource) : fStreamerSource(iStreamerSource), fStream(iBufferCount, iBufferSize, iStreamerSource->GetStreamRPos()) {}