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

📄 mybmp.c

📁 在ADS环境下MiniGUI的源码
💻 C
字号:
/*
** $Id: mybmp.c,v 1.10 2004/08/03 11:01:57 panweiguo Exp $
**
** Top-level bitmap file read/save function.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 2000 ~ 2002 Wei Yongming.
**
** Current maintainer: Wei Yongming.
**
** Create date: 2001/12/17, derived from original ../newgdi/readbmp.c
*/

/*
** 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 of the License, or
** (at your option) any later 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, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "readbmp.h"

/*
 * The idea comes from readbmp.c in Allegro by Shawn Hargreaves.
 */

typedef struct
{
   char ext[8];
   int (*load) (MG_RWops* fp, MYBITMAP *bmp, RGB *pal);
   int (*save) (MG_RWops* fp, MYBITMAP *bmp, RGB *pal);
   BOOL (*check) (MG_RWops* fp);
} BITMAP_TYPE_INFO;

#define MAX_BITMAP_TYPES   8

static BITMAP_TYPE_INFO bitmap_types [MAX_BITMAP_TYPES] =
{
   { "bmp", __mg_load_bmp, 

#ifdef _SAVE_BITMAP
__mg_save_bmp, __mg_check_bmp },
#else
NULL, __mg_check_bmp },
#endif

#ifdef _LBM_FILE_SUPPORT
   { "lbm", __mg_load_lbm, NULL, __mg_check_lbm },
#else
   { "",    NULL,     NULL, NULL },
#endif
#ifdef _PCX_FILE_SUPPORT
   { "pcx", __mg_load_pcx, NULL, NULL },
#else
   { "",    NULL,     NULL, NULL },
#endif
#ifdef _TGA_FILE_SUPPORT
   { "tga", __mg_load_tga, NULL, NULL },
#else
   { "",    NULL,     NULL, NULL },
#endif
#ifdef _GIF_FILE_SUPPORT
   { "gif", __mg_load_gif, NULL, __mg_check_gif },
#else
   { "",    NULL,     NULL, NULL },
#endif
#ifdef _JPG_FILE_SUPPORT
   { "jpg", __mg_load_jpg, NULL, __mg_check_jpg },
#else
   { "",    NULL,     NULL, NULL },
#endif
#ifdef _PNG_FILE_SUPPORT
   { "png", __mg_load_png, NULL, __mg_check_png },
#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) (MG_RWops* fp, MYBITMAP *bmp, RGB *pal), 
            int (*save) (MG_RWops* fp, MYBITMAP *bmp, RGB *pal),
            BOOL (*check) (MG_RWops* fp))
{
    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;
	        bitmap_types[i].check = check;
	        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, Uint32 width, Uint32 *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;
}

static const char* get_extension (const char* filename)
{
    const char* ext;

    ext = strrchr (filename, '.');

    if (ext)
        return ext + 1;

    return NULL;
}

/* Function: int LoadMyBitmapEx (PMYBITMAP my_bmp, RGB* pal, MG_RWops* area, const char* ext);
 *      This function loads a bitmap from an image source and fills
 *      the specified MYBITMAP struct and returns the palette in pal if any.
 */
int GUIAPI LoadMyBitmapEx (PMYBITMAP my_bmp, RGB* pal, MG_RWops* area, const char* ext)
{
    int type;
    int load_ret;

    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;
    }

    my_bmp->flags = MYBMP_LOAD_NONE;
    my_bmp->bits = NULL;
    my_bmp->frames = 1;
    my_bmp->depth = GetGDCapability (HDC_SCREEN, GDCAP_DEPTH);

    if (my_bmp->depth <= 8)
        GetPalette (HDC_SCREEN, 0, 256, (GAL_Color*)pal);

#ifdef _GRAY_SCREEN
    my_bmp->flags |= MYBMP_LOAD_GRAYSCALE;
#endif

    if ((load_ret = bitmap_types[type].load (area, my_bmp, pal)) != 0) {
        free (my_bmp->bits);
        return load_ret;
    }

    if (my_bmp->depth == 0) {
        fprintf (stderr, "A bad implementation of load_bmp: %s.\n", ext);
        return ERR_BMP_LOAD;
    }

    return ERR_BMP_OK;
}

int GUIAPI LoadMyBitmapFromFile (PMYBITMAP my_bmp, RGB* pal, const char* file_name)
{
    MG_RWops* area;
    const char* ext;
    int ret_val;

    if ((ext = get_extension (file_name)) == NULL)
        return ERR_BMP_UNKNOWN_TYPE;

    if (!(area = MGUI_RWFromFile (file_name, "rb"))) {
        return ERR_BMP_FILEIO;
    }

    ret_val = LoadMyBitmapEx (my_bmp, pal, area, ext);

    MGUI_RWclose (area);

    return ret_val;
}

int GUIAPI LoadMyBitmapFromMem (PMYBITMAP my_bmp, RGB* pal, const void* mem, int size, const char* ext)
{
    MG_RWops* area;
    int ret_val;

    if (!(area = MGUI_RWFromMem ((void*)mem, size))) {
        return ERR_BMP_MEM;
    }

    ret_val = LoadMyBitmapEx (my_bmp, pal, area, ext);

    MGUI_RWclose (area);

    return ret_val;
}

void GUIAPI UnloadMyBitmap (PMYBITMAP my_bmp)
{
    free (my_bmp->bits);
}

const char* GUIAPI CheckBitmapType (MG_RWops* fp)
{
    int type;
    int start_pos = MGUI_RWseek (fp, 0, SEEK_CUR);

    for (type = 0; type < MAX_BITMAP_TYPES; type++) {
        if (bitmap_types[type].check) {
            if (bitmap_types[type].check (fp)) {
                MGUI_RWseek (fp, start_pos, SEEK_SET);
                return bitmap_types[type].ext;
            }
            else {
                MGUI_RWseek (fp, start_pos, SEEK_SET);
            }
        }
    }

    return NULL;
}

#ifdef _SAVE_BITMAP
int GUIAPI SaveMyBitmapToFile (PMYBITMAP my_bmp, RGB* pal, const char* spFileName)
{
    MG_RWops* fp;
    const char* ext;
    int type;
    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;

    if (!(fp = MGUI_RWFromFile (spFileName, "wb+"))) {
#ifdef _DEBUG
        fprintf (stderr, "Saving BMP file: fopen error.\n");
#endif
        return ERR_BMP_FILEIO;
    }

	save_ret = bitmap_types[type].save (fp, my_bmp, pal);
    MGUI_RWclose (fp);
    return save_ret;
}

#endif

⌨️ 快捷键说明

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