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

📄 gifwin.cpp

📁 giflib-4.1.6.tar.gz,最新的GIF 解码库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            // Map color based on pColorMap, uColors            long lClosest = 5;            for (UINT u = 0; u < uColors; ++u)            {                const long lDiff = ColorDiff(pColorMap[u].from, rgb);                if (lDiff < lClosest)                {                    lClosest = lDiff;                    rgb = pColorMap[u].to;                }            }            // Check for "solid" color flag (no pixel averaging)            if (rgb & 0xff000000)            {                return rgb;            }            red += GetRValue(rgb);            grn += GetGValue(rgb);            blu += GetBValue(rgb);        }        pSrcRow += dwSrcRowBytes;    }    // Return "average" pixel    return RGB(red / iPower, grn / iPower, blu / iPower);}// Copy (and resize) 24-bit Bitmap mapping colorsLOCAL void CopyBitmap24(LPBYTE pDstRow, LPBYTE pSrcRow, int width, int height, LPCOLORMAP pColorMap, UINT uColors, int iScale){    ASSERT( iScale > 0 );    const DWORD dwSrcRowBytes = DWORD_PAD(width * 3);    const DWORD dwDstRowBytes = DWORD_PAD(width / iScale * 3);    for (int row = 0; row < height; row += iScale)    {        LPBYTE pDst = pDstRow;        LPBYTE pSrc = pSrcRow + (row * dwSrcRowBytes);        for (int col = 0; col < width; col += iScale)        {            const COLORREF rgb = AvePixel(pSrc, dwSrcRowBytes, pColorMap, uColors, iScale);            *pDst++ = GetBValue(rgb);            *pDst++ = GetGValue(rgb);            *pDst++ = GetRValue(rgb);            pSrc += (iScale * 3);        }        pDstRow += dwDstRowBytes;    }}// Create a Device Independent Bitmap from current GIF image// Colorize bitmap to match Windows desktop colors// Returns NULL if error else handle to bitmapHBITMAP CGIFWin::CreateMappedBitmap(LPCOLORMAP pMap, UINT uCount, int iScale /*=1*/){    HBITMAP hBitmap = NULL;    ASSERT( m_pGifFile && m_pBits );    // Create memory device context compatible with current screen    HDC hDC = ::CreateCompatibleDC(NULL);    if (hDC)    {        // Create bitmap from current image state        LPVOID pBits = NULL;        BMI256 bmiSize = m_bmiDisplay;        if (iScale > 0)        {            bmiSize.bmi.bmiHeader.biWidth /= iScale;            bmiSize.bmi.bmiHeader.biHeight /= iScale;        }        hBitmap = ::CreateDIBSection(hDC, &bmiSize.bmi, DIB_RGB_COLORS, &pBits, /*handle=*/ NULL, /*offset=*/ 0L);        if (hBitmap && pBits)        {		    const int cxScreen =  m_pGifFile->SWidth;		    const int cyScreen = m_pGifFile->SHeight;            ASSERT( m_bmiDisplay.bmi.bmiHeader.biBitCount == 24 );            ::CopyBitmap24((LPBYTE) pBits, (LPBYTE) m_pBits, cxScreen, cyScreen, pMap, uCount, iScale);        }        VERIFY( ::DeleteDC(hDC) );    }    return hBitmap;}int CGIFWin::GetHeight(){	return m_pGifFile ? m_pGifFile->SHeight : 0;}int CGIFWin::GetWidth(){	return m_pGifFile ? m_pGifFile->SWidth : 0;}// Netscape 2.0 looping extension blockLOCAL GifByteType szNetscape20ext[] = "\x0bNETSCAPE2.0";#define NSEXT_LOOP      0x01        // Loop Count field code////  Appendix E. Interlaced Images.////  The rows of an Interlaced images are arranged in the following order://  //        Group 1 : Every 8th. row, starting with row 0.              (Pass 1)//        Group 2 : Every 8th. row, starting with row 4.              (Pass 2)//        Group 3 : Every 4th. row, starting with row 2.              (Pass 3)//        Group 4 : Every 2nd. row, starting with row 1.              (Pass 4)//  const int InterlacedOffset[] = { 0, 4, 2, 1 }; /* The way Interlaced image should. */const int InterlacedJumps[] = { 8, 8, 4, 2 };    /* be read - offsets and jumps... */////  The Following example illustrates how the rows of an interlaced image are//  ordered.//  //        Row Number                                        Interlace Pass//  //   0    -----------------------------------------       1//   1    -----------------------------------------                         4//   2    -----------------------------------------                   3//   3    -----------------------------------------                         4//   4    -----------------------------------------             2//   5    -----------------------------------------                         4//   6    -----------------------------------------                   3//   7    -----------------------------------------                         4//   8    -----------------------------------------       1//   9    -----------------------------------------                         4//   10   -----------------------------------------                   3//   11   -----------------------------------------                         4//   12   -----------------------------------------             2//   13   -----------------------------------------                         4//   14   -----------------------------------------                   3//   15   -----------------------------------------                         4//   16   -----------------------------------------       1//   17   -----------------------------------------                         4//   18   -----------------------------------------                   3//   19   -----------------------------------------                         4//// Fetch next image from GIF file// Returns delay in msec, 0 for end-of-file, negative for error)int CGIFWin::NextImage(){	// Error if no gif file!	if (!m_pGifFile)	{		return -1;	}	const int cxScreen =  m_pGifFile->SWidth;	const int cyScreen = m_pGifFile->SHeight;	//					 ___________	//		pBits1 ->	|			|	//					|	current	|	//					|	image	|	//					|___________|	//		pBits2 ->	|			|	//					|	next	|	//					|	image	|	//					|___________|	//		pLine ->	|___________|	//	const DWORD dwRowBytes = DWORD_PAD(cxScreen * 3);#define XYOFFSET(x,y)	((y) * dwRowBytes + (x) * 3)	const DWORD dwScreen = dwRowBytes * cyScreen;	LPBYTE pBits1 = m_pBits;	LPBYTE pBits2 = pBits1 + dwScreen;	GifPixelType *pLine = pBits2 + dwScreen;	GifRecordType RecordType;	GifByteType *pExtension;	int delay = 10;     // Default to 100 msec	int dispose = 0;	int transparent = GIF_NOT_TRANSPARENT;	do {		int i, ExtCode;		if (DGifGetRecordType(m_pGifFile, &RecordType) == GIF_ERROR) 		{			break;		}		switch (RecordType)		{		case IMAGE_DESC_RECORD_TYPE:			if (DGifGetImageDesc(m_pGifFile) != GIF_ERROR)			{				const int x = m_pGifFile->Image.Left;				const int y = m_pGifFile->Image.Top;				++m_iImageNum;				TRACE("\nImage #%d:\n\n\tImage Size - Left = %d, Top = %d, Width = %d, Height = %d.\n",					   m_iImageNum, x, y,					   m_pGifFile->Image.Width, m_pGifFile->Image.Height);				TRACE("\tImage is %s",					   m_pGifFile->Image.Interlace ? "Interlaced" :								"Non Interlaced");				if (m_pGifFile->Image.ColorMap != NULL)					TRACE(", BitsPerPixel = %d.\n",						m_pGifFile->Image.ColorMap->BitsPerPixel);				else					TRACE(".\n");				GifColorType* pColorTable;				if (m_pGifFile->Image.ColorMap == NULL)				{					TRACE("\tNo Image Color Map.\n");					// Copy global bitmap info for display					memcpy(&m_bmiDisplay, &m_bmiGlobal, sizeof(m_bmiDisplay));					pColorTable = m_pGifFile->SColorMap->Colors;				}				else				{					TRACE("\tImage Has Color Map.\n");					::InitBitmapInfo(&m_bmiDisplay.bmi, cxScreen, cyScreen);					::CopyColorMap(m_pGifFile->Image.ColorMap, &m_bmiDisplay.bmi);					pColorTable = m_pGifFile->Image.ColorMap->Colors;				}				// Always copy next -> current image				memcpy(pBits1, pBits2, dwScreen);				const int Width = m_pGifFile->Image.Width;				const int Height = m_pGifFile->Image.Height;				if (m_pGifFile->Image.Interlace)				{					// Need to perform 4 passes on the images:					for (int pass = 0; pass < 4; pass++)					{						for (i = InterlacedOffset[pass]; i < Height; i += InterlacedJumps[pass])						{							if (DGifGetLine(m_pGifFile, pLine, Width) == GIF_ERROR)							{								TRACE("DGifGetLine error=%d\n", GifLastError());								return -1;							}							CopyGIF(pBits1 + XYOFFSET(x, y + i), pLine, Width, transparent, pColorTable);						}					}				}				else				{					// Non-interlaced image					for (i = 0; i < Height; i++)					{						if (DGifGetLine(m_pGifFile, pLine, Width) == GIF_ERROR)						{							TRACE("DGifGetLine error=%d\n", GifLastError());							return -1;						}						CopyGIF(pBits1 + XYOFFSET(x, y + i), pLine, Width, transparent, pColorTable);					}				}				// Prepare second image with next starting				if (dispose == GIF_DISPOSE_BACKGND)				{					TRACE("*** GIF_DISPOSE_BACKGND ***\n");					const int x = m_pGifFile->Image.Left;					const int y = m_pGifFile->Image.Top;					const int Width = m_pGifFile->Image.Width;					const int Height = m_pGifFile->Image.Height;					// Clear next image to background index					// Note: if transparent restore to transparent color (else use GIF background color)					const COLORREF rgbFill = (transparent == GIF_NOT_TRANSPARENT) ? m_rgbBackgnd : m_rgbTransparent;					for (int i = 0; i < Height; ++i)						::FillGIF(pBits2 + XYOFFSET(x, y + i), rgbFill, Width);				}				else if (dispose != GIF_DISPOSE_RESTORE)				{					// Copy current -> next (Update)					memcpy(pBits2, pBits1, dwScreen);				}				dispose = 0;				TRACE("\tdelay = %d msec\n", delay * 10);				if (delay)				{					return delay * 10;				}			}			break;		case EXTENSION_RECORD_TYPE:        {			if (DGifGetExtension(m_pGifFile, &ExtCode, &pExtension) == GIF_ERROR)			{				TRACE("DGifGetExtension error=%d\n", GifLastError());				return -2;			}			TRACE("\n");            BOOL bNetscapeExt = FALSE;			switch (ExtCode)			{			case COMMENT_EXT_FUNC_CODE:				TRACE("GIF89 comment");				break;			case GRAPHICS_EXT_FUNC_CODE:			{				TRACE("GIF89 graphics control");				ASSERT( pExtension[0] == 4 );				// 				int flag = pExtension[1];				delay  = MAKEWORD(pExtension[2], pExtension[3]);				transparent = (flag & GIF_TRANSPARENT) ? pExtension[4] : GIF_NOT_TRANSPARENT;				dispose = (flag >> GIF_DISPOSE_SHIFT) & GIF_DISPOSE_MASK;				TRACE(" delay = %d, dispose = %d transparent = %d\n", delay, dispose, transparent);				break;			}			case PLAINTEXT_EXT_FUNC_CODE:				TRACE("GIF89 plaintext");				break;			case APPLICATION_EXT_FUNC_CODE:            {				TRACE("GIF89 application block\n");                ASSERT( pExtension );                if (memcmp(pExtension, szNetscape20ext, szNetscape20ext[0]) == 0)                {                    TRACE("Netscape 2.0 extension\n");                    bNetscapeExt = TRUE;                }				break;            }			default:				TRACE("pExtension record of unknown type");				break;			}			TRACE(" (Ext Code = %d):\n", ExtCode);			do			{				if (DGifGetExtensionNext(m_pGifFile, &pExtension) == GIF_ERROR)				{					TRACE("DGifGetExtensionNext error=%d\n", GifLastError());					return -3;				}                // Process Netscape 2.0 extension (GIF looping)                if (pExtension && bNetscapeExt)                {                    GifByteType bLength = pExtension[0];                    int iSubCode = pExtension[1] & 0x07;                    if (bLength == 3 && iSubCode == NSEXT_LOOP)                    {                        UINT uLoopCount = MAKEWORD(pExtension[2], pExtension[3]);                        m_uLoopCount = uLoopCount - 1;                        TRACE("Looping extension, uLoopCount=%u\n", m_uLoopCount);                    }                }			}			while (pExtension);			break;        }		case TERMINATE_RECORD_TYPE:			break;		default:		     // Should be trapped by DGifGetRecordType			break;		}	}	while (RecordType != TERMINATE_RECORD_TYPE);	return 0;}

⌨️ 快捷键说明

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