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

📄 bmpimage.cpp

📁 本程序是计算机视觉稠密匹配的程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 *
 *  This code from Dr. Dobbs Journal, March 1995. Copyright information unavailable.
 *  http://www.ddj.com/ftp/1995/1995.03/bmp.zip
 *
 */

#include <stdafx.h>
#include "Image.h"
#include "BMPImage.h"

/*****************************************************************************
*
* Read functions.  All read functions take an open file pointer as the first
* parameter and a pointer to data as the second parameter.  The return value
* will be 0 on success, and EOF on failure.  If successful, the second
* parameter will point to the data read.
*/

/*
 * The INT8 and UINT8 types are stored as a single byte on disk.  The INT8
 * type is a signed integer with range (-128..127).  The UINT8 type is an
 * unsigned integer with range (0..255).
 */
int CBMPImage::readINT8little(FILE *f, INT8 *i)
{
    int rc;
    
    rc = fgetc(f);
    if (rc == EOF)
	return rc;
    
    *i = (INT8) (rc & 0xff);
    return 0;
}

int CBMPImage::readUINT8little(FILE *f, UINT8 *i)
{
    int  rc;
    
    rc = fgetc(f);
    if (rc == EOF)
    {
        return rc;
    }
    
    *i = (UINT8) (rc & 0xff);
    return 0;
}


/*
 * The INT16 and UINT16 types are stored as two bytes on disk.  The INT16 type
 * is a signed integer with range (-32768..32767).  The UINT16 type is an
 * unisgned integer with range (0..65535).
 */
int CBMPImage::readINT16little(FILE *f, INT16 *i)
{
    int rc;
    INT16 temp = 0;
    
    temp = (INT16) (fgetc(f) & 0xff);
    
    rc = fgetc(f);
    if (rc == EOF)
	return rc;
    
    temp |= ((rc & 0xff) << 8);
    *i = temp;
    return 0;
}

int CBMPImage::readUINT16little(FILE *f, UINT16 *i)
{
    int rc;
    UINT16 temp = 0;
    
    temp = (UINT16) (fgetc(f) & 0xff);
    
    rc = fgetc(f);
    if (rc == EOF)
	return rc;
    
    temp |= ((rc & 0xff) << 8);
    *i = temp;
    return 0;
}

/*
 * The INT32 and UINT32 types are stored as four bytes on disk.  The INT32
 * type is a signed integer with range (-2147483648..2147483647).  The UINT32
 * type is an unisgned integer with range (0..4294967295).
 */
int CBMPImage::readINT32little(FILE *f, INT32 *i)
{
    int rc;
    INT32 temp = 0;
    
    temp = ((long)fgetc(f) & 0xff);
    temp |= (((long)fgetc(f) & 0xff) << 8);
    temp |= (((long)fgetc(f) & 0xff) << 16);
    
    rc = fgetc(f);
    if (rc == EOF)
	return rc;
    
    temp |= (((long)rc & 0xff) << 24);
    *i = temp;
    return 0;
}

int CBMPImage::readUINT32little(FILE *f, UINT32 *i)
{
    int rc;
    UINT32 temp = 0;
    
    temp = ((long)fgetc(f) & 0xff);
    temp |= (((long)fgetc(f) & 0xff) << 8);
    temp |= (((long)fgetc(f) & 0xff) << 16);
    
    rc = fgetc(f);
    if (rc == EOF)
	return rc;
    
    temp |= (((long)rc & 0xff) << 24);
    *i = temp;
    return 0;
}

/*****************************************************************************
*
* Write functions.  All write functions take an open file pointer as the first
* parameter and a data as the second parameter.  The return value will be 0 on
* success, and EOF on failure.  If successful, the second parameter will have
* been written to the open file.
*/

int CBMPImage::writeINT8little(FILE *f, INT8 i)
{
    return fputc(i, f);
}

int CBMPImage::writeUINT8little(FILE *f, UINT8 i)
{
    return fputc(i, f);
}

int CBMPImage::writeINT16little(FILE *f, INT16 i)
{
    int rc;
    
    rc = fputc((i & 0xff), f);
    if (rc == EOF)
	return rc;
    
    return fputc(((i >> 8) & 0xff), f);
}

int CBMPImage::writeUINT16little(FILE *f, UINT16 i)
{
    int rc;
    
    rc = fputc((i & 0xff), f);
    if (rc == EOF)
	return rc;
    
    return fputc(((i >> 8) & 0xff), f);
}

int CBMPImage::writeINT32little(FILE *f, INT32 i)
{
    int rc;
    
    rc = fputc((i & 0xff), f);
    if (rc == EOF)
	return rc;
    
    rc = fputc(((i >> 8) & 0xff), f);
    if (rc == EOF)
	return rc;
    
    rc = fputc(((i >> 16) & 0xff), f);
    if (rc == EOF)
	return rc;
    
    return fputc(((i >> 24) & 0xff), f);
}


int CBMPImage::writeUINT32little(FILE *f, UINT32 i)
{
    int rc;
    
    rc = fputc((i & 0xff), f);
    if (rc == EOF)
	return rc;
    
    rc = fputc(((i >> 8) & 0xff), f);
    if (rc == EOF)
	return rc;
    
    rc = fputc(((i >> 16) & 0xff), f);
    if (rc == EOF)
	return rc;
    
    return fputc(((i >> 24) & 0xff), f);
}

/*****************************************************************************
 *
 * Mid-level functions.
 *
 * These functions read in the various structures defined in bmptypes.h.  Each
 * function assumes that the file pointer is positioned at the start of the
 * given structure.  Upon completion, each function will leave the file
 * pointer positioned on the byte immediately following the structure.  Return
 * values will be 0 for success and non-zero for failure.  In all cases, a
 * return value of non-zero means that the file position has been left in an
 * indeterminate state and further reading should not be attempted.
 */

/*
 * Read a BITMAPFILEHEADER structure.
 */
int CBMPImage::readBitmapFileHeader(FILE *fp, BITMAPFILEHEADER *bfh)
{
    int rc;
  
    rc = readUINT16little(fp, &(bfh->type));
    if (rc != 0)
	return rc;
    
    rc = readUINT32little(fp, &(bfh->size));
    if (rc != 0)
	return rc;
    
    rc = readINT16little(fp, &(bfh->xHotspot));
    if (rc != 0)
	return rc;
    
    rc = readINT16little(fp, &(bfh->yHotspot));
    if (rc != 0)
	return rc;
    
    rc = readUINT32little(fp, &(bfh->offsetToBits));
    return rc;
}

/*
 * Read a BITMAPARRAYHEADER
 */
int CBMPImage::readBitmapArrayHeader(FILE *fp, BITMAPARRAYHEADER *bah)
{
    int rc;
    
    rc = readUINT16little(fp, &(bah->type));
    if (rc != 0)
	return rc;
    rc = readUINT32little(fp, &(bah->size));
    if (rc != 0)
	return rc;
    rc = readUINT32little(fp, &(bah->next));
    if (rc != 0)
	return rc;
    rc = readUINT16little(fp, &(bah->screenWidth));
    if (rc != 0)
	return rc;
    rc = readUINT16little(fp, &(bah->screenHeight));
    return rc;
}

/*
 * Read the BITMAPHEADER structure.  This one requires a bit of sanity
 * checking.  The length of the structure on the disk is specified in the
 * first field.  We must stop reading after that many bytes, and if that value
 * is longer than sizeof(BITMAPHEADER), we must skip over any leftover bytes.
 * Finally, if size is 12, then width an height are really 16-bit values, and
 * we have to read them differently so they'll be properly stored in the
 * 32-bit fields BITMAPHEADER uses.
 */
int CBMPImage::readBitmapHeader(FILE *fp, BITMAPHEADER *bh)
{
    int    rc, oldFormat;
    unsigned int bytesRead;
    UINT16 tempVal;
    
    /*
     * Clear the structure.  Default values for all fields are zeros.  This
     * will prevent garbage from being returned if the structure is truncated
     * on disk.
     */
    memset(bh, 0, sizeof(BITMAPHEADER));
    
    /*
     * Read the size of the structure.  From here on in, we'll have to be sure
     * we don't read more bytes than this value.
     */
    rc = readUINT32little(fp, &(bh->size));
    if (rc != 0)
	return rc;
    bytesRead = 4;
    
    /*
     * If the size is 12 bytes or less, than this is an "old format"
     * structure.  So the width and height fields will have to be read
     * differently.
     */
    if (bh->size <= 12)
	oldFormat = 1;
    else
	oldFormat = 0;
    
    /*
     * Width and height are read differently for old and new format files.  In
     * the old format, they're 16-bit values.  In the new format, they're
     * 32-bits long.
     */
    if (oldFormat)
    {
	rc = readUINT16little(fp, &tempVal);
	if (rc != 0)
	    return rc;
	bh->width = tempVal;
	bytesRead += 2;
    }
    else
    {
	rc = readINT32little(fp, &(bh->width));
	if (rc != 0)
	    return rc;
	bytesRead += 4;
    }
    if (bytesRead >= bh->size)
	return 0;
    
    if (oldFormat)
    {
	rc = readUINT16little(fp, &tempVal);
	if (rc != 0)
	    return rc;
	bh->height = tempVal;
	bytesRead += 2;
    }
    else
    {
	rc = readINT32little(fp, &(bh->height));
	if (rc != 0)
	    return rc;
	bytesRead += 4;
    }
    if (bytesRead >= bh->size)
	return 0;
    
    /*
     * From this point on, old and new formats are identical to each other,
     * and we can proceed as if there was no difference.  For each field, we
     * read it in and increment the count of bytes read.  If at any time we
     * have read the amount we got earlier (in the size field), then stop and
     * leave the rest of the fields as zeros.
     */
    rc = readUINT16little(fp, &(bh->numBitPlanes));
    if (rc != 0)
	return rc;
    bytesRead += 2;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT16little(fp, &(bh->numBitsPerPlane));
    if (rc != 0)
	return rc;
    bytesRead += 2;
    if (bytesRead >= bh->size)
	return 0;
  
    /*
     * Old format stop here.  But we don't have to check, because in that
     * format, 12 bytes have been read and the function will have exited 
     * without any extra checking.
     */
    rc = readUINT32little(fp, &(bh->compressionScheme));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->sizeOfImageData));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->xResolution));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->yResolution));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->numColorsUsed));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->numImportantColors));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT16little(fp, &(bh->resolutionUnits));
    if (rc != 0)
	return rc;
    bytesRead += 2;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT16little(fp, &(bh->padding));
    if (rc != 0)
	return rc;
    bytesRead += 2;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT16little(fp, &(bh->origin));
    if (rc != 0)
	return rc;
    bytesRead += 2;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT16little(fp, &(bh->halftoning));
    if (rc != 0)
	return rc;
    bytesRead += 2;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->halftoningParam1));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->halftoningParam2));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
  
    rc = readUINT32little(fp, &(bh->colorEncoding));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    rc = readUINT32little(fp, &(bh->identifier));
    if (rc != 0)
	return rc;
    bytesRead += 4;
    if (bytesRead >= bh->size)
	return 0;
    
    /*
     * If there are more bytes in the file than this, then the file is using a
     * future format that doesn't exist yet.  Skip over the bytes.  Assuming
     * this future format somewhat resembles what we know now, ignoring the
     * fields will be safe.  We _MUST_ skip them, though, since the color
     * table begins on the byte after this structure, and we have to position
     * the file pointer there.
     */
    return fseek(fp, (bh->size - bytesRead), SEEK_CUR);
}


/*
 * readRgb reads in a single RGB structure from the disk.  The numBytes field
 * indicates how many bytes the field occupies on the disk.  It assumes that
 * each component is one byte on disk and the rest is padding.  This will
 * compensate for the old/new differences in color tables.  (Old format
 * bitmaps use 3 bytes per entry, while new format bitmaps use 4.)  Note how
 * it will never read more than the number of bytes requested.
 */
int CBMPImage::readRgb(FILE *fp, RGB *rgb, int numBytes)
{
    int rc;
    
    if (numBytes == 0)
	return 0;
    rc = readUINT8little(fp, &(rgb->blue));
    if (rc != 0)
	return rc;
    
    if (numBytes == 1)
	return 0;
    rc = readUINT8little(fp, &(rgb->green));
    if (rc != 0)
	return rc;
    
    if (numBytes == 2)
	return 0;
    rc = readUINT8little(fp, &(rgb->red));
    if (rc != 0)
	return rc;
    
    if (numBytes == 3)
	return 0;
    
    /* Skip over extra bytes if more than three were requested */
    return fseek(fp, (numBytes - 3), SEEK_CUR);
}

/*
 * A color table is a block of RGB structures, all the same size.  Read it by
 * calling readRgb repeatedly.
 */
int CBMPImage::readColorTable(FILE *fp, RGB *rgb, int numEntries, int numBytesPerEntry)
{
    int i, rc;
    
    for (i=0; i<numEntries; i++)
    {
	rc = readRgb(fp, &(rgb[i]), numBytesPerEntry);
	if (rc != 0)
	    return rc;
    }
    return 0;
}


/*
 * ReadBitsUncompressed.  Reads pixel values into an array of RGB
 * values.  It assmes that there is no compression.  Note that there we're
 * only handling bit depths of 1, 4, 8, 16, and 24. Note that OS/2 bitmaps
 * can (in theory) have any number of bits per pixel, so you might find a

⌨️ 快捷键说明

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