📄 bitmap.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Helpers for .BMP file loading.
*
****************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <dos.h>
#include "palette.h"
#include "bitmap.h"
#ifndef _WCI86HUGE
#if !defined(__386__) && defined(_M_IX86)
#define _WCI86HUGE __huge
#else
#define _WCI86HUGE
#endif
#endif
void MemFree( void *ptr );
void *MemAlloc( unsigned size );
void *MemReAlloc( void *ptr, unsigned size );
void MemStart( void );
#define HUGE_SHIFT 8
#define START_OF_HEADER sizeof( BITMAPFILEHEADER )
/*
* NOTE: assume fp is positioned at the start of the bitmap information.
* we first read in the BITMAPINFOHEADER to get information about the
* number of quads needed, then we reposition ourselves and read in
* the entire BITMAPINFOHEADER structure.
*/
static BITMAPINFO *readDIBInfo( FILE *fp )
{
BITMAPINFO *bm;
BITMAPINFOHEADER *header;
long bitmap_size;
header = MemAlloc( sizeof( BITMAPINFOHEADER ) );
if( !header ) return( NULL );
fseek( fp, START_OF_HEADER, SEEK_SET );
fread( header, sizeof( BITMAPINFOHEADER ), 1, fp );
if( header->biBitCount < 9 ) {
/* Bitmap has palette, read it */
fseek( fp, START_OF_HEADER, SEEK_SET );
bitmap_size = DIB_INFO_SIZE( header->biBitCount );
bm = MemReAlloc( header, bitmap_size );
if( !bm ) return( NULL );
fread( bm, bitmap_size, 1, fp );
}
else return( (BITMAPINFO*) header );
return( bm );
}
static BITMAPCOREINFO *readCoreInfo( FILE *fp )
{
BITMAPCOREINFO *bm_core;
BITMAPCOREHEADER *header;
long bitmap_size;
header = MemAlloc( sizeof( BITMAPCOREHEADER ) );
if( !header ) return( NULL );
fseek( fp, START_OF_HEADER, SEEK_SET );
fread( header, sizeof( BITMAPCOREHEADER ), 1, fp );
fseek( fp, START_OF_HEADER, SEEK_SET );
bitmap_size = CORE_INFO_SIZE( header->bcBitCount );
bm_core = MemReAlloc( header, bitmap_size );
if( !bm_core ) return( NULL );
fread( bm_core, bitmap_size, 1, fp );
return( bm_core );
}
#if defined(M_I86)
#define __halloc halloc
#define __hfree hfree
static void HugeMemCopy( char far *dst, char far *src, unsigned bytes )
{
long offset, selector;
long bytes_before_segment_end;
offset = FP_OFF( dst );
selector = FP_SEG( dst );
bytes_before_segment_end = 0x10000L - offset;
if( bytes_before_segment_end < bytes ) {
_fmemcpy( dst, src, bytes_before_segment_end );
bytes -= bytes_before_segment_end;
selector += HUGE_SHIFT;
dst = MK_FP( selector, 0 );
src += bytes_before_segment_end;
}
_fmemcpy( dst, src, bytes );
}
#else
#define HugeMemCopy( a, b, c ) memcpy( a, b, c )
#define __halloc( a, b ) MemAlloc( a )
#define __hfree MemFree
#endif
/* this is the amount of memory we read in at once */
#define CHUNK_SIZE (48 * 1024)
static void readInPieces( BYTE _WCI86HUGE *dst, FILE *fp, DWORD size )
{
BYTE *buffer;
WORD chunk_size;
chunk_size = CHUNK_SIZE;
while( chunk_size && ( ( buffer = MemAlloc( chunk_size ) ) == NULL ) ) {
chunk_size >>= 1;
}
if( buffer == NULL ) {
return;
}
while( size > chunk_size ) {
fread( buffer, chunk_size, 1, fp );
HugeMemCopy( dst, buffer, chunk_size );
dst += chunk_size;
size -= chunk_size;
}
fread( buffer, size, 1, fp );
HugeMemCopy( dst, buffer, size );
MemFree( buffer );
} /* readInPieces */
static HBITMAP readBitmap( HWND hwnd, FILE *fp, long offset, BOOL core,
bitmap_info *info )
{
DWORD size; /* generic size - used repeatedly */
BYTE _WCI86HUGE *mask_ptr; /* pointer to bit array in memory */
HDC hdc;
HPALETTE new_palette, old_palette;
BITMAPINFO *bm_info;
BITMAPCOREINFO *bm_core;
HBITMAP bitmap_handle;
bitmap_handle = (HBITMAP)0;
if( core ) {
bm_core = readCoreInfo( fp );
if( bm_core == NULL ) return( bitmap_handle );
size = BITS_TO_BYTES( bm_core->bmciHeader.bcWidth * bm_core->bmciHeader.bcBitCount,
bm_core->bmciHeader.bcHeight );
} else {
bm_info = readDIBInfo( fp );
if( bm_info == NULL ) return( bitmap_handle );
size = BITS_TO_BYTES( bm_info->bmiHeader.biWidth * bm_info->bmiHeader.biBitCount,
bm_info->bmiHeader.biHeight );
}
fseek( fp, offset, SEEK_SET );
mask_ptr = __halloc( size, 1 );
if( mask_ptr != NULL ) {
readInPieces( mask_ptr, fp, size );
if( core ) {
BITMAPCOREHEADER *h;
h = &bm_core->bmciHeader;
/*
* This will cause a GP Fault!
*/
bitmap_handle = CreateBitmap( h->bcWidth, h->bcHeight, h->bcPlanes,
h->bcBitCount, mask_ptr );
} else {
if( bm_info->bmiHeader.biBitCount < 9 ) {
/* Bitmap has palette, create it */
new_palette = CreateDIBPalette( bm_info );
if( new_palette ) {
hdc = GetDC( hwnd );
old_palette = SelectPalette( hdc, new_palette, FALSE );
RealizePalette( hdc );
bitmap_handle = CreateDIBitmap( hdc, &bm_info->bmiHeader,
CBM_INIT, mask_ptr, bm_info, DIB_RGB_COLORS );
SelectPalette( hdc, old_palette, FALSE );
DeleteObject( new_palette );
ReleaseDC( hwnd, hdc );
}
}
else {
/* Bitmap with no palette*/
hdc = GetDC( hwnd );
bitmap_handle = CreateDIBitmap( hdc, &bm_info->bmiHeader,
CBM_INIT, mask_ptr, bm_info, DIB_RGB_COLORS );
ReleaseDC( hwnd, hdc );
}
}
__hfree( mask_ptr );
}
if( core ) {
if( info != NULL ) {
info->bm_core = bm_core;
} else {
MemFree( bm_core );
}
} else {
if( info != NULL ) {
info->bm_info = bm_info;
} else {
MemFree( bm_info );
}
}
return( bitmap_handle );
} /* readBitmap */
/*
* Loads a device independant bitmap from the file <file_name> and
* returns a handle to a newly created BITMAP.
*/
HBITMAP ReadBitmapFile( HWND hwnd, char *file_name, bitmap_info *info )
{
FILE *fp;
HBITMAP bitmap_handle;
BITMAPFILEHEADER file_header;
BOOL core;
DWORD size;
bitmap_handle = (HBITMAP)0;
fp = fopen( file_name, "rb" );
if( fp == NULL ) return( bitmap_handle );
fread( &file_header, sizeof( BITMAPFILEHEADER ), 1, fp );
if( file_header.bfType != BITMAP_TYPE ) {
fclose( fp );
return( bitmap_handle );
}
fread( &size, sizeof( size ), 1, fp );
core = ( size == sizeof( BITMAPCOREHEADER ) );
if (!core) {
bitmap_handle = readBitmap( hwnd, fp, file_header.bfOffBits, core, info );
}
if( info != NULL ) {
info->is_core = core;
}
fclose( fp );
return( bitmap_handle );
} /* ReadBitmapFile */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -