📄 bmp.c
字号:
/* * Stand alone BMP library. * Copyright (c) 2006 Rene Rebe <rene@exactcode.de> * * based on: * * Project: libtiff tools * Purpose: Convert Windows BMP files in TIFF. * Author: Andrey Kiselev, dron@remotesensing.org * ****************************************************************************** * Copyright (c) 2004, Andrey Kiselev <dron@remotesensing.org> * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#ifndef WIN32#include <unistd.h>#else#include <io.h>#define open _open#define close _close#define read _read#define lseek _lseek#endif#ifdef HAVE_BYTESWAP_H#include <byteswap.h>#define BMPSwabShort(x) *x = bswap_16 (*x)#define BMPSwabLong(x) *x = bswap_32 (*x)#else#define BMPSwabShort(x) *x = ((((*x) >> 8) & 0xffu) | (((*x) & 0xffu) << 8))#define BMPSwabLong(x) *x = \ ((((*x) & 0xff000000u) >> 24) | (((*x) & 0x00ff0000u) >> 8) | \ (((*x) & 0x0000ff00u) << 8) | (((*x) & 0x000000ffu) << 24))#endif#ifdef WIN32typedef short int16;typedef unsigned short uint16;typedef int int32;typedef unsigned int uint32;#else#include <inttypes.h>typedef int16_t int16;typedef uint16_t uint16;typedef int32_t int32;typedef uint32_t uint32;#endif#include "bmp.h"#ifndef O_BINARY# define O_BINARY 0#endifenum BMPType { BMPT_WIN4, /* BMP used in Windows 3.0/NT 3.51/95 */ BMPT_WIN5, /* BMP used in Windows NT 4.0/98/Me/2000/XP */ BMPT_OS21, /* BMP used in OS/2 PM 1.x */ BMPT_OS22 /* BMP used in OS/2 PM 2.x */ };/* * Bitmap file consists of a BMPFileHeader structure followed by a * BMPInfoHeader structure. An array of BMPColorEntry structures (also called * a colour table) follows the bitmap information header structure. The colour * table is followed by a second array of indexes into the colour table (the * actual bitmap data). Data may be comressed, for 4-bpp and 8-bpp used RLE * compression. * * +---------------------+ * | BMPFileHeader | * +---------------------+ * | BMPInfoHeader | * +---------------------+ * | BMPColorEntry array | * +---------------------+ * | Colour-index array | * +---------------------+ * * All numbers stored in Intel order with least significant byte first. */enum BMPComprMethod { BMPC_RGB = 0L, /* Uncompressed */ BMPC_RLE8 = 1L, /* RLE for 8 bpp images */ BMPC_RLE4 = 2L, /* RLE for 4 bpp images */ BMPC_BITFIELDS = 3L, /* Bitmap is not compressed and the colour table * consists of three DWORD color masks that specify * the red, green, and blue components of each * pixel. This is valid when used with * 16- and 32-bpp bitmaps. */ BMPC_JPEG = 4L, /* Indicates that the image is a JPEG image. */ BMPC_PNG = 5L /* Indicates that the image is a PNG image. */ };enum BMPLCSType /* Type of logical color space. */ { BMPLT_CALIBRATED_RGB = 0, /* This value indicates that endpoints and * gamma values are given in the appropriate * fields. */ BMPLT_DEVICE_RGB = 1, BMPLT_DEVICE_CMYK = 2 };typedef struct{ int32 iCIEX; int32 iCIEY; int32 iCIEZ;} BMPCIEXYZ;typedef struct /* This structure contains the x, y, and z */{ /* coordinates of the three colors that */ /* correspond */ BMPCIEXYZ iCIERed; /* to the red, green, and blue endpoints for */ BMPCIEXYZ iCIEGreen; /* a specified logical color space. */ BMPCIEXYZ iCIEBlue;} BMPCIEXYZTriple;typedef struct{ char bType[2]; /* Signature "BM" */ uint32 iSize; /* Size in bytes of the bitmap file. Should * always be ignored while reading because * of error in Windows 3.0 SDK's description * of this field */ uint16 iReserved1; /* Reserved, set as 0 */ uint16 iReserved2; /* Reserved, set as 0 */ uint32 iOffBits; /* Offset of the image from file start in bytes */} BMPFileHeader;/* File header size in bytes: */const int BFH_SIZE = 14;typedef struct{ uint32 iSize; /* Size of BMPInfoHeader structure in bytes. * Should be used to determine start of the * colour table */ int32 iWidth; /* Image width */ int32 iHeight; /* Image height. If positive, image has bottom * left origin, if negative --- top left. */ int16 iPlanes; /* Number of image planes (must be set to 1) */ int16 iBitCount; /* Number of bits per pixel (1, 4, 8, 16, 24 * or 32). If 0 then the number of bits per * pixel is specified or is implied by the * JPEG or PNG format. */ uint32 iCompression; /* Compression method */ uint32 iSizeImage; /* Size of uncomressed image in bytes. May * be 0 for BMPC_RGB bitmaps. If iCompression * is BI_JPEG or BI_PNG, iSizeImage indicates * the size of the JPEG or PNG image buffer. */ int32 iXPelsPerMeter; /* X resolution, pixels per meter (0 if not used) */ int32 iYPelsPerMeter; /* Y resolution, pixels per meter (0 if not used) */ uint32 iClrUsed; /* Size of colour table. If 0, iBitCount should * be used to calculate this value * (1<<iBitCount). This value should be * unsigned for proper shifting. */ int32 iClrImportant; /* Number of important colours. If 0, all * colours are required */ /* * Fields above should be used for bitmaps, compatible with Windows NT 3.51 * and earlier. Windows 98/Me, Windows 2000/XP introduces additional fields: */ int32 iRedMask; /* Colour mask that specifies the red component * of each pixel, valid only if iCompression * is set to BI_BITFIELDS. */ int32 iGreenMask; /* The same for green component */ int32 iBlueMask; /* The same for blue component */ int32 iAlphaMask; /* Colour mask that specifies the alpha * component of each pixel. */ uint32 iCSType; /* Colour space of the DIB. */ BMPCIEXYZTriple sEndpoints; /* This member is ignored unless the iCSType * member specifies BMPLT_CALIBRATED_RGB. */ int32 iGammaRed; /* Toned response curve for red. This member * is ignored unless color values are * calibrated RGB values and iCSType is set to * BMPLT_CALIBRATED_RGB. Specified * in 16^16 format. */ int32 iGammaGreen; /* Toned response curve for green. */ int32 iGammaBlue; /* Toned response curve for blue. */} BMPInfoHeader;/* * Info header size in bytes: */const unsigned int BIH_WIN4SIZE = 40; /* for BMPT_WIN4 */const unsigned int BIH_WIN5SIZE = 57; /* for BMPT_WIN5 */const unsigned int BIH_OS21SIZE = 12; /* for BMPT_OS21 */const unsigned int BIH_OS22SIZE = 64; /* for BMPT_OS22 *//* * We will use plain byte array instead of this structure, but declaration * provided for reference */typedef struct{ char bBlue; char bGreen; char bRed; char bReserved; /* Must be 0 */} BMPColorEntry;/* * Image data in BMP file stored in BGR (or ABGR) format. We should rearrange * pixels to RGB (RGBA) format. */static voidrearrangePixels(unsigned char* buf, uint32 width, uint32 bit_count){ char tmp; uint32 i; switch(bit_count) { case 16: /* FIXME: need a sample file */ break; case 24: for (i = 0; i < width; i++, buf += 3) { tmp = *buf; *buf = *(buf + 2); *(buf + 2) = tmp; } break; case 32: { unsigned char* buf1 = buf; for (i = 0; i < width; i++, buf += 4) { tmp = *buf; *buf1++ = *(buf + 2); *buf1++ = *(buf + 1); *buf1++ = tmp; } } break; default: break; }}static int last_bit_set (int v){ unsigned int i; for (i = sizeof (int) * 8 - 1; i > 0; --i) { if (v & (1L << i)) return i; } return 0;} unsigned char* read_bmp (PSDoc *psdoc, const char* file, int* w, int* h, int* bps, int* spp, int* xres, int* yres, unsigned char** color_table, int* color_table_size, int* color_table_elements) { int fd; struct stat instat; BMPFileHeader file_hdr; BMPInfoHeader info_hdr; enum BMPType bmp_type; uint32 clr_tbl_size, n_clr_elems = 3; unsigned char *clr_tbl = NULL; uint32 row, stride; unsigned char* data = 0; fd = open(file, O_RDONLY|O_BINARY, 0); if (fd < 0) { ps_error(psdoc, PS_RuntimeError, _("Could not open bmp file.")); return 0; } read (fd, file_hdr.bType, 2); if(file_hdr.bType[0] != 'B' || file_hdr.bType[1] != 'M') { ps_error(psdoc, PS_RuntimeError, _("File is not a bmp file.")); goto bad; } /* -------------------------------------------------------------------- */ /* Read the BMPFileHeader. We need iOffBits value only */ /* -------------------------------------------------------------------- */ lseek(fd, 10, SEEK_SET); read(fd, &file_hdr.iOffBits, 4);#ifdef WORDS_BIGENDIAN BMPSwabLong(&file_hdr.iOffBits);#endif fstat(fd, &instat); file_hdr.iSize = instat.st_size; /* -------------------------------------------------------------------- */ /* Read the BMPInfoHeader. */ /* -------------------------------------------------------------------- */ lseek(fd, BFH_SIZE, SEEK_SET); read(fd, &info_hdr.iSize, 4);#ifdef WORDS_BIGENDIAN BMPSwabLong(&info_hdr.iSize);#endif if (info_hdr.iSize == BIH_WIN4SIZE) bmp_type = BMPT_WIN4; else if (info_hdr.iSize == BIH_OS21SIZE) bmp_type = BMPT_OS21;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -