bmx.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 601 行 · 第 1/2 页

CPP
601
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


/*
BMX:  Image file handling
*/

#include <stdlib.h>
#ifdef __UNIX__
#include <unistd.h>
#else
#include <direct.h>
#endif
#include "bmx.h"
#include "compress.h"


// Magic numbers for the supported image formats.
#define BITMAP_MAGIC    0x4D42
#define SHG1_MAGIC  0x706C
#define SHG2_MAGIC  0x506C

//  Bitmap::Bitmap  --Check that the given file is a valid bitmap.

Bitmap::Bitmap( InFile *fp ) : Bmx( fp )
{
    _size = 0;

    uint_16 magic;
    uint_32 filesize;

    _fp->reset();
    _fp->readbuf( &magic, 1, sizeof( uint_16 ) );
    _fp->readbuf( &filesize, 1, sizeof( uint_32 ) );
    _fp->reset(0, SEEK_END);
    _fileSize = _fp->tell();

    if( magic != BITMAP_MAGIC ||
        filesize != _fileSize ){
    _isValidImage = 0;
    } else {
    _isValidImage = 1;
    }

    _fp->close();   // To conserve file handles.
}


//  Bitmap::size        --Override of Dumpable::size.  Reads in the
//            bitmap and does a test compression of the pixels.

#define BLOCK_SIZE  1024    // Arbitrary large value.

#define BIH_SIZE    0x28    // Size of a BitmapInfoHeader (see Windows
                // docs on bitmaps).

#define MIN_16BIT   0x80    // Smallest value stored in a short
#define MIN_32BIT   0x8000  // Smallest value stored in a long

#define OBJ_OFFSET  8   // Offset of the "object" in a .SHG file.

uint_32 Bitmap::size()
{
    if( _size != 0 ){
    return _size;
    }

    _fp->open();
    _fp->reset( 10 );   // size of unneeded header info.

    _fp->readbuf( &_pixOffset, 1, sizeof( uint_32 ) );
    _fp->readbuf( &_headSize, 1, sizeof( uint_32 ) );

    if( _headSize == BIH_SIZE ){

    // If _headSize==0x28, this bitmap uses a BitmapInfoHeader
    // and RBG quads.

    _fp->readbuf( &_width, 1, sizeof( uint_32 ) );
    _fp->readbuf( &_height, 1, sizeof( uint_32 ) );

    _fp->readbuf( &_planes, 1, sizeof( uint_16 ) );
    _fp->readbuf( &_bitsPerPix, 1, sizeof( uint_16 ) );

    _fp->readbuf( &_compression, 1, sizeof( uint_32 ) );
    _fp->readbuf( &_imageSize, 1, sizeof( uint_32 ) );
    _fp->readbuf( &_xpels, 1, sizeof( uint_32 ) );
    _fp->readbuf( &_ypels, 1, sizeof( uint_32 ) );
    _fp->readbuf( &_colsUsed, 1, sizeof( uint_32 ) );

    if( _colsUsed == 0 ){
        // We can calculate _colsUsed from _bitsPerPix, except
        // in the case of a 24-bit bitmap.
        if( _bitsPerPix < 24 ){
        _colsUsed = 1<<_bitsPerPix;
        }
    }

    _fp->readbuf( &_colsImportant, 1, sizeof(uint_32) );
    _dataPos = _fp->tell();
    _fp->reset( sizeof(uint_32)*_colsUsed, SEEK_CUR );

    } else {

    // The other case is _headSize==0x0C, meaning this bitmap
    // uses a BitmapCoreHeader and RGB triples.

    _width = 0;
    _fp->readbuf( &_width, 1, sizeof( uint_16 ) );
    _height = 0;
    _fp->readbuf( &_height, 1, sizeof( uint_16 ) );
    _fp->readbuf( &_planes, 1, sizeof( uint_16 ) );
    _fp->readbuf( &_bitsPerPix, 1, sizeof( uint_16 ) );

    // Again, calculate _colsUsed from _bitsPerPix, unless
    // this is a 24-bit bitmap.
    if( _bitsPerPix < 24 ){
        _colsUsed = 1<<_bitsPerPix;
    } else {
        _colsUsed = 0;
    }
    _colsImportant = 0;

    _dataPos = _fp->tell();
    _fp->reset( 3*_colsUsed, SEEK_CUR );
    }

    _objOffset = sizeof(uint_32)*_colsUsed + 0x1C; // 0x1C = size of
                               // object header

    if( _bitsPerPix >= MIN_16BIT ){
    _objOffset += 1;
    }
    if( _width >= MIN_32BIT ){
    _objOffset += 2;
    }
    if( _height >= MIN_32BIT ){
    _objOffset += 2;
    }
    if( _colsUsed >= MIN_32BIT ){
    _objOffset += 2;
    }

    // Calculate the size of the compressed pixel data.
    CompWriter  riter;
    CompReader  reader( &riter );
    char    *buffer = new char[BLOCK_SIZE];
    int     blocksize;
    int     count = _pixOffset;

    _pixSize = 0;
    while( count < _fileSize ){
    blocksize = _fp->readbuf( buffer, BLOCK_SIZE );
    count += blocksize;
    _pixSize += reader.compress( buffer, blocksize );
    }

    if( _pixSize >= MIN_32BIT ){
    _objOffset += 2;
    }
    _size = _objOffset+OBJ_OFFSET+_pixSize;

    delete[] buffer;

    _fp->close();
    return _size;
}


//  Bitmap::dump    --Overrides Dumpable::dump.  Writes the
//            converted image.

int Bitmap::dump( OutFile *dest )
{
    uint_16 magic = SHG1_MAGIC;
    uint_16 num_objs = 1;
    uint_32 offset = OBJ_OFFSET;
    uint_16 two_hund = 0x200;
    uint_32 big_zero = 0x00000000;

    dest->writebuf( &magic, sizeof( uint_16 ), 1 );
    dest->writebuf( &num_objs, sizeof( uint_16 ), 1 );
    dest->writebuf( &offset, sizeof( uint_32 ), 1 );
    dest->writech( 0x06 );      // Identifies this as a .BMP
    dest->writech( 0x02 );      // Specifies the compression type
    dest->writech( 0xC0 );      // Specifies 96dpi
    dest->writech( 0x00 );      // Magic
    dest->writech( 0xC0 );      // Specifies 96dpi again
    dest->writebuf( &two_hund, sizeof( uint_16 ), 1 );

    _bitsPerPix *= 2;
    if( _bitsPerPix >= 2*MIN_16BIT ){
    _bitsPerPix += 1;
    dest->writebuf( &_bitsPerPix, sizeof( uint_16 ), 1 );
    } else {
    dest->writech( *((uint_8*) &_bitsPerPix) );
    }

    _width *= 2;
    if( _width >= 2*MIN_32BIT ){
    _width += 1;
    dest->writebuf( &_width, sizeof( uint_32 ), 1 );
    } else {
    dest->writebuf( (uint_16*) &_width, sizeof( uint_16 ), 1 );
    }

    _height *= 2;
    if( _height >= 2*MIN_32BIT ){
    _height += 1;
    dest->writebuf( &_height, sizeof( uint_32 ), 1 );
    } else {
    dest->writebuf( (uint_16*) &_height, sizeof( uint_16 ), 1 );
    }

    _colsUsed *= 2;
    if( _colsUsed >= 2*MIN_32BIT ){
    _colsUsed += 1;
    dest->writebuf( &_colsUsed, sizeof( uint_32 ), 1 );
    } else {
    dest->writebuf( (uint_16*) &_colsUsed, sizeof( uint_16 ), 1 );
    }
    _colsUsed /= 2; // We need this quantity again later.

    dest->writebuf( (uint_16*) &big_zero, sizeof( uint_16 ), 1 );

    _pixSize *= 2;
    if( _pixSize >= 2*MIN_32BIT ){
    _pixSize += 1;
    dest->writebuf( &_pixSize, sizeof( uint_32 ), 1 );
    } else {
    dest->writebuf( (uint_16*) &_pixSize, sizeof( uint_16 ), 1 );
    }

    dest->writebuf( (uint_16*) &big_zero, sizeof( uint_16 ), 1 );
    dest->writebuf( &_objOffset, sizeof( uint_32 ), 1 );
    dest->writebuf( &big_zero, sizeof( uint_32 ), 1 );

    // now write the colour table and pixel data.
    uint_32 colour;

    _fp->open();
    _fp->reset( _dataPos );
    if( _headSize == BIH_SIZE ){
    for( int i=0; i<_colsUsed; i++ ){
        _fp->readbuf( &colour, 1, sizeof( uint_32 ) );
        dest->writebuf( &colour, sizeof( uint_32 ), 1 );
    }
    } else {
    colour = 0;
    for( int i=0; i<_colsUsed; i++ ){
        _fp->readbuf( &colour, 3 );
        dest->writebuf( &colour, sizeof( uint_32 ), 1 );
    }
    }

    CompOutFile     riter( dest );
    CompReader      reader( &riter );
    char        *buffer = new char[BLOCK_SIZE];
    int         blocksize;
    int         count = _pixOffset;

    while( count < _fileSize ){
    blocksize = _fp->readbuf( buffer, BLOCK_SIZE );
    count += blocksize;
    reader.compress( buffer, blocksize );
    }

    delete[] buffer;
    reader.flush();

    _fp->close();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?