Exemplo n.º 1
0
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;
		}
	}
Exemplo n.º 2
0
ZStreamerRPos_PageBuffered::ZStreamerRPos_PageBuffered(
	size_t iBufferCount, size_t iBufferSize, ZRef<ZStreamerRPos> iStreamerSource)
:	fStreamerSource(iStreamerSource),
	fStream(iBufferCount, iBufferSize, iStreamerSource->GetStreamRPos())
	{}