📄 readbmp.c
字号:
// $Id: readbmp.c,v 1.5 2000/11/20 05:46:45 ymwei Exp $//// Top-level bitmap file read/save function.//// Copyright (C) 2000, Wei Yongming.//// Current maintainer: Wei Yongming./*** This library is free software; you can redistribute it and/or** modify it under the terms of the GNU Library General Public** License as published by the Free Software Foundation; either** version 2 of the License, or (at your option) any later version.**** This library 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** Library General Public License for more details.**** You should have received a copy of the GNU Library General Public** License along with this library; if not, write to the Free** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,** MA 02111-1307, USA*/// Create date: 2000/08/26, derived from original bitmap.c//// Modify records://// Who When Where For What Status//-----------------------------------------------------------------------------//// TODO:// #include <stdio.h>#include <stdlib.h>#include <string.h>#include "common.h"#include "gdi.h"#include "window.h"#include "cliprect.h"#include "gal.h"#include "internals.h"#include "dc.h"#include "readbmp.h"/* * The idea comes from readbmp.c in Allegro by Shawn Hargreaves. */typedef struct{ char ext[8]; int (*load) (FILE* fp, MYBITMAP *bmp, RGB *pal); int (*save) (FILE* fp, MYBITMAP *bmp, RGB *pal);} BITMAP_TYPE_INFO;#define MAX_BITMAP_TYPES 8static BITMAP_TYPE_INFO bitmap_types [MAX_BITMAP_TYPES] ={ { "bmp", load_bmp, #ifdef _SAVE_BITMAPsave_bmp },#elseNULL },#endif#ifdef _LBM_FILE_SUPPORT { "lbm", load_lbm, NULL },#else { "", NULL, NULL },#endif#ifdef _PCX_FILE_SUPPORT { "pcx", load_pcx, NULL },#else { "", NULL, NULL },#endif#ifdef _TGA_FILE_SUPPORT { "tga", load_tga, NULL },#else { "", NULL, NULL },#endif#ifdef _GIF_FILE_SUPPORT { "gif", load_gif, NULL },#else { "", NULL, NULL },#endif#ifdef _JPG_FILE_SUPPORT { "jpg", load_jpg, NULL },#else { "", NULL, NULL },#endif#ifdef _PNG_FILE_SUPPORT { "png", NULL, NULL },#else { "", NULL, NULL },#endif { "", NULL, NULL },};/* RegisterBitmapFileType * Informs Allegro of a new image file type, telling it how to load and * save files of this format (either function may be NULL). */BOOL GUIAPI RegisterBitmapFileType (const char *ext, int (*load) (FILE* fp, MYBITMAP *bmp, RGB *pal), int (*save) (FILE* fp, MYBITMAP *bmp, RGB *pal)){ int i; for (i = 0; i < MAX_BITMAP_TYPES; i++) { if ((!bitmap_types[i].ext [0]) || (strcasecmp (bitmap_types[i].ext, ext) == 0)) { strncpy (bitmap_types[i].ext, ext, sizeof (bitmap_types[i].ext) - 1); bitmap_types[i].ext [sizeof (bitmap_types[i].ext) - 1] = 0; bitmap_types[i].load = load; bitmap_types[i].save = save; return TRUE; } } return FALSE;}#define PIX2BYTES(n) (((n)+7)/8)/* * compute image line size and bytes per pixel * from bits per pixel and width */int bmpComputePitch(int bpp, int width, int *pitch, BOOL does_round){ int linesize; int bytespp = 1; if(bpp == 1) linesize = PIX2BYTES (width); else if(bpp <= 4) linesize = PIX2BYTES (width << 2); else if (bpp <= 8) linesize = width; else if(bpp <= 16) { linesize = width * 2; bytespp = 2; } else if(bpp <= 24) { linesize = width * 3; bytespp = 3; } else { linesize = width * 4; bytespp = 4; } /* rows are DWORD right aligned*/ if (does_round) *pitch = (linesize + 3) & -4; else *pitch = linesize; return bytespp;}void bmpSetBitsInLine (int bpp, BYTE* bits, int pos, BYTE* value){ int offset, shift; switch (bpp) { case 1: offset = pos / 8; shift = 8 - (pos % 8); bits [offset] |= (*value & 0x01) << shift; break; case 4: offset = pos / 2; shift = 4 - ((pos % 2) << 2); bits [offset] |= (*value & 0x0F) << shift; break; case 8: offset = pos; bits [offset] |= *value; break; case 15: case 16: offset = pos * 2; bits [offset] |= value [0]; bits [offset + 1] |= value [1]; break; case 24: offset = pos * 3; bits [offset] |= value [0]; bits [offset + 1] |= value [1]; bits [offset + 2] |= value [2]; break; case 32: offset = pos * 4; bits [offset] |= value [0]; bits [offset + 1] |= value [1]; bits [offset + 2] |= value [2]; bits [offset + 3] |= value [3]; break; }}static const char* get_extension (const char* filename){ const char* ext; ext = strrchr (filename, '.'); if (ext) return ext + 1; return NULL;}/* Funtion: int LoadBitmap (HDC hdc, PBITMAP pBitmap, const char* spFileName); * This function load a bitmap from BMP file and fill * the specified BITMAP struct. * Return: success: the size of bmBits. * failure: -1. */int GUIAPI LoadBitmap (HDC hdc, PBITMAP pBitmap, const char* spFileName){ FILE* fp; PDC pdc; int type, i; const char* ext; MYBITMAP myBitmap; RGB pal [256]; int load_ret; if ((ext = get_extension (spFileName)) == NULL) return ERR_BMP_UNKNOWN_TYPE; for (type = 0; type < MAX_BITMAP_TYPES; type++) { if ((bitmap_types[type].ext [0]) && (strcasecmp (bitmap_types[type].ext, ext) == 0)) break; } if (type == MAX_BITMAP_TYPES) return ERR_BMP_UNKNOWN_TYPE; if (bitmap_types[type].load == NULL) { return ERR_BMP_CANT_READ; } if( !(fp = fopen (spFileName, "rb"))) { return ERR_BMP_FILEIO; } pdc = dc_HDC2PDC (hdc); myBitmap.bits = NULL; myBitmap.frames = 1; myBitmap.transparent = -1; myBitmap.depth = GAL_BitsPerPixel (pdc->gc); if (myBitmap.depth <= 8) { for (i = 0; i < GAL_Colors (pdc->gc); i++) GAL_GetPalette (pdc->gc, i, 1, (gal_color*)(pal + i)); } myBitmap.rgb_order = RGB_ORDER_BGR; myBitmap.flags = LOADBMP_FLAG_NONE; if (GRAYSCALESCREEN) myBitmap.flags |= LOADBMP_FLAG_GRAYSCALE; if ((load_ret = bitmap_types[type].load (fp, &myBitmap, pal)) != 0) { free (myBitmap.bits); fclose (fp); return load_ret; } fclose (fp); if (!(pBitmap->bmBits = malloc ( (size_t)myBitmap.w * myBitmap.h * GAL_BytesPerPixel (pdc->gc)))) { free (myBitmap.bits); return ERR_BMP_MEM; } /* TODO: handle transparent bitmap */ pBitmap->bmWidth = myBitmap.w; pBitmap->bmHeight = myBitmap.h; switch (myBitmap.depth) { case 1: ExpandMonoBitmap (hdc, myBitmap.w, myBitmap.h, myBitmap.bits, myBitmap.flow, myBitmap.pitch, pBitmap->bmBits, GAL_MapColor (pdc->gc, (gal_color*)pal), GAL_MapColor (pdc->gc, (gal_color*)(pal + 1))); break; case 4: Expand16CBitmap (hdc, myBitmap.w, myBitmap.h, myBitmap.bits, myBitmap.flow, myBitmap.pitch, pBitmap->bmBits, pal); break; case 8: Expand256CBitmap (hdc, myBitmap.w, myBitmap.h, myBitmap.bits, myBitmap.flow, myBitmap.pitch, pBitmap->bmBits, pal); break; case 24: CompileRGBBitmap (hdc, myBitmap.w, myBitmap.h, myBitmap.bits, myBitmap.flow, myBitmap.pitch, pBitmap->bmBits, myBitmap.rgb_order); break; default: free (myBitmap.bits); return ERR_BMP_NOT_SUPPORTED; } free (myBitmap.bits); return ERR_BMP_OK;}#ifdef _SAVE_BITMAPint GUIAPI SaveBitmap (HDC hdc, PBITMAP pBitmap, const char* spFileName){ FILE* fp; PDC pdc; int type, i; const char* ext; MYBITMAP myBitmap; RGB pal [256]; int save_ret; if ((ext = get_extension (spFileName)) == NULL) return ERR_BMP_UNKNOWN_TYPE; for (type = 0; type < MAX_BITMAP_TYPES; type++) { if ((bitmap_types[type].ext [0]) && (strcasecmp (bitmap_types[type].ext, ext) == 0)) break; } if (type == MAX_BITMAP_TYPES) return ERR_BMP_UNKNOWN_TYPE; if (bitmap_types[type].save == NULL) return ERR_BMP_CANT_SAVE; pdc = dc_HDC2PDC (hdc); switch (GAL_BitsPerPixel (pdc->gc)) { case 4: for (i = 0; i < 16; i++) GAL_GetPalette (pdc->gc, i, 1, (gal_color*)(pal + i)); break; case 8: for (i = 0; i < 256; i++) GAL_GetPalette (pdc->gc, i, 1, (gal_color*)(pal + i)); break; } myBitmap.depth = GAL_BitsPerPixel (pdc->gc); myBitmap.w = pBitmap->bmWidth; myBitmap.h = pBitmap->bmHeight; myBitmap.size = myBitmap.w * myBitmap.h * GAL_BytesPerPixel (pdc->gc); myBitmap.bits = pBitmap->bmBits; if (!(fp = fopen (spFileName, "wb+"))) {#ifdef _DEBUG fprintf (stderr, "Saving BMP file: fopen error.\n");#endif return ERR_BMP_FILEIO; } save_ret = bitmap_types[type].save (fp, &myBitmap, pal); fclose (fp); return save_ret;}#endif// this function unloads bitmapvoid GUIAPI UnloadBitmap (PBITMAP pBitmap){ free (pBitmap->bmBits);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -