imagbmp.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,492 行 · 第 1/4 页
CPP
1,492 行
/////////////////////////////////////////////////////////////////////////////
// Name: imagbmp.cpp
// Purpose: wxImage BMP,ICO and CUR handlers
// Author: Robert Roebling, Chris Elliott
// RCS-ID: $Id: imagbmp.cpp,v 1.58 2005/09/13 16:06:41 ABX Exp $
// Copyright: (c) Robert Roebling, Chris Elliott
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "imagbmp.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/defs.h"
#if wxUSE_IMAGE
#include "wx/imagbmp.h"
#include "wx/bitmap.h"
#include "wx/debug.h"
#include "wx/log.h"
#include "wx/app.h"
#include "wx/filefn.h"
#include "wx/wfstream.h"
#include "wx/intl.h"
#include "wx/module.h"
#include "wx/quantize.h"
// For memcpy
#include <string.h>
#ifdef __SALFORDC__
#ifdef FAR
#undef FAR
#endif
#endif
#ifdef __WXMSW__
#include "wx/msw/wrapwin.h"
#endif
//-----------------------------------------------------------------------------
// wxBMPHandler
//-----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxBMPHandler,wxImageHandler)
#if wxUSE_STREAMS
#ifndef BI_RGB
#define BI_RGB 0
#endif
#ifndef BI_RLE8
#define BI_RLE8 1
#endif
#ifndef BI_RLE4
#define BI_RLE4 2
#endif
#ifndef BI_BITFIELDS
#define BI_BITFIELDS 3
#endif
#define poffset (line * width * 3 + column * 3)
bool wxBMPHandler::SaveFile(wxImage *image,
wxOutputStream& stream,
bool verbose)
{
return SaveDib(image, stream, verbose, true/*IsBmp*/, false/*IsMask*/);
}
bool wxBMPHandler::SaveDib(wxImage *image,
wxOutputStream& stream,
bool verbose,
bool IsBmp,
bool IsMask)
{
wxCHECK_MSG( image, false, _T("invalid pointer in wxBMPHandler::SaveFile") );
if ( !image->Ok() )
{
if ( verbose )
wxLogError(_("BMP: Couldn't save invalid image."));
return false;
}
// get the format of the BMP file to save, else use 24bpp
unsigned format = wxBMP_24BPP;
if ( image->HasOption(wxIMAGE_OPTION_BMP_FORMAT) )
format = image->GetOptionInt(wxIMAGE_OPTION_BMP_FORMAT);
wxUint16 bpp; // # of bits per pixel
int palette_size; // # of color map entries, ie. 2^bpp colors
// set the bpp and appropriate palette_size, and do additional checks
if ( (format == wxBMP_1BPP) || (format == wxBMP_1BPP_BW) )
{
bpp = 1;
palette_size = 2;
}
else if ( format == wxBMP_4BPP )
{
bpp = 4;
palette_size = 16;
}
else if ( (format == wxBMP_8BPP) || (format == wxBMP_8BPP_GREY) ||
(format == wxBMP_8BPP_RED) || (format == wxBMP_8BPP_PALETTE) )
{
// need to set a wxPalette to use this, HOW TO CHECK IF VALID, SIZE?
if ((format == wxBMP_8BPP_PALETTE)
#if wxUSE_PALETTE
&& !image->HasPalette()
#endif // wxUSE_PALETTE
)
{
if ( verbose )
wxLogError(_("BMP: wxImage doesn't have own wxPalette."));
return false;
}
bpp = 8;
palette_size = 256;
}
else // you get 24bpp
{
format = wxBMP_24BPP;
bpp = 24;
palette_size = 0;
}
unsigned width = image->GetWidth();
unsigned row_padding = (4 - int(width*bpp/8.0) % 4) % 4; // # bytes to pad to dword
unsigned row_width = int(width * bpp/8.0) + row_padding; // # of bytes per row
struct
{
// BitmapHeader:
wxUint16 magic; // format magic, always 'BM'
wxUint32 filesize; // total file size, inc. headers
wxUint32 reserved; // for future use
wxUint32 data_offset; // image data offset in the file
// BitmapInfoHeader:
wxUint32 bih_size; // 2nd part's size
wxUint32 width, height; // bitmap's dimensions
wxUint16 planes; // num of planes
wxUint16 bpp; // bits per pixel
wxUint32 compression; // compression method
wxUint32 size_of_bmp; // size of the bitmap
wxUint32 h_res, v_res; // image resolution in dpi
wxUint32 num_clrs; // number of colors used
wxUint32 num_signif_clrs;// number of significant colors
} hdr;
wxUint32 hdr_size = 14/*BitmapHeader*/ + 40/*BitmapInfoHeader*/;
hdr.magic = wxUINT16_SWAP_ON_BE(0x4D42/*'BM'*/);
hdr.filesize = wxUINT32_SWAP_ON_BE( hdr_size + palette_size*4 +
row_width * image->GetHeight() );
hdr.reserved = 0;
hdr.data_offset = wxUINT32_SWAP_ON_BE(hdr_size + palette_size*4);
hdr.bih_size = wxUINT32_SWAP_ON_BE(hdr_size - 14);
hdr.width = wxUINT32_SWAP_ON_BE(image->GetWidth());
if ( IsBmp )
{
hdr.height = wxUINT32_SWAP_ON_BE(image->GetHeight());
}
else
{
hdr.height = wxUINT32_SWAP_ON_BE(2 * image->GetHeight());
}
hdr.planes = wxUINT16_SWAP_ON_BE(1); // always 1 plane
hdr.bpp = wxUINT16_SWAP_ON_BE(bpp);
hdr.compression = 0; // RGB uncompressed
hdr.size_of_bmp = wxUINT32_SWAP_ON_BE(row_width * image->GetHeight());
hdr.h_res = hdr.v_res = wxUINT32_SWAP_ON_BE(72); // 72dpi is standard
hdr.num_clrs = wxUINT32_SWAP_ON_BE(palette_size); // # colors in colormap
hdr.num_signif_clrs = 0; // all colors are significant
if ( IsBmp )
{
if (// VS: looks ugly but compilers tend to do ugly things with structs,
// like aligning hdr.filesize's ofset to dword :(
// VZ: we should add padding then...
!stream.Write(&hdr.magic, 2) ||
!stream.Write(&hdr.filesize, 4) ||
!stream.Write(&hdr.reserved, 4) ||
!stream.Write(&hdr.data_offset, 4)
)
{
if (verbose)
wxLogError(_("BMP: Couldn't write the file (Bitmap) header."));
return false;
}
}
if ( !IsMask )
{
if (
!stream.Write(&hdr.bih_size, 4) ||
!stream.Write(&hdr.width, 4) ||
!stream.Write(&hdr.height, 4) ||
!stream.Write(&hdr.planes, 2) ||
!stream.Write(&hdr.bpp, 2) ||
!stream.Write(&hdr.compression, 4) ||
!stream.Write(&hdr.size_of_bmp, 4) ||
!stream.Write(&hdr.h_res, 4) ||
!stream.Write(&hdr.v_res, 4) ||
!stream.Write(&hdr.num_clrs, 4) ||
!stream.Write(&hdr.num_signif_clrs, 4)
)
{
if (verbose)
wxLogError(_("BMP: Couldn't write the file (BitmapInfo) header."));
return false;
}
}
wxPalette *palette = NULL; // entries for quantized images
wxUint8 *rgbquad = NULL; // for the RGBQUAD bytes for the colormap
wxImage *q_image = NULL; // destination for quantized image
// if <24bpp use quantization to reduce colors for *some* of the formats
if ( (format == wxBMP_1BPP) || (format == wxBMP_4BPP) ||
(format == wxBMP_8BPP) || (format == wxBMP_8BPP_PALETTE) )
{
// make a new palette and quantize the image
if (format != wxBMP_8BPP_PALETTE)
{
q_image = new wxImage();
// I get a delete error using Quantize when desired colors > 236
int quantize = ((palette_size > 236) ? 236 : palette_size);
// fill the destination too, it gives much nicer 4bpp images
wxQuantize::Quantize( *image, *q_image, &palette, quantize, 0,
wxQUANTIZE_FILL_DESTINATION_IMAGE );
}
else
{
#if wxUSE_PALETTE
palette = new wxPalette(image->GetPalette());
#endif // wxUSE_PALETTE
}
int i;
unsigned char r, g, b;
rgbquad = new wxUint8 [palette_size*4];
for (i = 0; i < palette_size; i++)
{
#if wxUSE_PALETTE
if ( !palette->GetRGB(i, &r, &g, &b) )
#endif // wxUSE_PALETTE
r = g = b = 0;
rgbquad[i*4] = b;
rgbquad[i*4+1] = g;
rgbquad[i*4+2] = r;
rgbquad[i*4+3] = 0;
}
}
// make a 256 entry greyscale colormap or 2 entry black & white
else if ( (format == wxBMP_8BPP_GREY) || (format == wxBMP_8BPP_RED) ||
(format == wxBMP_1BPP_BW) )
{
rgbquad = new wxUint8 [palette_size*4];
for ( int i = 0; i < palette_size; i++ )
{
// if 1BPP_BW then the value should be either 0 or 255
wxUint8 c = (wxUint8)((i > 0) && (format == wxBMP_1BPP_BW) ? 255 : i);
rgbquad[i*4] =
rgbquad[i*4+1] =
rgbquad[i*4+2] = c;
rgbquad[i*4+3] = 0;
}
}
// if the colormap was made, then it needs to be written
if (rgbquad)
{
if ( !IsMask )
{
if ( !stream.Write(rgbquad, palette_size*4) )
{
if (verbose)
wxLogError(_("BMP: Couldn't write RGB color map."));
delete[] rgbquad;
#if wxUSE_PALETTE
delete palette;
#endif // wxUSE_PALETTE
delete q_image;
return false;
}
}
delete []rgbquad;
}
// pointer to the image data, use quantized if available
wxUint8 *data = (wxUint8*) image->GetData();
if (q_image) if (q_image->Ok()) data = (wxUint8*) q_image->GetData();
wxUint8 *buffer = new wxUint8[row_width];
memset(buffer, 0, row_width);
int y; unsigned x;
long int pixel;
for (y = image->GetHeight() -1; y >= 0; y--)
{
if ( format == wxBMP_24BPP ) // 3 bytes per pixel red,green,blue
{
for ( x = 0; x < width; x++ )
{
pixel = 3*(y*width + x);
buffer[3*x ] = data[pixel+2];
buffer[3*x + 1] = data[pixel+1];
buffer[3*x + 2] = data[pixel];
}
}
else if ((format == wxBMP_8BPP) || // 1 byte per pixel in color
(format == wxBMP_8BPP_PALETTE))
{
for (x = 0; x < width; x++)
{
pixel = 3*(y*width + x);
#if wxUSE_PALETTE
buffer[x] = (wxUint8)palette->GetPixel( data[pixel],
data[pixel+1],
data[pixel+2] );
#else
// FIXME: what should this be? use some std palette maybe?
buffer[x] = 0;
#endif // wxUSE_PALETTE
}
}
else if ( format == wxBMP_8BPP_GREY ) // 1 byte per pix, rgb ave to grey
{
for (x = 0; x < width; x++)
{
pixel = 3*(y*width + x);
buffer[x] = (wxUint8)(.299*data[pixel] +
.587*data[pixel+1] +
.114*data[pixel+2]);
}
}
else if ( format == wxBMP_8BPP_RED ) // 1 byte per pixel, red as greys
{
for (x = 0; x < width; x++)
{
buffer[x] = (wxUint8)data[3*(y*width + x)];
}
}
else if ( format == wxBMP_4BPP ) // 4 bpp in color
{
for (x = 0; x < width; x+=2)
{
pixel = 3*(y*width + x);
// fill buffer, ignore if > width
#if wxUSE_PALETTE
buffer[x/2] = (wxUint8)(
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?