bmpencoder.cpp
来自「Jpeg编解码器的源代码」· C++ 代码 · 共 282 行
CPP
282 行
//
// Title: Windows Bitmap Coder
//
// Copyright 1997-1999, 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
//
// Author: John M. Miano (miano@colosseumbuilders.com)
//
// Date: April 15, 1999
//
// Version: 3
//
// Description:
//
// Windows BMP Encoder
//
// Revision History:
//
//
#include <windows.h>
#include <fstream>
#include <climits>
#include "bmpencoder.h"
using namespace std ;
namespace Colosseum
{
const UBYTE2 Signature = 'B'|('M'<<CHAR_BIT) ;
//
// Description:
//
// Default Constructor
//
BmpEncoder::BmpEncoder ()
: create_alpha_channel (true),
bits_per_pixel (24)
{
}
//
// Description:
//
// Class copy constructor
//
BmpEncoder::BmpEncoder (const BmpEncoder &source)
: BitmapImageEncoder (source),
create_alpha_channel (source.create_alpha_channel),
bits_per_pixel (source.bits_per_pixel)
{
return ;
}
//
// Description:
//
// Class assignment operator.
//
// Parameters:
// source: The object to copy
//
BmpEncoder &BmpEncoder::operator=(const BmpEncoder &source)
{
if (&source != this)
{
BitmapImageEncoder::operator=(source) ;
}
return *this ;
}
//
// Description:
//
// This function writes an image to a BMP stream.
//
// Parameters:
// strm: The output stream
// image: The image to output
//
void BmpEncoder::writeImage (std::ostream &strm, const BitmapImage &image)
{
if (image.getWidth () == 0 || image.getHeight () == 0)
throw BmpError ("Empty Image") ;
BITMAPFILEHEADER fileheader = {
SystemToLittleEndian (Signature),
0,
0,
0,
0 } ;
// The header is initialized for 32-Bit images. For other bit depths
// we filling the values later.
BITMAPV4HEADER infoheader = {
SystemToLittleEndian (static_cast<UBYTE4>(sizeof (BITMAPV4HEADER))), // Header Size
SystemToLittleEndian (static_cast<UBYTE4>(image.getWidth ())),
SystemToLittleEndian (- static_cast<BYTE4>(image.getHeight ())),
SystemToLittleEndian (static_cast<UBYTE2>(1)), // Planes
SystemToLittleEndian (static_cast<BYTE4>(bits_per_pixel)), // biBitCount
SystemToLittleEndian (static_cast<UBYTE4>(BI_BITFIELDS)), // biCompression
0, // Image Size
0, // biXPelsPerMeter
0, // biYPelsPerMeter
0, // biClrUsed
0, // biClrImportant
// This is the cut off from the BITMAPINFOHEADER
SystemToLittleEndian (static_cast<UBYTE4>(0xFF0000)), // Red Mask
SystemToLittleEndian (static_cast<UBYTE4>(0xFF00)), // Green Mask
SystemToLittleEndian (static_cast<UBYTE4>(0xFF)), // Blue Mask
create_alpha_channel ? SystemToLittleEndian (static_cast<UBYTE4>(0xFF000000)) : 0, // Alpha Mask
0, // CS Type
{ { 0, 0, 0, }, { 0, 0, 0, }, { 0, 0, 0, } }, // CIE
0, // Gamma Red
0, // Gamma Green
0, // Gamma Blue
} ;
// Row width rounded up to 4 bytes.
unsigned int rowwidth = (image.getWidth () * (bits_per_pixel / CHAR_BIT) + 0x3) & ~0x3 ;
// Calulate the space required for the image.
unsigned long datasize = image.getHeight () * rowwidth ;
if (bits_per_pixel == 16)
{
infoheader.bV4RedMask = SystemToLittleEndian (0x7C00U) ;
infoheader.bV4GreenMask = SystemToLittleEndian (0x3E0U) ;
infoheader.bV4BlueMask = SystemToLittleEndian (0x1FU) ;
}
else if (bits_per_pixel == 24)
{
// For 24-Bit images we set the BMP header up for the LCD in BMP files.
infoheader.bV4V4Compression = SystemToLittleEndian (static_cast<UBYTE4>(BI_RGB)) ;
infoheader.bV4Size = SystemToLittleEndian (sizeof (BITMAPINFOHEADER)) ;
infoheader.bV4Height = -infoheader.bV4Height ;
}
unsigned long spacerequired = sizeof (BITMAPFILEHEADER)
+ datasize
+ infoheader.bV4Size ;
// Fill in the remaining header fields.
fileheader.bfOffBits = SystemToLittleEndian (
static_cast<UBYTE4>(sizeof (BITMAPFILEHEADER)+ infoheader.bV4Size)
) ;
fileheader.bfSize = SystemToLittleEndian (static_cast<UBYTE4>(spacerequired)) ;
strm.write (reinterpret_cast<char*>(&fileheader), sizeof (BITMAPFILEHEADER)) ;
strm.write (reinterpret_cast<char*>(&infoheader), infoheader.bV4Size) ;
callProgressFunction (0) ;
unsigned int padsize = rowwidth - image.getWidth () * (bits_per_pixel / CHAR_BIT) ;
static const char pad [3] = { 0, 0, 0 } ;
switch (bits_per_pixel)
{
case 16:
{
const BitmapImage::Pixel *pixel = &image [0] ;
for (unsigned int ii = 0 ; ii < image.getHeight () ; ++ ii)
{
for (unsigned int jj = 0 ; jj < image.getWidth() ; ++ jj, ++ pixel)
{
UBYTE2 buffer = 0 ;
buffer |= (pixel->blue >> 3) & 0x1FU ;
buffer |= ((pixel->green >> 3) & 0x1FU) << 5 ;
buffer |= ((pixel->red >> 3) & 0x1FU) << 10 ;
strm.write (reinterpret_cast<const char*>(&buffer), sizeof (buffer)) ;
}
if (padsize != 0)
strm.write (pad, padsize) ;
callProgressFunction (ii * 100 /image.getHeight ()) ;
}
}
break ;
case 24:
{
for (int ii = image.getHeight () - 1 ; ii >= 0 ; -- ii)
{
// For 24-bit images we store the rows in reverse order
// in order to be compatible with the LCD in viewers.
const BitmapImage::Pixel *pixel = &image [ii * image.getWidth ()] ;
for (unsigned int jj = 0 ; jj < image.getWidth() ; ++ jj, ++ pixel)
{
RGBTRIPLE buffer ;
buffer.rgbtRed = pixel->red ;
buffer.rgbtGreen = pixel->green ;
buffer.rgbtBlue = pixel->blue ;
strm.write (reinterpret_cast<const char*>(&buffer), sizeof (buffer)) ;
}
if (padsize != 0)
strm.write (pad, padsize) ;
callProgressFunction (ii * 100 /image.getHeight ()) ;
}
}
break ;
case 32:
strm.write (reinterpret_cast<const char*>(&image [0]),
sizeof (BitmapImage::Pixel)
* image.getHeight ()
* image.getWidth ()) ;
break ;
}
callProgressFunction (100) ;
return ;
}
void BmpEncoder::writeImageFile (const std::string &filename, const BitmapImage &image)
{
ofstream strm (filename.c_str (), ios::binary|ios::trunc) ;
if (! strm)
{
string msg = "Cannot Open Input File " ;
msg += filename ;
throw BmpError (msg) ;
}
writeImage (strm, image) ;
return ;
}
void BmpEncoder::setCreateAlphaChannel (bool value)
{
create_alpha_channel = value ;
return ;
}
bool BmpEncoder::getCreateAlphaChannel () const
{
return create_alpha_channel ;
}
void BmpEncoder::setBitsPerPixel (unsigned int value)
{
switch (value)
{
case 16: case 24: case 32: break ;
default: throw BmpError ("Invalid Bit Depth") ;
}
bits_per_pixel = value ;
return ;
}
unsigned int BmpEncoder::getBitsPerPixel () const
{
return bits_per_pixel ;
}
//
// Description:
//
// This function calls the progress function if it has been defined.
//
// Parameters:
// percent: The percent completed (0..100)
//
void BmpEncoder::callProgressFunction (unsigned int percent)
{
if (progress_function == 0)
return ;
bool cancel = false ;
progress_function (*this, progress_data, 1, 1, percent, cancel) ;
if (cancel)
throw GraphicsAbort () ;
return ;
}
} // End Namespace
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?