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

📄 winbmp.c

📁 在ADS环境下MiniGUI的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
            pixel = fp_igetw (f);   /* read the gap */

        bits += pitch;
    }
}

/* __mg_load_bmp:
 *  Loads a Windows BMP file, returning in the my_bitmap structure and storing
 *  the palette data in the specified palette (this should be an array of
 *  at least 256 RGB structures).
 *
 *  Thanks to Seymour Shlien for contributing this function.
 */
int __mg_load_bmp (MG_RWops* fp, MYBITMAP* bmp, RGB* pal)
{
    BITMAPFILEHEADER fileheader;
    BITMAPINFOHEADER infoheader;
    int effect_depth;
    DWORD rmask = 0x001f, gmask = 0x03e0, bmask = 0x7c00;
    unsigned long biSize;
    BYTE* bits;
    int pitch;
    int ncol;

    if (read_bmfileheader (fp, &fileheader) != 0) {
        return ERR_BMP_IMAGE_TYPE;
    }

    biSize = fp_igetl (fp);

    if (biSize >= WININFOHEADERSIZE) {
        if (read_win_bminfoheader (fp, &infoheader) != 0) {
	        return ERR_BMP_LOAD;
        }
        MGUI_RWseek (fp, biSize - WININFOHEADERSIZE, SEEK_CUR);
        /* compute number of colors recorded */
        ncol = (fileheader.bfOffBits - biSize - 14) / 4;
        read_bmicolors (ncol, pal, fp, 1);
    }
    else if (biSize == OS2INFOHEADERSIZE) {
        if (read_os2_bminfoheader (fp, &infoheader) != 0) {
	        return ERR_BMP_LOAD;
        }
        /* compute number of colors recorded */
        ncol = (fileheader.bfOffBits - 26) / 3;
        read_bmicolors (ncol, pal, fp, 0);
    }
    else
	    return ERR_BMP_LOAD;

    /* Compute the size and pitch of the image */
    if (infoheader.biBitCount == 16)
        effect_depth = 24;
    else
        effect_depth = infoheader.biBitCount;
        
    bmpComputePitch (effect_depth, infoheader.biWidth, &pitch, TRUE);
    biSize = pitch * infoheader.biHeight;

    if( !(bits = malloc (biSize)) ) {
        return ERR_BMP_MEM;
    }
    bmp->bits = bits;

    bmp->flags = MYBMP_TYPE_BGR | MYBMP_FLOW_UP;

    switch (infoheader.biCompression) {
    case BI_BITFIELDS: /* ignore the bit fileds */
        MGUI_RWseek (fp, -16, SEEK_CUR);
        rmask = fp_igetl (fp);
        gmask = fp_igetl (fp);
        bmask = fp_igetl (fp);
        //fprintf (stderr, "__mg_load_bmp: discard the bit masks: %lx, %lx, %lx.\n", rmask, gmask, bmask);
    case BI_RGB:
        if (infoheader.biBitCount == 16) {
            bmp->flags |= MYBMP_RGBSIZE_3;
            read_16bit_image (fp, bits, pitch, &infoheader, gmask);
        }
        else if (infoheader.biBitCount == 32) {
            bmp->flags |= MYBMP_RGBSIZE_4;
            MGUI_RWread (fp, bits, sizeof(char), biSize);
        }
        else {
            bmp->flags |= MYBMP_RGBSIZE_3;
            MGUI_RWread (fp, bits, sizeof(char), biSize);
        }
	    break;

    case BI_RLE8:
	    read_RLE8_compressed_image (fp, bits, pitch, &infoheader);
	    break;

    case BI_RLE4:
	    read_RLE4_compressed_image (fp, bits, pitch, &infoheader);
	    break;

    default:
        return ERR_BMP_NOT_SUPPORTED;
    }

    bmp->depth = effect_depth;
    bmp->w     = infoheader.biWidth;
    bmp->h     = infoheader.biHeight;
    bmp->pitch = pitch;
    bmp->frames = 1;
    bmp->size  = biSize;

    return ERR_BMP_OK;
}

BOOL __mg_check_bmp (MG_RWops* fp)
{
   WORD bfType = fp_igetw (fp);

   if (bfType != 19778)
      return FALSE;

   return TRUE;
}

#ifdef _SAVE_BITMAP
static void bmpGet16CScanline (BYTE* bits, BYTE* scanline, 
                        int pixels)
{
    int i;

    for (i = 0; i < pixels; i++) {
        if (i % 2 == 0)
            *scanline = (bits [i] << 4) & 0xF0;
        else {
            *scanline |= bits [i] & 0x0F;
            scanline ++;
        }
    }
}

static inline void bmpGet256CScanline (BYTE* bits, BYTE* scanline, 
                        int pixels)
{
    memcpy (scanline, bits, pixels);
}

inline void pixel2rgb (gal_pixel pixel, GAL_Color* color, int depth)
{
    switch (depth) {
    case 24:
    case 32:
        color->r = (gal_uint8) ((pixel >> 16) & 0xFF);
        color->g = (gal_uint8) ((pixel >> 8) & 0xFF);
        color->b = (gal_uint8) (pixel & 0xFF);
        break;

    case 15:
        color->r = (gal_uint8)((pixel & 0x7C00) >> 7) | 0x07;
        color->g = (gal_uint8)((pixel & 0x03E0) >> 2) | 0x07;
        color->b = (gal_uint8)((pixel & 0x001F) << 3) | 0x07;
        break;

    case 16:
        color->r = (gal_uint8)((pixel & 0xF800) >> 8) | 0x07;
        color->g = (gal_uint8)((pixel & 0x07E0) >> 3) | 0x03;
        color->b = (gal_uint8)((pixel & 0x001F) << 3) | 0x07;
        break;
    }
}

static void bmpGetHighCScanline (BYTE* bits, BYTE* scanline, 
                        int pixels, int bpp, int depth)
{
    int i;
    gal_pixel c;
    GAL_Color color;

    for (i = 0; i < pixels; i++) {
        c = *((gal_pixel*)bits);

        pixel2rgb (c, &color, depth);
        *(scanline)     = color.b;
        *(scanline + 1) = color.g;
        *(scanline + 2) = color.r;

        bits += bpp;
        scanline += 3;
    }
}

inline static int depth2bpp (int depth)
{
    switch (depth) {
    case 4:
    case 8:
        return 1;
    case 15:
    case 16:
        return 2;
    case 24:
        return 3;
    case 32:
        return 4;
    }
    
    return 1;
}

int __mg_save_bmp (MG_RWops* fp, MYBITMAP* bmp, RGB* pal)
{
    BYTE* scanline = NULL;
    int i, bpp;
    int scanlinebytes;

    BITMAPFILEHEADER bmfh;
    WINBMPINFOHEADER bmih;

    memset (&bmfh, 0, sizeof (BITMAPFILEHEADER));
    bmfh.bfType         = MAKEWORD ('B', 'M');
    bmfh.bfReserved1    = 0;
    bmfh.bfReserved2    = 0;

    memset (&bmih, 0, sizeof (WINBMPINFOHEADER));
    bmih.biSize         = (DWORD)(WININFOHEADERSIZE);
    bmih.biWidth        = (DWORD)(bmp->w);
    bmih.biHeight       = (DWORD)(bmp->h);
    bmih.biPlanes       = 1;
    bmih.biCompression  = BI_RGB;

    bpp = depth2bpp (bmp->depth);
    switch (bmp->depth) {
        case 4:
            scanlinebytes       = (bmih.biWidth + 1)>>1;
            scanlinebytes       = ((scanlinebytes + 3)>>2)<<2;

#ifdef HAVE_ALLOCA
            if (!(scanline = alloca (scanlinebytes))) return ERR_BMP_MEM;
#else
            if (!(scanline = malloc (scanlinebytes))) return ERR_BMP_MEM;
#endif
            memset (scanline, 0, scanlinebytes);

            bmih.biSizeImage    = (DWORD)(bmih.biHeight*scanlinebytes);
            bmfh.bfOffBits      = SIZEOF_BMFH + SIZEOF_BMIH
                                    + (SIZEOF_RGBQUAD<<4);
            bmfh.bfSize         = (DWORD)(bmfh.bfOffBits + bmih.biSizeImage);
            bmih.biBitCount     = 4;
            bmih.biClrUsed      = 16L;
            bmih.biClrImportant = 16L;

            MGUI_RWwrite (fp, &bmfh.bfType, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfSize, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfReserved1, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfReserved2, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfOffBits, sizeof (DWORD), 1);
            
            MGUI_RWwrite (fp, &bmih.biSize, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biWidth, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biHeight, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biPlanes, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmih.biBitCount, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmih.biCompression, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biSizeImage, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biXPelsPerMeter, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biYPelsPerMeter, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biClrUsed, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biClrImportant, sizeof (DWORD), 1);

            for (i = 0; i < 16; i++) {
                RGBQUAD rgbquad;
                rgbquad.rgbRed = pal [i].r;
                rgbquad.rgbBlue = pal [i].b;
                rgbquad.rgbGreen = pal [i].g;
                MGUI_RWwrite (fp, &rgbquad, sizeof (char), sizeof (RGBQUAD));
            }
            
            for (i = bmp->h  - 1; i >= 0; i--) {
                bmpGet16CScanline (bmp->bits + i * bmp->pitch, scanline, bmp->w);
                MGUI_RWwrite (fp, scanline, sizeof (char), scanlinebytes);
            }
        break;

        case 8:
            scanlinebytes       = bmih.biWidth;
            scanlinebytes       = ((scanlinebytes + 3)>>2)<<2;

#ifdef HAVE_ALLOCA
            if (!(scanline = alloca (scanlinebytes))) return ERR_BMP_MEM;
#else
            if (!(scanline = malloc (scanlinebytes))) return ERR_BMP_MEM;
#endif
            memset (scanline, 0, scanlinebytes);

            bmih.biSizeImage    = bmih.biHeight*scanlinebytes;
            bmfh.bfOffBits      = SIZEOF_BMFH + SIZEOF_BMIH
                                    + (SIZEOF_RGBQUAD<<8);
            bmfh.bfSize         = bmfh.bfOffBits + bmih.biSizeImage;
            bmih.biBitCount     = 8;
            bmih.biClrUsed      = 256;
            bmih.biClrImportant = 256;

            MGUI_RWwrite (fp, &bmfh.bfType, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfSize, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfReserved1, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfReserved2, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfOffBits, sizeof (DWORD), 1);

            MGUI_RWwrite (fp, &bmih.biSize, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biWidth, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biHeight, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biPlanes, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmih.biBitCount, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmih.biCompression, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biSizeImage, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biXPelsPerMeter, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biYPelsPerMeter, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biClrUsed, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biClrImportant, sizeof (DWORD), 1);
            
            for (i = 0; i < 256; i++) {
                RGBQUAD rgbquad;
                rgbquad.rgbRed = pal [i].r;
                rgbquad.rgbBlue = pal [i].b;
                rgbquad.rgbGreen = pal [i].g;
                MGUI_RWwrite (fp, &rgbquad, sizeof (char), sizeof (RGBQUAD));
            }
            
            for (i = bmp->h - 1; i >= 0; i--) {
                bmpGet256CScanline (bmp->bits + bmp->pitch * i, scanline, bmp->w);
                MGUI_RWwrite (fp, scanline, sizeof (char), scanlinebytes);
            }
        break;

        default:
            scanlinebytes       = bmih.biWidth*3;
            scanlinebytes       = ((scanlinebytes + 3)>>2)<<2;

#ifdef HAVE_ALLOCA
            if (!(scanline = alloca (scanlinebytes))) return ERR_BMP_MEM;
#else
            if (!(scanline = malloc (scanlinebytes))) return ERR_BMP_MEM;
#endif
            memset (scanline, 0, scanlinebytes);

            bmih.biSizeImage    = bmih.biHeight*scanlinebytes;
            bmfh.bfOffBits      = SIZEOF_BMFH + SIZEOF_BMIH;
            bmfh.bfSize         = bmfh.bfOffBits + bmih.biSizeImage;
            bmih.biBitCount     = 24;

            MGUI_RWwrite (fp, &bmfh.bfType, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfSize, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfReserved1, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfReserved2, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmfh.bfOffBits, sizeof (DWORD), 1);
            
            MGUI_RWwrite (fp, &bmih.biSize, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biWidth, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biHeight, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biPlanes, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmih.biBitCount, sizeof (WORD), 1);
            MGUI_RWwrite (fp, &bmih.biCompression, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biSizeImage, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biXPelsPerMeter, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biYPelsPerMeter, sizeof (LONG), 1);
            MGUI_RWwrite (fp, &bmih.biClrUsed, sizeof (DWORD), 1);
            MGUI_RWwrite (fp, &bmih.biClrImportant, sizeof (DWORD), 1);

            for (i = bmp->h - 1; i >= 0; i--) {
                bmpGetHighCScanline (bmp->bits + i * bmp->pitch, scanline, 
                                bmp->w, bpp, bmp->depth);
                MGUI_RWwrite (fp, scanline, sizeof (char), scanlinebytes);
            }
        break;
    }

#ifndef HAVE_ALLOCA
    free (scanline);
#endif

    return ERR_BMP_OK;
}

#endif

⌨️ 快捷键说明

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