⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pngcodec.cpp

📁 symbian 开SDK例子!!3RD 是学习的不错实例啊
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			User::Leave(KErrCorrupt);

		Mem::Copy(iImageInfo.iTransparencyValue,aDataPtr,aChunkLength);
		}
	else if (iImageInfo.iColorType == TPngImageInformation::EGrayscale) // 0
		{
		if (aChunkLength < 2)
			User::Leave(KErrCorrupt);

		iImageInfo.iTransparentGray = TUint16((aDataPtr[0] << 8) | aDataPtr[1]);
		}
	else if (iImageInfo.iColorType == TPngImageInformation::EDirectColor) // 2
		{
		if (aChunkLength < 6)
			User::Leave(KErrCorrupt);

		iImageInfo.iTransparentRed = TUint16((aDataPtr[0] << 8) | aDataPtr[1]);
		iImageInfo.iTransparentGreen = TUint16((aDataPtr[2] << 8) | aDataPtr[3]);
		iImageInfo.iTransparentBlue = TUint16((aDataPtr[4] << 8) | aDataPtr[5]);
		}
	}

// Process a PNG image data
void CPngReadCodec::DoProcessDataL(const TUint8*& aDataPtr,const TUint8* aDataPtrLimit)
	{
	// Data is passed to the decompressor
	TInt bytesToProcess = Min(aDataPtrLimit - aDataPtr,iChunkBytesRemaining);
	iDataDes.Set(aDataPtr,bytesToProcess);
	iDecompressor->SetInput(iDataDes);

	while (iDecompressor->AvailIn() > 0)
		iDecompressor->InflateL();

	aDataPtr += bytesToProcess;
	iChunkBytesRemaining -= bytesToProcess;
	}

// From MEZBufferManager: manage decompressor stream
void CPngReadCodec::InitializeL(CEZZStream& aZStream)
	{
	aZStream.SetOutput(iDecoder->FirstBuffer());
	}

void CPngReadCodec::NeedInputL(CEZZStream& /*aZStream*/)
	{
	}

void CPngReadCodec::NeedOutputL(CEZZStream& aZStream)
	{
	aZStream.SetOutput(iDecoder->DecodeL());
	}

void CPngReadCodec::FinalizeL(CEZZStream& /*aZStream*/)
	{
	iDecoder->DecodeL();
	}



//
// CPngWriteCodec: writes a PNG image
//


CPngWriteCodec::CPngWriteCodec(TInt aBpp, TBool aColor, TBool aPaletted, TInt aCompressionLevel)
	: iCompressionLevel(aCompressionLevel), iCompressorPtr(NULL, 0)
	{
	// Set bpp
	iImageInfo.iBitsPerPixel = aBpp;
	switch (aBpp)
		{
		case 1:
			iImageInfo.iBitDepth = 1;
			break;
		case 2:
			iImageInfo.iBitDepth = 2;
			break;
		case 4:
			iImageInfo.iBitDepth = 4;
			break;
		case 8:
		case 24:
			iImageInfo.iBitDepth = 8;
			break;
		default:
			break;
		}

	// Set color type
	if (aColor && aPaletted)
		iImageInfo.iColorType = TPngImageInformation::EIndexedColor;
	else if (aColor)
		iImageInfo.iColorType = TPngImageInformation::EDirectColor;
	else
		iImageInfo.iColorType = TPngImageInformation::EGrayscale;
	}

CPngWriteCodec::~CPngWriteCodec()
	{
	delete iCompressor;
	delete iEncoder;
	}

// Called by framework at start of conversion operation
void CPngWriteCodec::InitFrameL(TBufPtr8& aDst, const CFbsBitmap& aSource)
	{
	if (aDst.Length() == 0)
		User::Leave(KErrArgument);	// Not enough length for anything

	SetSource(&aSource);
	iDestStartPtr = const_cast<TUint8*>(aDst.Ptr());
	iDestPtr = iDestStartPtr;
	iDestPtrLimit = iDestPtr + aDst.MaxLength();

	// Set image information
	const SEpocBitmapHeader& header = aSource.Header();
	iImageInfo.iSize = header.iSizeInPixels;

	switch (iImageInfo.iBitDepth)
		{
		case 1:
		case 2:
		case 4:
			if (iImageInfo.iColorType == TPngImageInformation::EDirectColor)
				{
				// Bit depths 1, 2 and 4 don't support RGB colour (color mode 2)
				// Must use paletted colour or greyscale
				User::Leave(KErrNotSupported);
				break;
				}
			// fall through to case 8
		case 8:
			break;
		default:
			User::Leave(KErrNotSupported);	// unsupported bit depth
			break;
		}

	iImageInfo.iCompressionMethod = TPngImageInformation::EDeflateInflate32K;
	iImageInfo.iFilterMethod = TPngImageInformation::EAdaptiveFiltering;
	iImageInfo.iInterlaceMethod = TPngImageInformation::ENoInterlace;

	// Create encoder
	if (iEncoder)
		{
		delete iEncoder;
		iEncoder = NULL;
		}
	iEncoder = CPngWriteSubCodec::NewL(iImageInfo, &aSource);

	// Create compressor
	if (iCompressor)
		{
		delete iCompressor;
		iCompressor = NULL;
		}
	iCompressor = CEZCompressor::NewL(*this, iCompressionLevel);

	// Initial encoder state
	if (iImageInfo.iColorType == TPngImageInformation::EIndexedColor)
		iEncoderState = EPngWritePLTE;	
	else
		iEncoderState = EPngDeflate;
	iCallAgain = ETrue;		// to make sure we call DeflateL

	// Write header
	User::LeaveIfError(WriteHeaderChunk(aDst));
	}

// Called by the framework to process frame data
TFrameState CPngWriteCodec::ProcessFrameL(TBufPtr8& aDst)
	{
	if (aDst.Length() == 0)
		User::Leave(KErrArgument);	// Not enough length for anything

	TFrameState state = EFrameIncomplete;
	iDestStartPtr = const_cast<TUint8*>(aDst.Ptr());
	iDestPtr = iDestStartPtr;
	iDestPtrLimit = iDestPtr + aDst.MaxLength();

	// Set return buffer length to 0 initially
	aDst.SetLength(0);

	while (aDst.Length() == 0 && state != EFrameComplete)
		{
		// Loop round until we have some data to return or
		// the image is encoded
		switch (iEncoderState)
			{
			case EPngWritePLTE:
				WritePLTEChunk(aDst);
				break;
			case EPngDeflate:
				DeflateEncodedDataL(aDst, state);
				break;
			case EPngWriteIDAT:
				WriteIDATChunk(aDst);
				break;
			case EPngFlush:
				FlushCompressedDataL(aDst, state);
				break;
			case EPngEndChunk:
				WriteEndChunk(aDst);
				state = EFrameComplete;
				break;
			default:
				break;
			}
		}

	return state;
	}

// Write a compressed image data chunk
void CPngWriteCodec::DeflateEncodedDataL(TBufPtr8& aDst, TFrameState& /*aState*/)
	{
	// Set ptr for compressed data
	const TInt dataLength = aDst.MaxLength() - KPngChunkLengthSize - KPngChunkIdSize - KPngChunkCRCSize;
	ASSERT(dataLength > 0);
	iCompressorPtr.Set(iDestPtr + KPngChunkIdSize + KPngChunkLengthSize, dataLength, dataLength);

	// Initialise input/output for compressor
	iCompressor->SetInput(iEncoder->EncodeL(iScanline));
	iScanline++;
	iCompressor->SetOutput(iCompressorPtr);

	while ((iEncoderState == EPngDeflate) && iCallAgain)
		iCallAgain = iCompressor->DeflateL();

	// Write the IDAT chunk
	WriteIDATChunk(aDst);
	iEncoderState = EPngFlush;
	}

void CPngWriteCodec::FlushCompressedDataL(TBufPtr8& aDst, TFrameState& /*aState*/)
	{
	if (iCallAgain)
		{
		iCallAgain = iCompressor->DeflateL();
		WriteIDATChunk(aDst);
		}
	else
		{
		iEncoderState = EPngEndChunk;
		}
	}

// Write a PLTE chunk
void CPngWriteCodec::WritePLTEChunk(TBufPtr8& aDst)
	{
	ASSERT(iEncoder->Palette() &&
		   (iImageInfo.iColorType == TPngImageInformation::EIndexedColor ||
		    iImageInfo.iColorType == TPngImageInformation::EDirectColor ||
		    iImageInfo.iColorType == TPngImageInformation::EAlphaDirectColor));	// allowed color types for PLTE chunk

	// Get palette entries
	CPalette* palette = iEncoder->Palette();
	ASSERT(palette);
	const TInt count = palette->Entries();
	TUint8* ptr = iDestPtr + KPngChunkIdSize + KPngChunkLengthSize;
	TInt length = count * 3;
	TPtr8 data(ptr, length, length);
	for (TInt i=0; i < count; i++)
		{
		TRgb rgb = palette->GetEntry(i);
		*ptr = TUint8(rgb.Red());
		ptr++;
		*ptr = TUint8(rgb.Green());
		ptr++;
		*ptr = TUint8(rgb.Blue());
		ptr++;
		}
	// Write PLTE chunk
	WritePngChunk(iDestPtr, KPngPLTEChunkId, data, length);
	ASSERT(length % 3 == 0);	// length must be divisible by 3
	aDst.SetLength(length);
	iEncoderState = EPngDeflate;
	}

// Write a data chunk
void CPngWriteCodec::WriteIDATChunk(TBufPtr8& aDst)
	{
	TPtrC8 ptr(iCompressor->OutputDescriptor());
	if (ptr.Length())
		{
		TInt length = 0;
		WritePngChunk(iDestPtr, KPngIDATChunkId, ptr, length);
		aDst.SetLength(length);

		// New output can write to the same compressor ptr
		iCompressor->SetOutput(iCompressorPtr);
		}

	if (iCallAgain)
		iEncoderState = EPngFlush;
	}

// Write an END chunk
void CPngWriteCodec::WriteEndChunk(TBufPtr8& aDst)
	{
	// Write IEND chunk
	TInt length = 0;
	WritePngChunk(iDestPtr, KPngIENDChunkId, KNullDesC8, length);
	aDst.SetLength(length);
	}

// Write a header chunk
TInt CPngWriteCodec::WriteHeaderChunk(TBufPtr8& aDst)
	{
	// Write signature
	Mem::Copy(iDestPtr, &KPngSignature[0], KPngFileSignatureLength);
	iDestPtr += KPngFileSignatureLength;

	// Write IHDR chunk
	TBuf8<KPngIHDRChunkSize> buffer;
	TUint8* ptr = const_cast<TUint8*>(buffer.Ptr());
	// Set length of data
	buffer.SetLength(KPngIHDRChunkSize);
	// Chunk data
	// width (4 bytes)
	if ((iImageInfo.iSize.iWidth == 0) ||
		(static_cast<TUint>(iImageInfo.iSize.iWidth) > KPngMaxImageSize))
		{
		return KErrArgument;	// invalid width
		}
	PtrWriteUtil::WriteBigEndianInt32(ptr, iImageInfo.iSize.iWidth);
	ptr += 4;
	// height (4 bytes)
	if ((iImageInfo.iSize.iHeight == 0) ||
		(static_cast<TUint>(iImageInfo.iSize.iHeight) > KPngMaxImageSize))
		{
		return KErrArgument;	// invalid height
		}
	PtrWriteUtil::WriteBigEndianInt32(ptr, iImageInfo.iSize.iHeight);
	ptr += 4;
	// bit depth (1 byte)
	PtrWriteUtil::WriteInt8(ptr, iImageInfo.iBitDepth);
	ptr++;
	// colour type (1 byte)
	PtrWriteUtil::WriteInt8(ptr, iImageInfo.iColorType);
	ptr++;
	// compression method (1 byte)
	PtrWriteUtil::WriteInt8(ptr, iImageInfo.iCompressionMethod);
	ptr++;
	// filter method (1 byte)
	PtrWriteUtil::WriteInt8(ptr, iImageInfo.iFilterMethod);
	ptr++;
	// interlace method (1 byte)
	PtrWriteUtil::WriteInt8(ptr, iImageInfo.iInterlaceMethod);
	ptr++;

	TInt length = 0;
	WritePngChunk(iDestPtr, KPngIHDRChunkId, buffer, length);
	aDst.SetLength(KPngFileSignatureLength + length);

	return KErrNone;
	}

// Chunk writing helper function
void CPngWriteCodec::WritePngChunk(TUint8*& aDestPtr, const TDesC8& aChunkId, const TDesC8& aData, TInt& aLength)
	{
	// Chunk length (4 bytes)
	PtrWriteUtil::WriteBigEndianInt32(aDestPtr, aData.Length());
	aDestPtr += KPngChunkLengthSize;
	TUint8* crcPtr = aDestPtr;	// start position for calculating CRC
	// Chunk type (4 bytes)
	Mem::Copy(aDestPtr, aChunkId.Ptr(), KPngChunkIdSize);
	aDestPtr += KPngChunkIdSize;
	// Chunk data (0...n bytes)
	Mem::Copy(aDestPtr, aData.Ptr(), aData.Length());
	aDestPtr += aData.Length();
	// CRC (4 bytes)
	TUint32 crc = KPngCrcMask;
	GetCrc(crc, crcPtr, KPngChunkIdSize + aData.Length());
	crc ^= KPngCrcMask;
	PtrWriteUtil::WriteBigEndianInt32(aDestPtr, crc);
	aDestPtr += KPngChunkCRCSize;
	// Length of chunk
	aLength = KPngChunkLengthSize + KPngChunkIdSize + aData.Length() + KPngChunkCRCSize;
	}

// from MEZBufferManager, manage data compressor
void CPngWriteCodec::InitializeL(CEZZStream& /*aZStream*/)
	{
	}

void CPngWriteCodec::NeedInputL(CEZZStream& aZStream)
	{
	// Give compressor more data from encoder
	aZStream.SetInput(iEncoder->EncodeL(iScanline));
	if (iCompressor->AvailIn() != 0)
		iScanline++;
	}

void CPngWriteCodec::NeedOutputL(CEZZStream& /*aZStream*/)
	{
	// Signal to write an IDAT chunk
	iEncoderState = EPngWriteIDAT;
	}

void CPngWriteCodec::FinalizeL(CEZZStream& /*aZStream*/)
	{
	}

// Calculate CRC for PNG chunks
void CPngWriteCodec::GetCrc(TUint32& aCrc, const TUint8* aPtr, const TInt aLength)
	{
	if (!iCrcTableCalculated)
		CalcCrcTable();
	TUint32 code = aCrc;
	for (TInt i=0; i < aLength; i++)
		code = iCrcTable[(code ^ aPtr[i]) & 0xff] ^ (code >> 8);
	aCrc = code;
	}

void CPngWriteCodec::CalcCrcTable()
	{
	for (TInt i=0; i < KPngCrcTableLength; i++)
		{
		TUint32 code = static_cast<TUint32>(i);

		for (TInt j = 0; j < 8; j++)
			{
			if (code & 1)
				code = 0xedb88320 ^ (code >> 1);
			else
				code = code >> 1;
			}
		iCrcTable[i] = code;
		}
	iCrcTableCalculated = ETrue;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -