📄 bitmap.c
字号:
/*
* @(#)bitmap.c
*
* Copyright 1997-1999, Wes Cherry (mailto:wesc@technosis.com)
* 2000-2001, Aaron Ardiri (mailto:aaron@ardiri.com)
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, please write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Revisions:
* ==========
*
* pre 18-Jun-2000 <numerous developers>
* creation
* 18-Jun-2000 Aaron Ardiri
* GNU GPL documentation additions
*/
#ifndef __GNUC__
#pragma pack(2)
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <memory.h>
#include <string.h>
#include <ctype.h>
#include "RCP2C.h"
typedef unsigned char PILRC_BYTE; /* b */
typedef unsigned short PILRC_USHORT; /* us */
typedef unsigned int PILRC_ULONG; /* ul */
typedef int bool; /* f */
//
// data structures
//
/*
* Microsoft Windows .BMP file format
*/
typedef struct tagBITMAPFILEHEADER
{
#ifdef __GNUC__
PILRC_USHORT bfType; // gcc will only align the structure
PILRC_USHORT bfSize1; // correctly this way :P
PILRC_USHORT bfSize2;
PILRC_USHORT bfReserved1;
PILRC_USHORT bfReserved2;
PILRC_USHORT bfOffBits1;
PILRC_USHORT bfOffBits2;
#else
PILRC_USHORT bfType;
PILRC_ULONG bfSize;
PILRC_USHORT bfReserved1;
PILRC_USHORT bfReserved2;
PILRC_ULONG bfOffBits;
#endif
}
BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER
{
PILRC_ULONG biSize;
long biWidth;
long biHeight;
PILRC_USHORT biPlanes;
PILRC_USHORT biBitCount;
PILRC_ULONG biCompression;
PILRC_ULONG biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
PILRC_ULONG biClrUsed;
PILRC_ULONG biClrImportant;
}
BITMAPINFOHEADER;
typedef struct tagRGBQUAD
{
PILRC_BYTE rgbBlue;
PILRC_BYTE rgbGreen;
PILRC_BYTE rgbRed;
PILRC_BYTE rgbReserved;
}
RGBQUAD;
typedef struct tagBITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
}
BITMAPINFO;
// *INDENT-OFF*
/*
* The 1bit-2 color system palette for Palm Computing Devices.
*/
int PalmPalette1bpp[2][3] =
{
{ 255, 255, 255}, { 0, 0, 0 }
};
/*
* The 2bit-4 color system palette for Palm Computing Devices.
*/
int PalmPalette2bpp[4][3] =
{
{ 255, 255, 255}, { 192, 192, 192}, { 128, 128, 128 }, { 0, 0, 0 }
};
/*
* The 4bit-16 color system palette for Palm Computing Devices.
*/
int PalmPalette4bpp[16][3] =
{
{ 255, 255, 255}, { 238, 238, 238 }, { 221, 221, 221 }, { 204, 204, 204 },
{ 187, 187, 187}, { 170, 170, 170 }, { 153, 153, 153 }, { 136, 136, 136 },
{ 119, 119, 119}, { 102, 102, 102 }, { 85, 85, 85 }, { 68, 68, 68 },
{ 51, 51, 51}, { 34, 34, 34 }, { 17, 17, 17 }, { 0, 0, 0 }
};
/*
* The 4bit-16 color system palette for Palm Computing Devices.
*/
int PalmPalette4bppColor[16][3] =
{
{ 255, 255, 255}, { 128, 128, 128 }, { 128, 0, 0 }, { 128, 128, 0 },
{ 0, 128, 0}, { 0, 128, 128 }, { 0, 0, 128 }, { 128, 0, 128 },
{ 255, 0, 255}, { 192, 192, 192 }, { 255, 0, 0 }, { 255, 255, 0 },
{ 0, 255, 0}, { 0, 255, 255 }, { 0, 0, 255 }, { 0, 0, 0 }
};
/*
* The 8bit-256 color system palette for Palm Computing Devices.
*/
int PalmPalette8bpp[256][3] =
{
{ 255, 255, 255 }, { 255, 204, 255 }, { 255, 153, 255 }, { 255, 102, 255 },
{ 255, 51, 255 }, { 255, 0, 255 }, { 255, 255, 204 }, { 255, 204, 204 },
{ 255, 153, 204 }, { 255, 102, 204 }, { 255, 51, 204 }, { 255, 0, 204 },
{ 255, 255, 153 }, { 255, 204, 153 }, { 255, 153, 153 }, { 255, 102, 153 },
{ 255, 51, 153 }, { 255, 0, 153 }, { 204, 255, 255 }, { 204, 204, 255 },
{ 204, 153, 255 }, { 204, 102, 255 }, { 204, 51, 255 }, { 204, 0, 255 },
{ 204, 255, 204 }, { 204, 204, 204 }, { 204, 153, 204 }, { 204, 102, 204 },
{ 204, 51, 204 }, { 204, 0, 204 }, { 204, 255, 153 }, { 204, 204, 153 },
{ 204, 153, 153 }, { 204, 102, 153 }, { 204, 51, 153 }, { 204, 0, 153 },
{ 153, 255, 255 }, { 153, 204, 255 }, { 153, 153, 255 }, { 153, 102, 255 },
{ 153, 51, 255 }, { 153, 0, 255 }, { 153, 255, 204 }, { 153, 204, 204 },
{ 153, 153, 204 }, { 153, 102, 204 }, { 153, 51, 204 }, { 153, 0, 204 },
{ 153, 255, 153 }, { 153, 204, 153 }, { 153, 153, 153 }, { 153, 102, 153 },
{ 153, 51, 153 }, { 153, 0, 153 }, { 102, 255, 255 }, { 102, 204, 255 },
{ 102, 153, 255 }, { 102, 102, 255 }, { 102, 51, 255 }, { 102, 0, 255 },
{ 102, 255, 204 }, { 102, 204, 204 }, { 102, 153, 204 }, { 102, 102, 204 },
{ 102, 51, 204 }, { 102, 0, 204 }, { 102, 255, 153 }, { 102, 204, 153 },
{ 102, 153, 153 }, { 102, 102, 153 }, { 102, 51, 153 }, { 102, 0, 153 },
{ 51, 255, 255 }, { 51, 204, 255 }, { 51, 153, 255 }, { 51, 102, 255 },
{ 51, 51, 255 }, { 51, 0, 255 }, { 51, 255, 204 }, { 51, 204, 204 },
{ 51, 153, 204 }, { 51, 102, 204 }, { 51, 51, 204 }, { 51, 0, 204 },
{ 51, 255, 153 }, { 51, 204, 153 }, { 51, 153, 153 }, { 51, 102, 153 },
{ 51, 51, 153 }, { 51, 0, 153 }, { 0, 255, 255 }, { 0, 204, 255 },
{ 0, 153, 255 }, { 0, 102, 255 }, { 0, 51, 255 }, { 0, 0, 255 },
{ 0, 255, 204 }, { 0, 204, 204 }, { 0, 153, 204 }, { 0, 102, 204 },
{ 0, 51, 204 }, { 0, 0, 204 }, { 0, 255, 153 }, { 0, 204, 153 },
{ 0, 153, 153 }, { 0, 102, 153 }, { 0, 51, 153 }, { 0, 0, 153 },
{ 255, 255, 102 }, { 255, 204, 102 }, { 255, 153, 102 }, { 255, 102, 102 },
{ 255, 51, 102 }, { 255, 0, 102 }, { 255, 255, 51 }, { 255, 204, 51 },
{ 255, 153, 51 }, { 255, 102, 51 }, { 255, 51, 51 }, { 255, 0, 51 },
{ 255, 255, 0 }, { 255, 204, 0 }, { 255, 153, 0 }, { 255, 102, 0 },
{ 255, 51, 0 }, { 255, 0, 0 }, { 204, 255, 102 }, { 204, 204, 102 },
{ 204, 153, 102 }, { 204, 102, 102 }, { 204, 51, 102 }, { 204, 0, 102 },
{ 204, 255, 51 }, { 204, 204, 51 }, { 204, 153, 51 }, { 204, 102, 51 },
{ 204, 51, 51 }, { 204, 0, 51 }, { 204, 255, 0 }, { 204, 204, 0 },
{ 204, 153, 0 }, { 204, 102, 0 }, { 204, 51, 0 }, { 204, 0, 0 },
{ 153, 255, 102 }, { 153, 204, 102 }, { 153, 153, 102 }, { 153, 102, 102 },
{ 153, 51, 102 }, { 153, 0, 102 }, { 153, 255, 51 }, { 153, 204, 51 },
{ 153, 153, 51 }, { 153, 102, 51 }, { 153, 51, 51 }, { 153, 0, 51 },
{ 153, 255, 0 }, { 153, 204, 0 }, { 153, 153, 0 }, { 153, 102, 0 },
{ 153, 51, 0 }, { 153, 0, 0 }, { 102, 255, 102 }, { 102, 204, 102 },
{ 102, 153, 102 }, { 102, 102, 102 }, { 102, 51, 102 }, { 102, 0, 102 },
{ 102, 255, 51 }, { 102, 204, 51 }, { 102, 153, 51 }, { 102, 102, 51 },
{ 102, 51, 51 }, { 102, 0, 51 }, { 102, 255, 0 }, { 102, 204, 0 },
{ 102, 153, 0 }, { 102, 102, 0 }, { 102, 51, 0 }, { 102, 0, 0 },
{ 51, 255, 102 }, { 51, 204, 102 }, { 51, 153, 102 }, { 51, 102, 102 },
{ 51, 51, 102 }, { 51, 0, 102 }, { 51, 255, 51 }, { 51, 204, 51 },
{ 51, 153, 51 }, { 51, 102, 51 }, { 51, 51, 51 }, { 51, 0, 51 },
{ 51, 255, 0 }, { 51, 204, 0 }, { 51, 153, 0 }, { 51, 102, 0 },
{ 51, 51, 0 }, { 51, 0, 0 }, { 0, 255, 102 }, { 0, 204, 102 },
{ 0, 153, 102 }, { 0, 102, 102 }, { 0, 51, 102 }, { 0, 0, 102 },
{ 0, 255, 51 }, { 0, 204, 51 }, { 0, 153, 51 }, { 0, 102, 51 },
{ 0, 51, 51 }, { 0, 0, 51 }, { 0, 255, 0 }, { 0, 204, 0 },
{ 0, 153, 0 }, { 0, 102, 0 }, { 0, 51, 0 }, { 17, 17, 17 },
{ 34, 34, 34 }, { 68, 68, 68 }, { 85, 85, 85 }, { 119, 119, 119 },
{ 136, 136, 136 }, { 170, 170, 170 }, { 187, 187, 187 }, { 221, 221, 221 },
{ 238, 238, 238 }, { 192, 192, 192 }, { 128, 0, 0 }, { 128, 0, 128 },
{ 0, 128, 0 }, { 0, 128, 128 }, { 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }
};
#define COLOR_TABLE_SIZE 1026
// *INDENT-ON*
//
// local function prototypes
//
// *INDENT-OFF*
static PILRC_ULONG LLoadX86(PILRC_ULONG w);
static PILRC_USHORT WLoadX86(PILRC_USHORT w);
static int BMP_RGBToColorIndex(int, int, int, int[][3], int);
static int BMP_GetBits1bpp(BITMAPINFO *, int, PILRC_BYTE *,
int, int, int, int *, int *, int *, int *);
static int BMP_GetBits4bpp(BITMAPINFO *, int, PILRC_BYTE *,
int, int, int, int *, int *, int *, int *);
static int BMP_GetBits8bpp(BITMAPINFO *, int, PILRC_BYTE *,
int, int, int, int *, int *, int *, int *);
static int BMP_GetBits16bpp(BITMAPINFO *, int, PILRC_BYTE *,
int, int, int, int *, int *, int *, int *);
static int BMP_GetBits24bpp(BITMAPINFO *, int, PILRC_BYTE *,
int, int, int, int *, int *, int *, int *);
static int BMP_GetBits32bpp(BITMAPINFO *, int, PILRC_BYTE *,
int, int, int, int *, int *, int *, int *);
static void BMP_SetBits1bpp(int, PILRC_BYTE *, int, int, int);
static void BMP_SetBits2bpp(int, PILRC_BYTE *, int, int, int, int);
static void BMP_SetBits4bpp(int, PILRC_BYTE *, int, int, int, int);
static void BMP_SetBits8bpp(int, PILRC_BYTE *, int, int, int, int);
static void BMP_SetBits16bpp(int, PILRC_BYTE *, int, int, int, int);
static void BMP_SetBits24bpp(int, PILRC_BYTE *, int, int, int, int);
static void BMP_SetBits32bpp(int, PILRC_BYTE *, int, int, int, int);
static void BMP_ConvertWindowsBitmap(RCBITMAP *, PILRC_BYTE *, int, BOOL, int *);
static void BMP_ConvertTextBitmap(RCBITMAP *, PILRC_BYTE *, int);
static void BMP_ConvertX11Bitmap(RCBITMAP *, PILRC_BYTE *, int);
static void BMP_ConvertPNMBitmap(RCBITMAP *, PILRC_BYTE *, int, int, BOOL);
static void BMP_CompressBitmap(RCBITMAP *, int, BOOL, BOOL);
static void BMP_CompressDumpBitmap(RCBITMAP *, int, int, BOOL, BOOL, BOOL, BOOL);
static void BMP_InvalidExtension(char *);
// *INDENT-ON*
//
// code
//
/**
* Convert a RGB triplet to a index within the PalmPalette256[][] table.
*
* @param r the red RGB value
* @param g the green RGB value
* @param b the blue RGB value
* @param palette a pointer to a color pallete array
* @param paletteSize the number of items in the palette array (triples)
* @return the index of the RGB triplet in the palette table.
*/
static int
BMP_RGBToColorIndex(int r,
int g,
int b,
int palette[][3],
int paletteSize)
{
int index, lowValue, i, *diffArray;
// generate the color "differences" for all colors in the palette
diffArray = (int *)malloc(paletteSize * sizeof(int));
for (i = 0; i < paletteSize; i++)
{
diffArray[i] = ((palette[i][0] - r) * (palette[i][0] - r)) +
((palette[i][1] - g) * (palette[i][1] - g)) +
((palette[i][2] - b) * (palette[i][2] - b));
}
// find the palette index that has the smallest color "difference"
// OLD ALGORITHM
//
// index = 0;
// lowValue = diffArray[0];
// for (i=1; i<paletteSize; i++) {
// NEW ALGORITHM
//
// by Scott Ludwig - ensures (0,0,0) in 8bpp color is index 255
index = paletteSize - 1;
lowValue = diffArray[index];
for (i = index - 1; i >= 0; i--)
{
if (diffArray[i] < lowValue)
{
lowValue = diffArray[i];
index = i;
}
}
// clean up
free(diffArray);
return index;
}
/**
* Convert an unsigned long from x86 to Palm Computing Platform format.
*
* @param ul the unsigned long to convert
* @return the unsigned long in Palm Computing Platform format.
*/
static PILRC_ULONG
LLoadX86(PILRC_ULONG ul)
{
PILRC_BYTE *pb;
PILRC_ULONG ulOut;
pb = (PILRC_BYTE *) & ul;
ulOut =
(PILRC_ULONG) ((*(pb + 3) << 24) | (*(pb + 2) << 16) |
(*(pb + 1) << 8) | (*pb));
return ulOut;
}
/**
* Convert an unsigned short from x86 to Palm Computing Platform format.
*
* @param ul the unsigned short to convert
* @return the unsigned short in Palm Computing Platform format.
*/
static PILRC_USHORT
WLoadX86(PILRC_USHORT w)
{
PILRC_BYTE *pb;
PILRC_USHORT wOut;
pb = (PILRC_BYTE *) & w;
wOut = (PILRC_USHORT) ((*(pb + 1) << 8) | (*pb));
return wOut;
}
/**
* Get the number of bytes each bitmap row requires.
*
* @param cx the width of the bitmap.
* @param cbpp the number of bits per byte.
* @param cBitsAlign the os-dependant byte alignment definition.
* @return the number of bytes each bitmap row requires.
*/
static int
BMP_CbRow(int cx,
int cbpp,
int cBitsAlign)
{
return ((cx * cbpp + (cBitsAlign - 1)) & ~(cBitsAlign - 1)) >> 3;
}
/**
* Get a single bit from a 1bpp bitmap
*
* @param pbmi bitmap information
* @param cx the width of the bitmap.
* @param pb a reference to the bitmap resource.
* @param x the x-coordinate of the pixel to process.
* @param y the y-coordinate of the pixel to process.
* @param cBitsAlign the os-dependant byte alignment definition.
* @param a alpha channel of pixel
* @param r red channel of pixel
* @param g green channel of pixel
* @param b blue channel of pixel
* @return zero if the bit not set, non-zero otherwise.
*/
static int
BMP_GetBits1bpp(BITMAPINFO * pbmi,
int cx,
PILRC_BYTE * pb,
int x,
int y,
int cBitsAlign,
int *a,
int *r,
int *g,
int *b)
{
int cbRow;
int w;
cbRow = BMP_CbRow(cx, 1, cBitsAlign);
pb += cbRow * y + (x >> 3);
w = (*pb & (0x01 << (7 - (x & 7)))) ? 1 : 0;
// return the values we need
*a = 0;
*r = pbmi->bmiColors[w].rgbRed;
*g = pbmi->bmiColors[w].rgbGreen;
*b = pbmi->bmiColors[w].rgbBlue;
return w;
}
/**
* Set a single bit in a 1bpp bitmap
*
* @param cx the width of the bitmap.
* @param pb a reference to the bitmap resource.
* @param x the x-coordinate of the pixel to process.
* @param y the y-coordinate of the pixel to process.
* @param cBitsAlign the os-dependant byte alignment definition.
*/
static void
BMP_SetBits1bpp(int cx,
PILRC_BYTE * pb,
int x,
int y,
int cBitsAlign)
{
int cbRow;
cbRow = BMP_CbRow(cx, 1, cBitsAlign);
pb += cbRow * y + (x >> 3);
*pb |= (0x01 << (7 - (x & 7)));
}
/**
* Set bits in a 2bpp bitmap
*
* @param cx the width of the bitmap.
* @param pb a reference to the bitmap resource.
* @param x the x-coordinate of the pixel to process.
* @param y the y-coordinate of the pixel to process.
* @param bits the bits to set (0..3).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -