Пример #1
0
void ZDCPixmapEncoder_JPEGLib::Imp_Write(const ZStreamW& iStream,
	const void* iBaseAddress,
	const ZDCPixmapNS::RasterDesc& iRasterDesc,
	const ZDCPixmapNS::PixelDesc& iPixelDesc,
	const ZRect& iBounds)
	{
	jpeg_compress_struct theJCS;
	JPEGErrorMgr theEM;
	theJCS.err = &theEM;
	::jpeg_create_compress(&theJCS);

	theJCS.image_width = iBounds.Width();
	theJCS.image_height = iBounds.Height();

	JPEGWriter theJW(iStream);
	theJCS.dest = &theJW;

	vector<uint8> rowBufferVector;
	try
		{
		ZDCPixmapNS::PixvalDesc destPixvalDesc;
		ZDCPixmapNS::PixelDesc destPixelDesc;

		ZRef<ZDCPixmapNS::PixelDescRep> thePixelDescRep = iPixelDesc.GetRep();

		if (ZDCPixmapNS::PixelDescRep_Gray* thePixelDescRep_Gray
			= ZRefDynamicCast<ZDCPixmapNS::PixelDescRep_Gray>(thePixelDescRep))
			{
			theJCS.input_components = 1;
			theJCS.in_color_space = JCS_GRAYSCALE;
			rowBufferVector.resize(iBounds.Width());

			destPixelDesc = ZDCPixmapNS::PixelDesc(ZDCPixmapNS::eFormatStandard_Gray_8);
			destPixvalDesc.fDepth = 8;
			destPixvalDesc.fBigEndian = true;
			}
		else
			{
			theJCS.input_components = 3;
			theJCS.in_color_space = JCS_RGB;
			rowBufferVector.resize(3 * iBounds.Width());

			destPixelDesc = ZDCPixmapNS::PixelDesc(ZDCPixmapNS::eFormatStandard_RGB_24);
			destPixvalDesc.fDepth = 24;
			destPixvalDesc.fBigEndian = true;
			}

		::jpeg_set_defaults(&theJCS);
		::jpeg_set_quality(&theJCS, fQuality, TRUE);
		theJCS.dct_method = JDCT_FASTEST;

		::jpeg_start_compress(&theJCS, TRUE);

		JSAMPROW rowPtr[1];
		rowPtr[0] = &rowBufferVector[0];
		for (size_t y = iBounds.top; y < iBounds.bottom; ++y)
			{
			const void* sourceRowAddress = iRasterDesc.CalcRowAddress(iBaseAddress, y);

			ZDCPixmapNS::sBlitRow(
				sourceRowAddress, iRasterDesc.fPixvalDesc, iPixelDesc, iBounds.left,
				rowPtr[0], destPixvalDesc, destPixelDesc, 0,
				iBounds.Width());

			::jpeg_write_scanlines(&theJCS, rowPtr, 1);
			}

		::jpeg_finish_compress(&theJCS);
		}
	catch (...)
		{
		::jpeg_destroy(reinterpret_cast<j_common_ptr>(&theJCS));
		throw;
		}

	::jpeg_destroy(reinterpret_cast<j_common_ptr>(&theJCS));
	}
Пример #2
0
void ZDCPixmapEncoder_GIF::Imp_Write(const ZStreamW& iStream,
	const void* iBaseAddress,
	const ZDCPixmapNS::RasterDesc& iRasterDesc,
	const ZDCPixmapNS::PixelDesc& iPixelDesc,
	const ZRect& iBounds)
	{
	ZRef<ZDCPixmapNS::PixelDescRep_Indexed> thePixelDescRep_Indexed
		= ZRefDynamicCast<ZDCPixmapNS::PixelDescRep_Indexed>(iPixelDesc.GetRep());
	ZAssertStop(2, thePixelDescRep_Indexed);

	if (fTransparent)
		iStream.WriteString("GIF89a");
	else
		iStream.WriteString("GIF87a");
	iStream.WriteUInt16LE(iBounds.Width());
	iStream.WriteUInt16LE(iBounds.Height());

	uint8 globalStrmFlags = 0;
	globalStrmFlags |= 0x80; // hasGlobalColorTable
	globalStrmFlags |= 0x70; // colorResolution (8 bits per component)
	// globalStrmFlags |= 0x08; // set this if the color table is sorted in priority order

	ZAssertStop(2, iRasterDesc.fPixvalDesc.fDepth > 0 && iRasterDesc.fPixvalDesc.fDepth <= 8);
	
	globalStrmFlags |= iRasterDesc.fPixvalDesc.fDepth - 1; // globalColorTableSize & depth
	iStream.WriteUInt8(globalStrmFlags);

	iStream.WriteUInt8(0); // backgroundColorIndex
	iStream.WriteUInt8(0); // Pixel aspect ratio -- 0 == none specified.

	const ZRGBColorPOD* theColors;
	size_t theColorsCount;
	thePixelDescRep_Indexed->GetColors(theColors, theColorsCount);
	sWriteColorTable(iStream, theColors, theColorsCount, 1 << iRasterDesc.fPixvalDesc.fDepth);

	if (fTransparent)
		{
		iStream.WriteUInt8('!'); // Extension block
		iStream.WriteUInt8(0xF9); // Graphic Control Extension
		iStream.WriteUInt8(4); // Block size
		// The next byte encodes four fields:
		// 3 bits, Reserved == 0
		// 3 bits, Disposal Method == none (0),
		// 1 bit, User Input Flag == none (0)
		// 1 bit, Transparent Color Flag = yes (1)
		iStream.WriteUInt8(1);
		iStream.WriteUInt16LE(0); // Delay time
		iStream.WriteUInt8(fTransparentPixval);
		iStream.WriteUInt8(0); // Block terminator
		}

	iStream.WriteUInt8(','); // Start of image
	iStream.WriteUInt16LE(0); // Origin h
	iStream.WriteUInt16LE(0); // Origin v
	iStream.WriteUInt16LE(iBounds.Width());
	iStream.WriteUInt16LE(iBounds.Height());

	uint8 localStrmFlags = 0;
//	localStrmFlags |= 0x80; // hasLocalColorTable
	if (fInterlace)
		localStrmFlags |= 0x40; // interlaced
//	localStrmFlags |= 0x20; // sorted
//	localStrmFlags |= 0x70; // localColorTableSize
	iStream.WriteUInt8(localStrmFlags);

	iStream.WriteUInt8(iRasterDesc.fPixvalDesc.fDepth); // Initial code size.

	{ // Scope theSC.
	StreamW_Chunk theSC(iStream);

	ZStreamW_LZWEncode* theSLZW = nil;
	ZStreamW_LZWEncodeNoPatent* theSLZWNP = nil;

	ZStreamW* theStream;
	if (fNoPatent)
		{
		theSLZWNP = new ZStreamW_LZWEncodeNoPatent(iRasterDesc.fPixvalDesc.fDepth, theSC);
		theStream = theSLZWNP;
		}
	else
		{
		theSLZW = new ZStreamW_LZWEncode(iRasterDesc.fPixvalDesc.fDepth, theSC);
		theStream = theSLZW;
		}

	ZDCPixmapNS::PixvalDesc destPixvalDesc(8, true);

	vector<uint8> theRowBufferVector(iBounds.Width());
	void* theRowBuffer = &theRowBufferVector[0];

	try
		{
		if (fInterlace)
			{
			for (int pass = 0; pass < 4; ++pass)
				{
				for (ZCoord currentY = iBounds.top + sInterlaceStart[pass];
					currentY < iBounds.bottom; currentY += sInterlaceIncrement[pass])
					{
					const void* sourceRowAddress
						= iRasterDesc.CalcRowAddress(iBaseAddress, currentY);

					ZDCPixmapNS::sBlitRowPixvals(
						sourceRowAddress, iRasterDesc.fPixvalDesc, iBounds.left,
						theRowBuffer, destPixvalDesc, 0,
						iBounds.Width());

					theStream->Write(theRowBuffer, iBounds.Width());
					}
				}
			}
		else
			{
			for (ZCoord currentY = iBounds.top; currentY < iBounds.bottom; ++currentY)
				{
				const void* sourceRowAddress
					= iRasterDesc.CalcRowAddress(iBaseAddress, currentY);

				ZDCPixmapNS::sBlitRowPixvals(
					sourceRowAddress, iRasterDesc.fPixvalDesc, iBounds.left,
					theRowBuffer, destPixvalDesc, 0,
					iBounds.Width());
				theStream->Write(theRowBuffer, iBounds.Width());
				}
			}
		}
	catch (...)
		{
		delete theSLZW;
		delete theSLZWNP;
		throw;
		}

	delete theSLZW;
	delete theSLZWNP;
	}

	iStream.WriteUInt8(';'); // Trailer.
	}
Пример #3
0
static void sUnpackFromStream(const ZStreamR& inStream,
	ZCoord inSourceWidth, ZCoord inSourceHeight,
	unsigned short inSourceRowBytes, short inSourcePixelSize,
	const ZRGBColorPOD* inSourceColors, size_t inSourceColorTableSize,
	void* inDestBaseAddress,
	const ZDCPixmapNS::RasterDesc& inDestRasterDesc,
	const ZDCPixmapNS::PixelDesc& inDestPixelDesc)
	{
	// We're only supporting indexed pixels right now
	ZAssert(inSourcePixelSize == 1 || inSourcePixelSize == 2
		|| inSourcePixelSize == 4 || inSourcePixelSize == 8);

	ZDCPixmapNS::PixelDesc sourcePixelDesc(inSourceColors, inSourceColorTableSize);
	ZDCPixmapNS::PixvalDesc sourcePixvalDesc(inSourcePixelSize, true);

	if (inSourceRowBytes < 8)
		{
		// ah-ha!  The bits aren't actually packed. This will be easy.
		uint8 lineBuffer[8];
		for (ZCoord theScanLine = 0; theScanLine < inSourceHeight; ++theScanLine)
			{
			inStream.Read(lineBuffer, inSourceRowBytes);
			void* destRowAddress = inDestRasterDesc.CalcRowAddress(inDestBaseAddress, theScanLine);
			ZDCPixmapNS::sBlitRow(lineBuffer, sourcePixvalDesc, sourcePixelDesc, 0,
				destRowAddress, inDestRasterDesc.fPixvalDesc, inDestPixelDesc, 0,
				inSourceWidth);
			}
		}
	else
		{
		// Sometimes we get rows with length > rowBytes.  Allocate some extra for slop.
		// Also note that the data is stored as multiples of rowBytes, which may represent more
		// pixels than inSourceWidth (if inSourceWidth % 4 != 0). So we have to check for
		// destinationH < inSourceWidth before we actually blit to the destination.
		vector<uint8> lineBufferVector(inSourceRowBytes + 80);
		uint8* lineBuffer = &lineBufferVector[0];
		ZDCPixmapNS::PixvalAccessor destAccessor(inDestRasterDesc.fPixvalDesc);
		for (ZCoord theScanLine = 0; theScanLine < inSourceHeight; ++theScanLine)
			{
			void* destRowAddress = inDestRasterDesc.CalcRowAddress(inDestBaseAddress, theScanLine);

			size_t lineLen;
			if (inSourceRowBytes > 250 || inSourcePixelSize > 8)
				lineLen = inStream.ReadUInt16();
			else
				lineLen = inStream.ReadUInt8();
			if (lineLen > inSourceRowBytes + 80)
				::sThrowBadFormat();
			inStream.Read(lineBuffer, lineLen);

			ZCoord destinationH = 0;
			for (size_t j = 0; j < lineLen; /*no increment*/)
				{
				if (lineBuffer[j] & 0x80)
					{
					size_t repeatCount = (lineBuffer[j++] ^ 0xFF) + 2;
					ZRGBColorPOD theRGBColor;
					sourcePixelDesc.AsRGBColor(lineBuffer[j++], theRGBColor);
					uint32 destPixval = inDestPixelDesc.AsPixval(theRGBColor);
					for (size_t k = 0; k < repeatCount; ++k)
						{
						if (destinationH < inSourceWidth)
							destAccessor.SetPixval(destRowAddress, destinationH, destPixval);
						destinationH += 1;
						}
					}
				else
					{
					size_t realLength = lineBuffer[j] + 1;
					if (inSourceWidth > destinationH)
						{
						size_t countToCopy = min(realLength, size_t(inSourceWidth - destinationH));
						ZDCPixmapNS::sBlitRow(lineBuffer,
							sourcePixvalDesc, sourcePixelDesc, j + 1,
							destRowAddress,
							inDestRasterDesc.fPixvalDesc, inDestPixelDesc, destinationH,
							countToCopy);
						destinationH += countToCopy;
						}
					j += realLength + 1;
					}
				}
			}
		}
	}