📄 bitimage.cpp
字号:
//
// Copyright (c) 1997,1998 Colosseum Builders, Inc.
// All rights reserved.
//
// Colosseum Builders, Inc. makes no warranty, expressed or implied
// with regards to this software. It is provided as is.
//
// See the README.TXT file that came with this software for restrictions
// on the use and redistribution of this file or send E-mail to
// info@colosseumbuilders.com
//
//
// Title: Bitmap Image Class Implementation
//
// Author: John M. Miano miano@colosseumbuilders.com
//
#include "bitimage.h"
#include "grexcept.h"
// Function to round a row width up to the nearest multiple of
// RowRounding. Windows expects rows to be a length that is a multiple of
// four.
static inline int SQUARE (int xx)
{
return xx * xx ;
}
static inline unsigned int RoundRow (unsigned int width)
{
unsigned int result = (width + BitmapImage::RowRounding - 1)
& ~(BitmapImage::RowRounding - 1) ;
return result ;
}
//
// Description:
//
// Default Constructor
//
BitmapImage::BitmapImage ()
{
Initialize () ;
return ;
}
//
// Description:
//
// Copy Constructor
//
BitmapImage::BitmapImage (const BitmapImage &source)
{
Initialize () ;
DoCopy (source) ;
return ;
}
//
// Description:
//
// Assignment Operator
//
// Parameters:
// source: The object to copy
//
BitmapImage &BitmapImage::operator=(const BitmapImage &source)
{
delete [] color_map ;
delete [] image_data ;
DoCopy (source) ;
return *this ;
}
//
// Description:
//
// Common initialization function.
//
void BitmapImage::Initialize ()
{
ClearData () ;
progress_function = NULL ;
progress_data = NULL ;
return ;
}
//
// Description:
//
// Class Destructor
//
BitmapImage::~BitmapImage ()
{
delete [] color_map ;
delete [] image_data ;
return ;
}
//
// Description:
//
// Common function for resetting an object to a known state.
//
void BitmapImage::ClearData ()
{
bit_count = 0 ;
image_width = 0 ;
image_height = 0 ;
color_count = 0 ;
color_map = NULL ;
image_data = NULL ;
color_usage = NULL ;
color_areas = NULL ;
color_area_count = 0 ;
return ;
}
//
// Description:
//
// Common copy function for use by the copy constructor and assignment
// operator.
//
// Parameters:
// source: The object to copy
//
void BitmapImage::DoCopy (const BitmapImage &source)
{
progress_function = source.progress_function ;
progress_data = source.progress_function ;
bit_count = source.bit_count ;
image_width = source.image_width ;
image_height = source.image_height ;
color_count = source.color_count ;
color_map = NULL ;
image_data = NULL ;
color_usage = NULL ;
color_areas = NULL ;
color_area_count = 0 ;
// Only copy the image data if the size values are valid.
if (image_width > 0 && image_height > 0 && bit_count > 0
&& (bit_count == 24 || color_count != 0))
{
unsigned int bitwidth ;
unsigned int bytecount ;
switch (bit_count)
{
case 1:
case 2:
case 4:
case 8:
color_map = new ColorMapEntry [color_count] ;
memcpy (color_map,
source.color_map,
sizeof (ColorMapEntry) * color_count) ;
bitwidth = bit_count * image_width ;
row_width = RoundRow ((bitwidth + 7)/8) ;
bytecount = row_width * image_height ;
image_data = new UBYTE1 [bytecount] ;
memcpy (image_data, source.image_data, bytecount) ;
break ;
case 24:
row_width = RoundRow (3 * image_width) ;
image_data = new UBYTE1 [row_width * image_height] ;
memcpy (image_data, source.image_data, row_width * image_height) ;
break ;
default:
if (image_width != 0 ||image_height != 0)
throw EInvalidBitCount () ;
}
}
return ;
}
#if defined (CHECK_RANGE)
//
// Description:
//
// Row Class Constructor. The row class represents a single
// row of image data.
//
// Parameters:
// data: A pointer to the row's data.
// length: The row length
//
BitmapImage::Row::Row (UBYTE1 *data, unsigned int length)
{
row_data = data ;
row_length = length ;
return ;
}
//
// Description:
//
// Row class [] operator. This operator returns the data
// value at a given point offset in the row.
//
// Parameters:
// index: The row offset
//
// Return Value:
// The data value in the row at the specified offset
//
UBYTE1 &BitmapImage::Row::operator[](unsigned int index)
{
if (index >= row_length)
throw ESubscriptOutOfRange () ;
return row_data [index] ;
}
//
// Description:
//
// This function returns a pointer to the Nth row of the image's data.
// It is set up to return the rows in reverse order as Windows expects
// them so that other software does not have to deal with such wierdness.
//
// Parameters:
// xx: The row index
//
// Return Value:
// A Row object that describes the image row.
//
BitmapImage::Row BitmapImage::operator[](unsigned int xx)const
{
// In Windows bitmaps are stored bass ackwards.
if (xx >= image_height)
throw ESubscriptOutOfRange () ;
return Row (&image_data [(image_height - xx - 1) * row_width],
row_width) ;
}
#endif
//
// Description:
//
// This function allocates space to hold an image of the specified size.
// The colormap (if used) and the image data are all set to zeros.
//
// Parameters:
// cc: Number of colors. Ignored for 24-bit bitmaps
// bits: Number of bits per pixel.
// ww, hh: Bitmap size
//
void BitmapImage::SetSize (unsigned int cc, // Color Count
unsigned int bits, // Data Size in Bits
unsigned int ww, // Width
unsigned int hh) // Height
{
// Get rid of any existing image.
delete [] color_map ;
delete [] image_data ;
ClearData () ;
switch (bits)
{
case 1:
case 2:
case 4:
case 8:
{
bit_count = bits ;
color_count = cc ;
image_width = ww ;
image_height = hh ;
color_map = new ColorMapEntry [color_count] ;
memset (color_map, 0, sizeof (ColorMapEntry) * color_count) ;
unsigned int bitsize = bit_count * image_width ;
row_width = RoundRow ((bitsize + 7)/8) ;
unsigned int bytecount = row_width * image_height ;
image_data = new UBYTE1 [bytecount] ;
memset (image_data, 0, bytecount) ;
}
break ;
case 24:
{
bit_count = bits ;
color_count = cc ;
image_width = ww ;
image_height = hh ;
row_width = RoundRow (3 * image_width) ;
image_data = new UBYTE1 [row_width * image_height] ;
memset (image_data, 0, row_width * image_height) ;
}
break ;
default:
throw EInvalidBitCount () ;
}
return ;
}
//
// Description:
//
// This function returns a reference to the Nth colormap entry.
//
// Parameters:
// index: The index of the color map entry 0..ColorCount () -1.
//
// Return Value:
// The color map entry.
//
BitmapImage::ColorMapEntry &BitmapImage::ColorMap (unsigned int index)
{
if (index >= color_count)
throw ESubscriptOutOfRange () ;
return color_map [index] ;
}
//
// Description:
//
// This function returns a reference to the Nth colormap entry.
//
// This is a const version of the previous function.
//
// Parameters:
// index: The index of the color map entry 0..ColorCount () -1.
//
// Return Value:
// The color map entry.
//
BitmapImage::ColorMapEntry BitmapImage::ColorMap (unsigned int index) const
{
if (index >= color_count)
throw ESubscriptOutOfRange () ;
return color_map [index] ;
}
//
// Description:
//
// This function clears out the image.
//
void BitmapImage::Clear ()
{
delete [] color_map ;
delete [] image_data ;
ClearData () ;
return ;
}
//
// Description:
//
// This function returns the RGB values for a pixel in the bitmap at the
// point [row,col] where row=[0..height-1] and col=[0..width-1].
//
// This function allows a caller to get the RGB values for 1, 2, 4, 6,
// and 24-bit bitmaps using the same method.
//
// Parameters:
// row, col: The position in the image to return data from
// red, green, blue: The color value at the specified position
//
void BitmapImage::GetRGB (unsigned int row, unsigned int col,
UBYTE1 &red, UBYTE1 &green, UBYTE1 &blue) const
{
if (row >= image_height && col >= image_width)
throw ESubscriptOutOfRange () ;
switch (bit_count)
{
unsigned int index ;
unsigned int offset ;
case 1:
offset = col / 8 ;
index = (((*this)[row][offset] >> (7 - (col % 8))) & 0x1) ;
red = color_map [index].red ;
green = color_map [index].green ;
blue = color_map [index].blue ;
break ;
case 2:
offset = col / 4 ;
index = (((*this)[row][offset] >> (2 * (3 - (col % 4)))) & 0x3) ;
red = color_map [index].red ;
green = color_map [index].green ;
blue = color_map [index].blue ;
break ;
case 4:
offset = col / 2 ;
if (col % 2 == 0)
index = ((*this)[row][offset] & 0xF0) >> 4 ;
else
index = ((*this)[row][offset] & 0x0F) ;
red = color_map [index].red ;
green = color_map [index].green ;
blue = color_map [index].blue ;
break ;
case 8:
red = color_map [(*this)[row][col]].red ;
green = color_map [(*this)[row][col]].green ;
blue = color_map [(*this)[row][col]].blue ;
break ;
case 24:
red = (*this)[row][3 * col + RedOffset] ;
green = (*this)[row][3 * col + GreenOffset] ;
blue = (*this)[row][3 * col + BlueOffset] ;
break ;
default:
throw EInvalidBitCount () ;
}
return ;
}
//
// Description:
// This sets the progress function for the image.
//
// Parameters:
// function: The progress function
// data: The call progress data
//
void BitmapImage::SetProgressFunction (
IMAGEPROGRESSFUNCTION function,
void *data)
{
progress_function = function ;
progress_data = data ;
return ;
}
//
// Description:
// This function calls the progression function.
//
// Parameters:
// percent: % complete
// pass: Current Pass
// passcount: Number of passes
//
void BitmapImage::CallProgressFunction (unsigned int percent,
unsigned int pass,
unsigned int passcount)
{
if (progress_function == NULL)
return ;
if (percent > 100)
percent = 100 ;
bool cancel = false ;
progress_function (*this, progress_data, pass, passcount, percent, cancel) ;
if (cancel)
throw EGraphicsAbort () ;
return ;
}
//
// Color Quantization Routines
//
// Since I have received many requests for color quantization I have
// whipped this up. I have to admit to knowing nothing about color
// quantization (I have always had systems that did not need it). The
// only techniques for quantization that I had been familiar with are
// scaling color values and having a fixed color space. However, I thought
// 1-pass methods such as those would be too cude for someone of my
// programming skill.
//
// What I have tried instead is to use two passes. What we do is create
// a 3-dimensional hash table of color values. The we keep dividing the
// colorspace in half until we have set of color ranges.
//
// Hey, it's probably not all that efficient but it's the best I could come
// up with in an evening.
//
//
//
// Description:
// This function looks up the color entry in the color hash table
// for a specified color value.
//
// Parameters:
// red, green, blue: The color value to search for.
//
BitmapImage::ColorUsage *BitmapImage::FindColor (UBYTE1 red,
UBYTE1 green,
UBYTE1 blue)
{
if (color_usage->lists [red][RedOffset] == NULL
|| color_usage->lists [green][GreenOffset] == NULL
|| color_usage->lists [blue][BlueOffset] == NULL)
{
return NULL ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -