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

📄 pngscanlinedecoder.cpp

📁 symbian 开SDK例子!!3RD 是学习的不错实例啊
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// PNGSCANLINEDECODER.CPP
//
// Copyright (c) 1997-2002 Symbian Ltd.  All rights reserved.
//

#include "PNGCodec.h"

const TInt KPngScanlineFilterTypeLength = 1;

const TInt KColStart[KPngNumInterlacedPasses] = { 0, 4, 0, 2, 0, 1, 0, 0 };
const TInt KRowStart[KPngNumInterlacedPasses] = { 0, 0, 4, 0, 2, 0, 1, 0 };
const TInt KColIncrement[KPngNumInterlacedPasses] = { 8, 8, 4, 4, 2, 2, 1, 0 };
const TInt KRowIncrement[KPngNumInterlacedPasses] = { 8, 8, 8, 4, 4, 2, 2, 0 };
const TInt KBlockWidth[KPngNumInterlacedPasses] = { 8, 4, 4, 2, 2, 1, 1, 0 };
const TInt KBlockHeight[KPngNumInterlacedPasses] = { 8, 8, 4, 4, 2, 2, 1, 0 };

//
// These classes specialise the PNG reader to read
// scanlines with different bitmap depths/colour types
//

class CBitDepth1Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth2Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth4Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth8Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth8ColorType2Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth8ColorType4Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth8ColorType6Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth16ColorType0Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth16ColorType2Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth16ColorType4Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

class CBitDepth16ColorType6Decoder : public CPngReadSubCodec
	{
private:
	virtual void DoConstructL();
	virtual TInt ScanlineBufferSize(TInt aPixelLength);
	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
	};

//
// CPngReadSubCodec: base class for classes that read scanlines
//

// Factory function
CPngReadSubCodec* CPngReadSubCodec::NewL(CImageProcessor* aImageProc,CImageProcessor* aMaskProc,const TPngImageInformation& aInfo)
	{
	CPngReadSubCodec* self = NULL;

	switch (aInfo.iBitDepth)
		{
	case 1:
		self = new(ELeave) CBitDepth1Decoder;
		break;
	case 2:
		self = new(ELeave) CBitDepth2Decoder;
		break;
	case 4:
		self = new(ELeave) CBitDepth4Decoder;
		break;
	case 8:
		switch (aInfo.iColorType)
			{
		case TPngImageInformation::EGrayscale:
		case TPngImageInformation::EIndexedColor:
			self = new(ELeave) CBitDepth8Decoder;
			break;
		case TPngImageInformation::EDirectColor:
			self = new(ELeave) CBitDepth8ColorType2Decoder;
			break;
		case TPngImageInformation::EAlphaGrayscale:
			self = new(ELeave) CBitDepth8ColorType4Decoder;
			break;
		case TPngImageInformation::EAlphaDirectColor:
			self = new(ELeave) CBitDepth8ColorType6Decoder;
			break;
		default:
			User::Leave(KErrNotSupported);
			break;
			}
		break;
	case 16:
		switch (aInfo.iColorType)
			{
		case TPngImageInformation::EGrayscale:
			self = new(ELeave) CBitDepth16ColorType0Decoder;
			break;
		case TPngImageInformation::EDirectColor:
			self = new(ELeave) CBitDepth16ColorType2Decoder;
			break;
		case TPngImageInformation::EAlphaGrayscale:
			self = new(ELeave) CBitDepth16ColorType4Decoder;
			break;
		case TPngImageInformation::EAlphaDirectColor:
			self = new(ELeave) CBitDepth16ColorType6Decoder;
			break;
		case TPngImageInformation::EIndexedColor:
		default:
			User::Leave(KErrNotSupported);
			break;
			}
		break;
	default:
		User::Leave(KErrNotSupported);
		break;
		}

	CleanupStack::PushL(self);
	self->ConstructL(aImageProc,aMaskProc,aInfo);
	CleanupStack::Pop(); // self
	return self;
	}

CPngReadSubCodec::CPngReadSubCodec():
	iScanlineDes1(NULL,0),
	iScanlineDes2(NULL,0)
	{}

CPngReadSubCodec::~CPngReadSubCodec()
	{
	delete iScanlineBuffer1;
	delete iScanlineBuffer2;
	}

void CPngReadSubCodec::ConstructL(CImageProcessor* aImageProc,CImageProcessor* aMaskProc,const TPngImageInformation& aInfo)
	{
	iImageProc = aImageProc;
	iMaskProc = aMaskProc;
	iInfo = aInfo;
	iScanlineBufferSize = ScanlineBufferSize(iInfo.iSize.iWidth);

	DoConstructL();

	iScanlineBuffer1 = HBufC8::NewMaxL(iScanlineBufferSize);
	iScanlineBuffer2 = HBufC8::NewMaxL(iScanlineBufferSize);

	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
		{
		iInterlacedScanlineBufferSize[0] = ScanlineBufferSize((iInfo.iSize.iWidth + 7) >> 3);
		iInterlacedScanlineBufferSize[1] = ScanlineBufferSize((iInfo.iSize.iWidth + 3) >> 3);
		iInterlacedScanlineBufferSize[2] = ScanlineBufferSize((iInfo.iSize.iWidth + 3) >> 2);
		iInterlacedScanlineBufferSize[3] = ScanlineBufferSize((iInfo.iSize.iWidth + 1) >> 2);
		iInterlacedScanlineBufferSize[4] = ScanlineBufferSize((iInfo.iSize.iWidth + 1) >> 1);
		iInterlacedScanlineBufferSize[5] = ScanlineBufferSize(iInfo.iSize.iWidth >> 1);
		iInterlacedScanlineBufferSize[6] = iScanlineBufferSize;
		iInterlacedScanlineBufferSize[7] = 0;
		iPass = 0;

		iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]);
		iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]);
		}
	else
		{
		iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iScanlineBufferSize,iScanlineBufferSize);
		iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iScanlineBufferSize,iScanlineBufferSize);
		}
	}

TDes8& CPngReadSubCodec::FirstBuffer()
	{
	iScanlineDes1.FillZ();
	iCurrentScanlineBuffer = 2;
	return iScanlineDes2;
	}

TDes8& CPngReadSubCodec::DecodeL()
	{
	TUint8* dataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes1[1] : &iScanlineDes2[1];
	const TUint8* dataPtrLimit = dataPtr + iScanlineDes1.Length() - 1;

	FilterScanlineDataL(dataPtr,dataPtrLimit);
	DoDecode(dataPtr,dataPtrLimit);
	UpdatePos();

	if (iCurrentScanlineBuffer == 1)
		{
		iCurrentScanlineBuffer = 2;
		return iScanlineDes2;
		}
	else
		{
		iCurrentScanlineBuffer = 1;
		return iScanlineDes1;
		}
	}

void CPngReadSubCodec::FilterScanlineDataL(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
	{
	TInt filterType = (iCurrentScanlineBuffer == 1) ? iScanlineDes1[0] : iScanlineDes2[0];

	switch (filterType)
		{
	case 0: // None
		break;
	case 1: // Sub
		{
		aDataPtr += iBytesPerPixel;

		while (aDataPtr < aDataPtrLimit)
			{
			aDataPtr[0] = TUint8(aDataPtr[0] + aDataPtr[-iBytesPerPixel]);
			aDataPtr++;
			}
		}
		break;
	case 2: // Up
		{
		TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1];

		while (aDataPtr < aDataPtrLimit)
			*aDataPtr++ = TUint8(*aDataPtr + *altDataPtr++);
		}
		break;
	case 3: // Average
		{
		const TUint8* tempDataPtrLimit = Min<const TUint8*>(aDataPtr + iBytesPerPixel,aDataPtrLimit);
		TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1];

		while (aDataPtr < tempDataPtrLimit)
			{
			aDataPtr[0] = TUint8(aDataPtr[0] + (altDataPtr[0] / 2));
			aDataPtr++;
			altDataPtr++;
			}

		while (aDataPtr < aDataPtrLimit)
			{
			aDataPtr[0] = TUint8(aDataPtr[0] + ((altDataPtr[0] + aDataPtr[-iBytesPerPixel]) / 2));
			aDataPtr++;
			altDataPtr++;
			}
		}
		break;
	case 4: // Paeth
		{
		const TUint8* tempDataPtrLimit = Min<const TUint8*>(aDataPtr + iBytesPerPixel,aDataPtrLimit);
		TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1];

		while (aDataPtr < tempDataPtrLimit)
			{
			aDataPtr[0] = TUint8(aDataPtr[0] + altDataPtr[0]);
			aDataPtr++;
			altDataPtr++;
			}

		while (aDataPtr < aDataPtrLimit)
			{
			aDataPtr[0] = TUint8(aDataPtr[0] + PaethPredictor(aDataPtr[-iBytesPerPixel],altDataPtr[0],altDataPtr[-iBytesPerPixel]));
			aDataPtr++;
			altDataPtr++;
			}
		}
		break;
	default: // Error
		User::Leave(KErrCorrupt);
		break;
		}
	}

TInt CPngReadSubCodec::PaethPredictor(TInt aLeft,TInt aAbove,TInt aAboveLeft)
	{
	TInt p = aLeft + aAbove - aAboveLeft;
	TInt pa = Abs(p - aLeft);
	TInt pb = Abs(p - aAbove);
	TInt pc = Abs(p - aAboveLeft);

	if (pa <= pb && pa <= pc)
		return aLeft;
	else if (pb <= pc)
		return aAbove;
	else
		return aAboveLeft;
	}

void CPngReadSubCodec::WritePixel(TRgb aPixelColor)
	{
	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
		{
		const TInt width = Min(KBlockWidth[iPass],iInfo.iSize.iWidth - iPos.iX);
		const TInt endY = Min(iPos.iY + KBlockHeight[iPass],iInfo.iSize.iHeight);

		TPoint pos(iPos);

		while (pos.iY < endY)
			{
			iImageProc->SetPos(pos);

			for (TInt col = 0; col < width; col++)
				iImageProc->SetPixel(aPixelColor);

			pos.iY++;
			}

		iPos.iX += KColIncrement[iPass];
		}
	else
		iImageProc->SetPixel(aPixelColor);
	}

void CPngReadSubCodec::WritePixel(TRgb aPixelColor,TUint8 aAlphaValue)
	{
	ASSERT(iMaskProc);

	TRgb maskColor(TRgb::Gray256(aAlphaValue));

	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
		{
		iImageProc->SetPos(iPos);
		iMaskProc->SetPos(iPos);
		iImageProc->SetPixel(aPixelColor);
		iMaskProc->SetPixel(maskColor);

		iPos.iX += KColIncrement[iPass];
		}
	else
		{
		iImageProc->SetPixel(aPixelColor);
		iMaskProc->SetPixel(maskColor);
		}
	}

void CPngReadSubCodec::UpdatePos()
	{
	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
		{
		ASSERT(iPass <= 7);

		iPos.iX = KColStart[iPass];
		iPos.iY += KRowIncrement[iPass];

		while (iPos.iX >= iInfo.iSize.iWidth || iPos.iY >= iInfo.iSize.iHeight)
			{
			iPass++;
			iPos.iX = KColStart[iPass];
			iPos.iY = KRowStart[iPass];
			iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[iPass],iInterlacedScanlineBufferSize[iPass]);
			iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[iPass],iInterlacedScanlineBufferSize[iPass]);
			iScanlineDes1.FillZ();
			iScanlineDes2.FillZ();
			}
		}
	}

//
// CBitDepth1Decoder: specialised reader for 1bpp scanlines
//
void CBitDepth1Decoder::DoConstructL()
	{
	if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed))
		{ // Set up palette to be grayscale values
		iInfo.iPalette[0] = KRgbBlack;
		iInfo.iPalette[1] = KRgbWhite;


		if (iInfo.iTransparencyPresent)
			{
			if (iInfo.iTransparentGray <= 1)
				iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0;
			}
		}

	// Replicate values to avoid shifts when decoding
	iInfo.iPalette[2] = iInfo.iPalette[1];
	iInfo.iPalette[4] = iInfo.iPalette[1];
	iInfo.iPalette[8] = iInfo.iPalette[1];
	iInfo.iPalette[16] = iInfo.iPalette[1];
	iInfo.iPalette[32] = iInfo.iPalette[1];
	iInfo.iPalette[64] = iInfo.iPalette[1];
	iInfo.iPalette[128] = iInfo.iPalette[1];

	if (iInfo.iTransparencyPresent && iInfo.iTransparencyValue[1] != 255)
		{
		iInfo.iTransparencyValue[2] = iInfo.iTransparencyValue[1];
		iInfo.iTransparencyValue[4] = iInfo.iTransparencyValue[1];
		iInfo.iTransparencyValue[8] = iInfo.iTransparencyValue[1];
		iInfo.iTransparencyValue[16] = iInfo.iTransparencyValue[1];
		iInfo.iTransparencyValue[32] = iInfo.iTransparencyValue[1];
		iInfo.iTransparencyValue[64] = iInfo.iTransparencyValue[1];
		iInfo.iTransparencyValue[128] = iInfo.iTransparencyValue[1];
		}

	iBytesPerPixel = 1;
	if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace)
		{
		TInt pixelPadding = ((iInfo.iSize.iWidth + 7) & ~7) - iInfo.iSize.iWidth;
		iImageProc->SetPixelPadding(pixelPadding);
		if (iMaskProc)
			iMaskProc->SetPixelPadding(pixelPadding);
		}
	}

TInt CBitDepth1Decoder::ScanlineBufferSize(TInt aPixelLength)
	{
	return ((aPixelLength + 7) / 8) + KPngScanlineFilterTypeLength;
	}

void CBitDepth1Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
	{
	if (iMaskProc && iInfo.iTransparencyPresent)
		{
		while (aDataPtr < aDataPtrLimit)
			{
			TInt dataValue = *aDataPtr++;

⌨️ 快捷键说明

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