📄 gvwdib.cpp
字号:
/* Copyright (C) 2000, Ghostgum Software Pty Ltd. All rights reserved.
This file is part of GSview.
This program is distributed with NO WARRANTY OF ANY KIND. No author
or distributor accepts any responsibility for the consequences of using it,
or for whether it serves any particular purpose or works at all, unless he
or she says so in writing. Refer to the GSview Free Public Licence
(the "Licence") for full details.
Every copy of GSview must include a copy of the Licence, normally in a
plain ASCII text file named LICENCE. The Licence grants you the right
to copy, modify and redistribute GSview, but only under certain conditions
described in the Licence. Among other things, the Licence requires that
the copyright notice and this notice be preserved on all copies.
*/
// DIB.cpp: implementation of the CDIB class.
// To change this back to using MFC:
// Replace GFile with CFile
// Exception handling around CFile::Read
// CDC not HDC
// delete palette, brush etc, not DeleteObject
#define STRICT
#include <windows.h>
#include <windowsx.h>
extern "C" {
#include "gvcfile.h"
}
#include "gvwdib.h"
#ifdef NOTUSED
#include "stdafx.h"
#include "afxmt.h"
//#include "GSview.h"
#include "DIB.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#endif
// This code assumes that structures elements are PACKED
// on byte boundaries.
static unsigned long dsc_arch = 0x00000001; // to determine if we are little endian
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDIB::CDIB(void)
{
m_palette = NULL;
m_bitmap = NULL;
m_colors = NULL;
m_bits = NULL;
m_valid = FALSE;
}
CDIB::~CDIB(void)
{
CleanupAll();
}
DWORD
CDIB::GetDword(LPBYTE pbyte)
{
if (m_little_endian)
return (*(LPDWORD)pbyte);
else
return ( pbyte[0] | (pbyte[1]<<8) | (pbyte[2]<<16) | (pbyte[3]<<24) );
}
WORD
CDIB::GetWord(LPBYTE pbyte)
{
if (m_little_endian)
return (*(LPWORD)pbyte);
else
return (WORD)( pbyte[0] | (pbyte[1]<<8) );
}
void
CDIB::Draw(HDC hdc)
{
Draw(hdc, 0, 0);
}
void CDIB::Draw(HDC hdc, int xOffset, int yOffset)
{
if (!m_valid) {
RECT rect;
GetClipBox(hdc, &rect);
FillRect(hdc, &rect, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
return;
}
Lock();
ASSERT(m_valid);
int palcount = PalCount();
UINT fuColorUse = DIB_RGB_COLORS;
DWORD caps = GetDeviceCaps(hdc, RASTERCAPS);
if (!(caps & RC_STRETCHDIB)) {
LPTSTR message = TEXT("Device doesn't support StretchDIBits");
TextOut(hdc, 10, 10, message, lstrlen(message));
Unlock();
return;
}
if (caps & RC_PALETTE) {
// palette device
if ((palcount != 0) && m_palette) {
// bitmap has palette, so use it
fuColorUse = DIB_PAL_COLORS;
}
}
if (fuColorUse == DIB_PAL_COLORS) {
// device and bitmap both use a palette
// create a special bitmap header with palette indices
struct bmi_s {
BITMAPINFOHEADER h;
WORD pal_index[256];
} bmi;
HPALETTE old_palette;
int i;
bmi.h.biSize = sizeof(bmi.h);
bmi.h.biWidth = m_bmp.bmp2.biWidth;
bmi.h.biHeight = m_bmp.bmp2.biHeight;
bmi.h.biPlanes = 1;
bmi.h.biBitCount = m_bmp.bmp2.biBitCount;
bmi.h.biCompression = 0;
bmi.h.biSizeImage = 0; /* default */
bmi.h.biXPelsPerMeter = 0; /* default */
bmi.h.biYPelsPerMeter = 0; /* default */
bmi.h.biClrUsed = palcount;
bmi.h.biClrImportant = palcount;
for (i = 0; i < palcount; i++)
bmi.pal_index[i] = (WORD)i;
old_palette = SelectPalette(hdc, m_palette, FALSE);
RealizePalette(hdc);
SetStretchBltMode(hdc, COLORONCOLOR);
StretchDIBits(hdc, xOffset, yOffset,
m_bmp.bmp2.biWidth, m_bmp.bmp2.biHeight,
0, 0, m_bmp.bmp2.biWidth, m_bmp.bmp2.biHeight,
m_bits, (BITMAPINFO *)&bmi, fuColorUse, SRCCOPY);
SelectPalette(hdc, old_palette, FALSE);
}
else {
// either device doesn't use palettes
// or bitmap does use a colour table
SetStretchBltMode(hdc, COLORONCOLOR);
// may need to modify target dimensions to allow print preview to work.
// At present, preview should work if bitmap is at printer resolution.
StretchDIBits(hdc, xOffset, yOffset,
m_bmp.bmp2.biWidth, m_bmp.bmp2.biHeight,
0, 0, m_bmp.bmp2.biWidth, m_bmp.bmp2.biHeight,
m_bits, (BITMAPINFO *)&m_bmp, fuColorUse, SRCCOPY);
}
Unlock();
}
#ifdef NOTUSED
#ifdef _DEBUG
void CDIB::Dump(CDumpContext& dc) const
{
dc << "DIB:\n";
dc << " HeaderSize " << m_bmp.bmp2.biSize << "\n";
dc << " Width " << m_bmp.bmp2.biWidth << "\n";
dc << " Height " << m_bmp.bmp2.biHeight << "\n";
dc << " Planes " << m_bmp.bmp2.biPlanes << "\n";
dc << " BitCount " << m_bmp.bmp2.biBitCount << "\n";
dc << " SizeImage " << m_bmp.bmp2.biSizeImage << "\n";
dc << " XDPI " << m_bmp.bmp2.biXPelsPerMeter << "\n";
dc << " YDPI " << m_bmp.bmp2.biYPelsPerMeter << "\n";
dc << " ClrUsed " << m_bmp.bmp2.biClrUsed << "\n";
dc << " ClrImportant " << m_bmp.bmp2.biClrImportant << "\n";
}
#endif
#endif
void
CDIB::DrawDump(HDC hdc)
{
TEXTMETRIC tm;
LOGFONT lf;
HFONT font;
int cyHeight;
int cxLeftMargin;
int x, y;
TCHAR str[256];
Lock();
memset(&lf, 0, sizeof(lf));
lf.lfHeight = 8;
lstrcpy(lf.lfFaceName, TEXT("MS Sans Serif"));
font = CreateFontIndirect(&lf);
SelectObject(hdc, font);
GetTextMetrics(hdc, &tm);
cyHeight = tm.tmHeight + tm.tmExternalLeading;
cxLeftMargin = tm.tmAveCharWidth * 2;
x = cxLeftMargin;
y = cyHeight;
wsprintf(str,
TEXT("HeaderSize=%d Width=%d Height=%d Planes=%d BitCount=%d"),
m_bmp.bmp2.biSize, m_bmp.bmp2.biWidth, m_bmp.bmp2.biHeight,
(int)m_bmp.bmp2.biPlanes, (int)m_bmp.bmp2.biBitCount);
TextOut(hdc,x, y, str, lstrlen(str));
y+= cyHeight;
wsprintf(str,
TEXT("SizeImage=%d XDPI=%d YDPI=%d ClrUsed=%d ClrImportant=%d"),
m_bmp.bmp2.biSizeImage,
m_bmp.bmp2.biXPelsPerMeter, m_bmp.bmp2.biYPelsPerMeter,
m_bmp.bmp2.biClrUsed, m_bmp.bmp2.biClrImportant);
TextOut(hdc, x, y, str, lstrlen(str));
Unlock();
}
BOOL
CDIB::MakePalette(void)
{
// Make a palette if needed
int i;
int pcount = PalCount();
LPLOGPALETTE logpalette;
LPBYTE p = m_colors;
if (m_palette) {
DeletePalette(m_palette);
m_palette = NULL;
}
if (pcount == 0)
return TRUE;
logpalette = new LOGPALETTE[pcount];
logpalette->palVersion = 0x300;
logpalette->palNumEntries = (WORD)pcount;
for (i = 0; i < pcount; i++) {
m_bmp.rgb4[i].rgbReserved = logpalette->palPalEntry[i].peFlags = 0;
m_bmp.rgb4[i].rgbBlue = logpalette->palPalEntry[i].peBlue = *p++;
m_bmp.rgb4[i].rgbGreen = logpalette->palPalEntry[i].peGreen = *p++;
m_bmp.rgb4[i].rgbRed = logpalette->palPalEntry[i].peRed = *p++;
if (!m_old)
p++;
}
m_palette = CreatePalette(logpalette);
delete [] logpalette;
return (m_palette != NULL);
}
void CDIB::CleanupPalette(void)
{
if (m_palette) {
DeletePalette(m_palette);
m_palette = NULL;
m_valid = FALSE;
}
}
void CDIB::CleanupBitmap(void)
{
if (m_bitmap) {
HGLOBAL hglobal = GlobalHandle(m_bitmap);
GlobalUnlock(hglobal);
GlobalFree(hglobal);
m_bitmap = NULL;
m_valid = FALSE;
}
}
void CDIB::CleanupAll(void)
{
m_valid = FALSE;
CleanupPalette();
CleanupBitmap();
}
void CDIB::Release(void)
{
Lock();
CleanupAll();
Unlock();
}
void CDIB::Init(void)
{
Lock();
CleanupAll();
Unlock();
}
BOOL CDIB::Init(HGLOBAL hglobal)
{
Lock();
CleanupAll();
// We are now responsible for freeing this memory
m_bitmap = (LPBYTE)GlobalLock(hglobal);
BOOL flag = Init(m_bitmap);
Unlock();
return flag;
}
BOOL
CDIB::Init(LPBYTE pbmp, LPBYTE pbits)
{
Lock();
BOOL flag = Init(pbmp);
m_bits = pbits;
Unlock();
return flag;
}
BOOL
CDIB::Init(LPBYTE pbmp)
{
Lock();
CleanupPalette();
m_little_endian = (*((char *)(&dsc_arch))) == 1;
m_bmp.bmp2.biSize = GetDword(pbmp);
pbmp += 4;
if (m_bmp.bmp2.biSize > 12) {
// new bitmap
m_old = FALSE;
m_bmp.bmp2.biWidth = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biHeight = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biPlanes = GetWord(pbmp);
pbmp += 2;
m_bmp.bmp2.biBitCount = GetWord(pbmp);
pbmp += 2;
m_bmp.bmp2.biCompression = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biSizeImage = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biXPelsPerMeter = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biYPelsPerMeter = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biClrUsed = GetDword(pbmp);
pbmp += 4;
m_bmp.bmp2.biClrImportant = GetDword(pbmp);
pbmp += 4;
m_bytewidth = (( m_bmp.bmp2.biWidth * m_bmp.bmp2.biBitCount + 31)
& ~31) >> 3;
m_colors = pbmp;
pbmp += PalLength();
m_bits = pbmp;
}
else {
// old bitmap
m_old = TRUE;
m_bmp.bmp2.biWidth = GetWord(pbmp);
pbmp += 2;
m_bmp.bmp2.biHeight = GetWord(pbmp);
pbmp += 2;
m_bmp.bmp2.biPlanes = GetWord(pbmp);
pbmp += 2;
m_bmp.bmp2.biBitCount = GetWord(pbmp);
pbmp += 2;
m_bmp.bmp2.biCompression = 0;
m_bmp.bmp2.biSizeImage = 0;
m_bmp.bmp2.biXPelsPerMeter = 72;
m_bmp.bmp2.biYPelsPerMeter = 72;
m_bmp.bmp2.biClrUsed = 0;
m_bmp.bmp2.biClrImportant = 0;
m_bytewidth = (( m_bmp.bmp2.biWidth * m_bmp.bmp2.biBitCount + 31)
& ~31) >> 3;
m_colors = pbmp;
pbmp += PalLength();
m_bits = pbmp;
}
m_valid = MakePalette();
Unlock();
return m_valid;
}
/* number of colours in colour table */
UINT
CDIB::PalCount(void)
{
if (m_old) {
// old bitmap
if (m_bmp.bmp2.biBitCount == 24)
return 0;
return 1 << (m_bmp.bmp2.biBitCount * m_bmp.bmp2.biPlanes);
}
// new bitmap
switch (m_bmp.bmp2.biBitCount) {
case 16:
case 24:
case 32:
return 0;
case 1:
case 4:
case 8:
return (m_bmp.bmp2.biClrUsed > 0 ? (UINT)m_bmp.bmp2.biClrUsed :
1 << (m_bmp.bmp2.biBitCount * m_bmp.bmp2.biPlanes));
}
// unsupported bitmap format
return 0; // should throw an exception
}
// length of colour table in bytes
UINT
CDIB::PalLength(void)
{
if ((m_bmp.bmp2.biBitCount == 16) || (m_bmp.bmp2.biBitCount == 32)) {
if (m_bmp.bmp2.biCompression == BI_BITFIELDS)
return 12; // 3 * DWORD
return 0; /* default bit fields */
}
return PalCount() * (m_old ? 3 : 4);
}
// pointer to bitmap bits
LPBYTE
CDIB::GetBits(void)
{
ASSERT(m_valid);
if (!m_valid)
return 0;
return m_bits;
}
// width of bitmap row in bytes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -