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

📄 dibdisplay.c

📁 傅立叶变换和小波变换是图像压缩的重要工具。该代大戏是利用小波变换进行图像压缩。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************************/
/*  DIBDisplay.C                                                                        */
/*                                                                                      */
/*  Author:  Mike Sandige                                                               */
/*  Description:  display surface manager for windows with a DIB as the frame buffer    */
/*                Code fragments contributed by John Miles                              */
/*                                                                                      */
/*  The contents of this file are subject to the Genesis3D Public License               */
/*  Version 1.0 (the "License"); you may not use this file except in                    */
/*  compliance with the License. You may obtain a copy of the License at                */
/*  http://www.genesis3d.com                                                            */
/*                                                                                      */
/*  Software distributed under the License is distributed on an "AS IS"                 */
/*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
/*  the License for the specific language governing rights and limitations              */
/*  under the License.                                                                  */
/*                                                                                      */
/*  The Original Code is Genesis3D, released March 25, 1999.                            */
/*  Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved           */
/*                                                                                      */
/****************************************************************************************/

#define WIN32_LEAN_AND_MEAN
#pragma warning(disable : 4201 4214 4115)
#include <windows.h>
#pragma warning(default : 4201 4214 4115; disable : 4514)

#include "DIBDisplay.h"
#include <assert.h>
#include <stdio.h>			// vsprintf()
#include <malloc.h>			// malloc(),free()
#include "errorlog.h"


static const char * DIBDISPLAY_DESCRIPTION_STRING = "Window DIB ";

typedef struct
{
   uint r;
   uint g;
   uint b;
   int alpha;
}
DIBDisplay_RGB32;


	// data needed for DIB section (and some cached info about bitmasks
typedef struct
{
	uint		DIB_R_bitmask;			// DIB high-color pixel format
	uint		DIB_G_bitmask;
	uint		DIB_B_bitmask;

	BITMAPINFO  *pbmi;					// BITMAPINFO structure
	HBITMAP		hDIB;					// Handle returned from CreateDIBSection

	ubyte		*lpDIBBuffer;			// DIB image buffer
} DIBDisplay_DIBInfo;	



typedef struct DIBDisplay 
{
	HWND				hWnd;					// Handle to application window
	bool			Locked;					// is display 'locked'
	int				BitsPerPixel;			// Mode info set by last call to 
	int				Pitch;					// (BitsPerPixel/8) * Size_X
	int				Size_X;					// size of window rounded up to the nearest multiple of 4
	int				Size_Y;
	uint				Flags;					// display flags (currently unused)
	DIBDisplay_DIBInfo	DIBInfo;
} DIBDisplay;


void DIBDisplay_GetDisplayFormat(	const DIBDisplay *D,
									int   *Width, 
									int   *Height,
									int   *BitsPerPixel,
									uint  *Flags)
{
	assert( D            != NULL );
	assert( Width        != NULL );
	assert( Height       != NULL );
	assert( BitsPerPixel != NULL );
	assert( Flags        != NULL );

	*Width        = D->Size_X;
	*Height       = D->Size_Y;
	*BitsPerPixel = D->BitsPerPixel;
	*Flags        = D->Flags;
}	


bool DIBDisplay_GetDisplayInfo(	char			*DescriptionString, 
										unsigned int	 DescriptionStringMaxLength,
										DisplayModeInfo *Info)
{
	int BitsPerPixel;

	assert( Info != NULL );
	assert( DescriptionString != NULL );
	assert( DescriptionStringMaxLength > 0 );
	if (strlen(DIBDISPLAY_DESCRIPTION_STRING) >= DescriptionStringMaxLength)
		{
			geErrorLog_AddString(GE_ERR_BAD_PARAMETER,"DIBDisplay_GetDescriptionString: description string too short",NULL);
			return false;
		}

	strcpy(DescriptionString,DIBDISPLAY_DESCRIPTION_STRING);

//	if ( CPUInfo_TestFor3DNow()==true)
//		BitsPerPixel = 32;
//	else
		BitsPerPixel = 16;

	if (DisplayModeInfo_AddEntry(Info,-1,-1,BitsPerPixel,0)==false)
		{
			geErrorLog_AddString(GE_ERR_SUBSYSTEM_FAILURE,"DIBDisplay_GetDescriptionString: unable to add mode entry",NULL);
			return false;
		}
	return true;
}


//------------------------------------------------
static void DIBDisplay_DebugPrintf(char *fmt, ...)
{
	static char work_string[4096];

	if ((fmt == NULL) || (strlen(fmt) > sizeof(work_string)))
		{
			strcpy(work_string, "(String missing or too large)");
		}
	else
		{
			va_list ap;

			va_start(ap,fmt);

			vsprintf(work_string, fmt, ap);

			va_end  (ap);
		}

	#if 0  // log to file
	{
		FILE       *log;
		log = fopen("DEBUG.LOG","a+t");

		if (log != NULL)
			{
				fprintf(log,"%s\n",work_string);
				fclose(log);
			}
	}
	#endif

	OutputDebugString(work_string);
}


//------------------------------------------------
#ifndef NDEBUG
static bool DIBDisplay_IsValid(const DIBDisplay *D)
{
	if (D == NULL)
		return false;

	if (D->DIBInfo.pbmi == NULL)
		return false;
	if (D->DIBInfo.hDIB == NULL)
		return false;
	if (D->DIBInfo.lpDIBBuffer == NULL)
		return false;

	return true;
}
#endif


//------------------------------------------------
static bool DIBDisplay_FindDesktopRGBMasks(	HDC		hdc,
								int	desktop_bpp,
								uint  *desktop_R_bitmask,
								uint	*desktop_G_bitmask,
								uint	*desktop_B_bitmask)
{
	assert( hdc != NULL );
	assert( desktop_R_bitmask != NULL );
	assert( desktop_G_bitmask != NULL );
	assert( desktop_B_bitmask != NULL );

	if(desktop_bpp > 8)
		{
			COLORREF		color,save;
			HBITMAP			TempBmp;
			OSVERSIONINFO	WinVer;

			memset(&WinVer, 0, sizeof(OSVERSIONINFO));
			WinVer.dwOSVersionInfoSize	=sizeof(OSVERSIONINFO);

			GetVersionEx(&WinVer);
			if(WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
				{
					TempBmp	=CreateCompatibleBitmap(hdc, 8, 8);
					if(TempBmp)
						{
							BITMAPINFO		*TempInfo;
							int HeaderSize =  sizeof(BITMAPINFO) + sizeof(RGBQUAD)*2;
							TempInfo = malloc(HeaderSize);
							if (TempInfo == NULL)
								{
									geErrorLog_Add(DIBDisplay_FindDesktopRGBMasks,"Failed to allocate header for NT mask test");
									DeleteObject(TempBmp);
									return false;
								}
							memset(TempInfo, 0, HeaderSize);
							TempInfo->bmiHeader.biSize		=sizeof(BITMAPINFO);
							TempInfo->bmiHeader.biBitCount	=(uint16)desktop_bpp;
							TempInfo->bmiHeader.biCompression	=BI_BITFIELDS;
							if(GetDIBits(hdc, TempBmp, 0, 0, NULL, TempInfo, DIB_RGB_COLORS))
								{
									*desktop_R_bitmask	=*((uint *)&TempInfo->bmiColors[0]);
									*desktop_G_bitmask	=*((uint *)&TempInfo->bmiColors[1]);
									*desktop_B_bitmask	=*((uint *)&TempInfo->bmiColors[2]);
									DIBDisplay_DebugPrintf("(%x-%x-%x)\n", *desktop_R_bitmask, *desktop_G_bitmask, *desktop_B_bitmask);
								}
							else
								{
									free(TempInfo);
									DeleteObject(TempBmp);
									geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks:  Unable to get bit format from desktop compatible bitmap",NULL);
									return false;
								}
							free(TempInfo);
							DeleteObject(TempBmp);
						}
					else
						{
							geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks:  Unable to create desktop compatible bitmap",NULL);
							return false;
						}
					// detect failure (Win2000 only?)
					if (((*desktop_R_bitmask | *desktop_G_bitmask | *desktop_B_bitmask)&0x7FFF) != 0x7FFF)
						{
							SetLastError(0);
							geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks:  GetDIBits didn't return proper masking information.",NULL);
							return false;
						}

				}
			else
				{
					HDC hdc2;
					
					hdc2 = CreateDC("Display", NULL, NULL,NULL);
					if (hdc2==NULL)
						{
							geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks: Unable to create compatible hdc",NULL);
							return false;
						}
						
					save = GetPixel(hdc2,0,0);
					if ( save == CLR_INVALID )
						{
							geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks:  Unable to get pixel from desktop",NULL);
							DeleteDC(hdc2);
							return false;
						}
							

					if (SetPixel(hdc2,0,0,RGB(0x08,0x08,0x08))==-1)
						{
							geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks: Unable to select bitmap",NULL);
							DeleteDC(hdc2);
							return false;
						}
					
					color = GetPixel(hdc2,0,0) & 0xffffff;
					if ( color == CLR_INVALID )
						{
							geErrorLog_AddString(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_FindDesktopRGBMasks:  Unable to get test pixel from desktop",NULL);
							DeleteDC(hdc2);
							return false;
						}

					SetPixel(hdc,0,0,save);		// ignore an error here.
					DeleteDC(hdc2);

					DIBDisplay_DebugPrintf("DIBDisplay: Desktop pixel format = 0x%X ",color);
					

					switch (color)
						{
							case 0x000000:						// 0x000000 = 5-5-5
								DIBDisplay_DebugPrintf("(5-5-5)\n");

								*desktop_R_bitmask = 0x007c00;
								*desktop_G_bitmask = 0x0003e0;
								*desktop_B_bitmask = 0x00001f;
								break;

							case 0x000800:						// 0x000800 = 5-6-5
    							DIBDisplay_DebugPrintf("(5-6-5)\n");

								*desktop_R_bitmask = 0x00f800;
								*desktop_G_bitmask = 0x0007e0;
								*desktop_B_bitmask = 0x00001f;
								break;
				
							case 0x080808:						// 0x080808 = 8-8-8
								DIBDisplay_DebugPrintf("(8-8-8)\n");

								*desktop_R_bitmask = 0xff0000;
								*desktop_G_bitmask = 0x00ff00;
								*desktop_B_bitmask = 0x0000ff;
								break;

							default:
								DIBDisplay_DebugPrintf("(Unsupported, using 5-6-5)\n");

								if ((desktop_bpp == 15) || (desktop_bpp == 16))
								   {
									   *desktop_R_bitmask = 0x00f800;
									   *desktop_G_bitmask = 0x0007e0;
									   *desktop_B_bitmask = 0x00001f;
									}
								else
									{
										geErrorLog_AddString(GE_ERR_DISPLAY_RESOURCE,"DIBDisplay_FindDesktopRGBMasks:  Unsupported desktop format.",NULL);
										return false;
									}
								break;
							}

				}
		}
	return true;
}



//------------------------------------------------
static void DIBDisplay_DestroyDIB(DIBDisplay_DIBInfo *DI)
{
	assert( DI != NULL );

	if (DI->pbmi != NULL)
		{
			free(DI->pbmi);
			DI->pbmi = NULL;
		}

	if (DI->hDIB != NULL)
		{
			DeleteObject(DI->hDIB);
			DI->hDIB = NULL;
		}
}

//------------------------------------------------
static bool DIBDisplay_CreateDIB( 
				int   display_size_X,
                int   display_size_Y,
                int   display_bpp,
				HWND    hWnd,
				DIBDisplay_DIBInfo *DI)
{
	HDC      hdc;
	BITMAPINFOHEADER *pbmih;              // Pointer to pbmi header
	uint		desktop_R_bitmask;        // Desktop high-color pixel format
	uint		desktop_G_bitmask;        
	uint		desktop_B_bitmask;
	int		desktop_bpp;              // Windows video mode BPP
	
	assert( display_size_X > 0 );
	assert( display_size_Y > 0 );
	assert( (display_bpp == 16) || (display_bpp == 24));
	assert( DI != NULL );

	DI->hDIB        = NULL;
	DI->lpDIBBuffer = NULL;

	DI->pbmi = (BITMAPINFO *) 
				malloc(sizeof (BITMAPINFOHEADER) + (sizeof (RGBQUAD) * 256));

	if (DI->pbmi == NULL)
		{
			geErrorLog_Add(GE_ERR_MEMORY_RESOURCE,"DIBDisplay_CreateDIB: failed to allocate bitmap header");
			return false;
		}

	memset(DI->pbmi, 0, sizeof (BITMAPINFOHEADER) + (sizeof (RGBQUAD) * 256));

	pbmih = &(DI->pbmi->bmiHeader);

	pbmih->biSize          =  sizeof(BITMAPINFOHEADER);
	pbmih->biWidth         =  display_size_X;
	pbmih->biHeight        = -(display_size_Y);
	pbmih->biPlanes        =  1;
	pbmih->biBitCount      =  (uint16) display_bpp;
	pbmih->biSizeImage     =  0;
	pbmih->biXPelsPerMeter =  0;
	pbmih->biYPelsPerMeter =  0;
	pbmih->biClrUsed       =  0;
	pbmih->biClrImportant  =  0;

	//
	// Get Windows desktop display format (and masks, in high-color modes)
	//

	hdc = GetDC(hWnd);
	if ( hdc == NULL )
		{
			geErrorLog_Add(GE_ERR_WINDOWS_API_FAILURE,"DIBDisplay_CreateDIB: unable to get desktop HDC");
			return false;
		}

	desktop_bpp = GetDeviceCaps(hdc, BITSPIXEL) * 
				  GetDeviceCaps(hdc, PLANES);

	DIBDisplay_DebugPrintf("DIBDisplay: Desktop %d BPP\n", desktop_bpp);

	if (DIBDisplay_FindDesktopRGBMasks( hdc,
										desktop_bpp,
										&desktop_R_bitmask,

⌨️ 快捷键说明

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