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

📄 gifwin.cpp

📁 giflib-4.1.6.tar.gz,最新的GIF 解码库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***********************************************************	File:	GifWin.cpp*	Title:	Graphics Interchange Format implementation**	Author:	Lennie Araki*	Date:	24-Nov-1999**	This class is a thin wrapper around the open source*	giflib-1.4.0 for opening, parsing and displaying*	Compuserve GIF files on Windows.**	The baseline code was derived from fragments extracted*	from the sample programs gif2rgb.c and giftext.c.*	Added support for local/global palettes, transparency*	and "dispose" methods to improve display compliance*	with GIF89a.**	Copyright (c) 1999 CallWave, Inc.*		CallWave, Inc.*		136 W. Canon Perdido Suite A*		Santa Barbara, CA 93101**	Licensed under the terms laid out in the libungif *	COPYING file.**********************************************************/#include "stdafx.h"#include <windowsx.h>#include "GifWin.h"extern "C"{    #include "gif_lib.h"}#define LOCAL	static////	Implements the GIF89a specification with the following omissions:////	Section 18. Logical Screen Descriptor://		Pixel Aspect Ratio is ignored - square pixels assumed (1:1)//	Section 23. Graphic Control Extension://		User Input Flag is ignored - could be added but not very useful//	Section 25. Plain Text Extension//		Not implemented - would require embedding fonts and text drawing//		code to be added//	Section 26. Application Extension//		Not implemented.  Note: this includes Netscape 2.0 looping//		extensions////   _______________________________//	|  reserved | disposal  |u_i| t |//	|___|___|___|___|___|___|___|___|//#define GIF_TRANSPARENT		0x01#define GIF_USER_INPUT		0x02#define GIF_DISPOSE_MASK	0x07#define GIF_DISPOSE_SHIFT	2#define GIF_NOT_TRANSPARENT	-1#define GIF_DISPOSE_NONE	0		// No disposal specified. The decoder is									// not required to take any action.#define GIF_DISPOSE_LEAVE	1		// Do not dispose. The graphic is to be left									// in place.#define GIF_DISPOSE_BACKGND	2		// Restore to background color. The area used by the									// graphic must be restored to the background color.#define GIF_DISPOSE_RESTORE	3		// Restore to previous. The decoder is required to									// restore the area overwritten by the graphic with									// what was there prior to rendering the graphic.// Initialize BITMAPINFO LOCAL void InitBitmapInfo(LPBITMAPINFO pBMI, int cx, int cy){    ::ZeroMemory(pBMI, sizeof(BITMAPINFOHEADER));    pBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);	pBMI->bmiHeader.biWidth = cx;	pBMI->bmiHeader.biHeight = -cy;     // negative for top-down bitmap	pBMI->bmiHeader.biPlanes = 1;	pBMI->bmiHeader.biBitCount = 24;   	pBMI->bmiHeader.biClrUsed = 256;}// Copy GIF ColorMap into Windows BITMAPINFOLOCAL void CopyColorMap(ColorMapObject* pColorMap, LPBITMAPINFO pBMI){	int iLen = pColorMap->ColorCount;	ASSERT( iLen <= 256 );	int iCount = min(iLen, 256);	for (int i = 0; i < iCount; i++)	{		BYTE red = pColorMap->Colors[i].Red;		BYTE green = pColorMap->Colors[i].Green;		BYTE blue = pColorMap->Colors[i].Blue;		TRACE("%3d: %02xh %02xh %02xh   ", i, red, green, blue);		pBMI->bmiColors[i].rgbRed = red;		pBMI->bmiColors[i].rgbGreen = green;		pBMI->bmiColors[i].rgbBlue = blue;		pBMI->bmiColors[i].rgbReserved = 0;		if (i % 4 == 3)			TRACE("\n");	}	TRACE("\n");}#define DWORD_PAD(x)		(((x) + 3) & ~3)// Copy bytes from source to destination  skipping transparent bytesLOCAL void CopyGIF(LPBYTE pDst, LPBYTE pSrc, int width, const int transparent, GifColorType* pColorTable){	ASSERT( pColorTable );	if (width)	{		do		{			BYTE b = *pSrc++;			if (b != transparent)			{				// Translate to 24-bit RGB value if not transparent				const GifColorType* pColor = pColorTable + b;				pDst[0] = pColor->Blue;				pDst[1] = pColor->Green;				pDst[2] = pColor->Red;			}			// Skip to next pixel			pDst += 3;		}		while (--width);	}}// Fix pixels in 24-bit GIF bufferLOCAL void FillGIF(LPBYTE pDst, const COLORREF rgb, int width){	if (width)	{		do		{			pDst[0] = GetBValue(rgb);			pDst[1] = GetGValue(rgb);			pDst[2] = GetRValue(rgb);			pDst += 3;		}		while (--width);	}}// Constructor/destructorCGIFWin::CGIFWin(){	m_pGifFile = NULL;	m_pBits = NULL;	// Clear bitmap information	::ZeroMemory(&m_bmiGlobal, sizeof(m_bmiGlobal));	::ZeroMemory(&m_bmiDisplay, sizeof(m_bmiDisplay));	//	// Per Section 11 of GIF spec:	// If no color table is available at all, the decoder is free to use a 	// system color table or a table of its own. In that case, the decoder 	// may use a color table with as many colors as its hardware is able 	// to support; it is recommended that such a table have black and	// white as its first two entries, so that monochrome images can be 	// rendered adequately.	//	const RGBQUAD rgbWhite = { 255, 255, 255, 0 };	const RGBQUAD rgbBlack = { 0, 0, 0, 0 };	m_bmiGlobal.bmi.bmiColors[0] = rgbBlack;	for (int i = 1; i < 256; ++i)	{		m_bmiGlobal.bmi.bmiColors[i] = rgbWhite;	}}CGIFWin::~CGIFWin(){	TRACE("*** CGIFWin destructor called ***\n");	Close();}// Open GIF file and allocate "screen" bufferint CGIFWin::Open(LPCTSTR pszGifFileName, COLORREF rgbTransparent){	m_rgbBackgnd = m_rgbTransparent = rgbTransparent;	// First close and delete previous GIF (if open)	Close();    m_pGifFile = ::DGifOpenFileName(pszGifFileName);	int iResult = -1;    if (m_pGifFile)    {		const int cxScreen =  m_pGifFile->SWidth;		const int cyScreen = m_pGifFile->SHeight;		TRACE("\n%s:\n\n\tScreen Size - Width = %d, Height = %d.\n", pszGifFileName, cxScreen, cyScreen);		TRACE("\tColorResolution = %d, BackGround = %d.\n", m_pGifFile->SColorResolution, m_pGifFile->SBackGroundColor);		// Allocate buffer big enough for 2 screens + 1 line		// Use 24-bit (3-bytes per pixel) to correctly handle local palettes		const DWORD dwRowBytes = DWORD_PAD(cxScreen * 3);		const DWORD dwScreen = dwRowBytes * cyScreen;		m_pBits = (LPBYTE) GlobalAllocPtr(GHND, dwScreen * 2 + dwRowBytes);		iResult = -2;		if (m_pBits)		{			// Fill in current and next image with background color			for (int y = 0; y < cyScreen * 2; ++y)			{				::FillGIF(m_pBits + y * dwRowBytes, rgbTransparent, cxScreen);			}			::InitBitmapInfo(&m_bmiGlobal.bmi, cxScreen, cyScreen);			if (m_pGifFile->SColorMap)			{				TRACE("\tGlobal Color Map:\n");				::CopyColorMap(m_pGifFile->SColorMap, &m_bmiGlobal.bmi);				GifColorType* pColor = m_pGifFile->SColorMap->Colors + m_pGifFile->SBackGroundColor;				m_rgbBackgnd = RGB(pColor->Red, pColor->Green, pColor->Blue);			}			iResult = 0;			m_iImageNum = 0;            m_uLoopCount = 0U;		}	}	return iResult;}// Close the GIF file and free resources allocated by libgifvoid CGIFWin::Close(){	// Close GIF file if opened	if (m_pGifFile)	{		int iError = DGifCloseFile(m_pGifFile);		if (iError == GIF_ERROR)		{			TRACE("DGifCloseFile error=%d\n", GifLastError());		}		m_pGifFile = NULL;	}	// Free memory if allocated	if (m_pBits)	{		GlobalFreePtr(m_pBits);		m_pBits = NULL;	}}////  Draw entire GIF to a Windows Device Context//      iFactor Percent Ratio//      -3      25%     (1:4)//      -2      33%     (1:3)//      -1      50%     (1:2)//       0      100%    (1:1)//       1      200%    (2:1)//       2      300%    (3:1)//       3      400%    (4:1)//int CGIFWin::Draw(HDC hDC, LPCRECT pRect, int iFactor /*=0*/){	int iResult = 0;	if (m_pGifFile && m_pBits)	{		const int Width =  m_pGifFile->SWidth;		const int Height = m_pGifFile->SHeight;        int zoomWidth = Width;        int zoomHeight = Height;        if (iFactor < 0)        {            zoomWidth /= (1 - iFactor);            zoomHeight /= (1 - iFactor);        }        else if (iFactor > 0)        {            zoomWidth *= (1 + iFactor);            zoomHeight *= (1 + iFactor);        }		int x, y;		if (pRect)		{			// Center image in rectangle			x = (pRect->right - pRect->left - zoomWidth) / 2 + pRect->left;			y = (pRect->bottom - pRect->top - zoomHeight) / 2 + pRect->top;		}		else		{			// Draw image at top-left			x = y = 0;		}		if (Width && Height)		{            if (iFactor < 0)            {                HBITMAP hBitmap = CreateMappedBitmap(NULL, 0, 1 - iFactor);                if (hBitmap)                {	                HDC hdcMem = ::CreateCompatibleDC(hDC);                    if (hdcMem)                    {	                    HBITMAP hOldBm = (HBITMAP) ::SelectObject(hdcMem, hBitmap);	                    // Blast bits from memory DC to target DC.	                    iResult = ::BitBlt(hDC, x, y, zoomWidth, zoomHeight, hdcMem, 0, 0, SRCCOPY);                        ::SelectObject(hdcMem, hOldBm);                        ::DeleteDC(hdcMem);                    }                    ::DeleteObject(hBitmap);                }            }            else // (iFactor >= 0)            {			    // Display bitmap on screen (-negative height to flip DIB upside down)			    iResult = ::StretchDIBits(hDC, x, y, zoomWidth, zoomHeight, 0, 0, Width, Height, m_pBits, &m_bmiDisplay.bmi, DIB_RGB_COLORS, SRCCOPY);            }		}	}	return iResult;}// Compute least squared color differenceLOCAL COLORREF ColorDiff(COLORREF rgb1, COLORREF rgb2){    // If matching color, replace with Windows color    const int rDiff = GetRValue(rgb1) - GetRValue(rgb2);    const int gDiff = GetGValue(rgb1) - GetGValue(rgb2);    const int bDiff = GetBValue(rgb1) - GetBValue(rgb2);    // Use least squared difference    const long lDiff = rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;    return lDiff;}LOCAL COLORREF AvePixel(LPBYTE pSrcRow, DWORD dwSrcRowBytes, LPCOLORMAP pColorMap, UINT uColors, int iScale){    const int iPower = iScale * iScale;    const int iPower2 = iPower / 2;    int red = iPower2;      // For rounding    int grn = iPower2;    int blu = iPower2;    for (int row = iScale; row > 0; --row)    {        LPBYTE pSrc = pSrcRow;        for (int col = iScale; col > 0; --col)        {            COLORREF rgb = RGB(pSrc[2], pSrc[1], pSrc[0]);            pSrc += 3;

⌨️ 快捷键说明

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