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

📄 bitimage.cpp

📁 超强jpeg解码程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -