📄 image32.c
字号:
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <windows.h>
#include <commdlg.h>
#include "image32.h"
char szName[256];
struct IMAGE *image;
int nHorz,nVert,nPal_f,nBits,nColors;
HDC hMemDC;
HBITMAP hBitmap,hOldBitmap;
void ImageCreate(struct IMAGE * image, int wid, int hei, int bitcount) // 建立DIB
{
BITMAPINFOHEADER bmi={40,1,1,1,1,0,0,0,0,0,0}; // 位图信息头初始值
int palette;
DWORD size,offset;
if (image->hdib) ImageClose(image);
if (bitcount<=8) palette=4*(1<<bitcount); // 计算调色板数据字节数
else palette=0; // 真彩色图像无调色板
image->wid=wid; // 宽度
image->hei=hei; // 高度
image->bitcount=(WORD) bitcount; // 每像素位数
image->bpp=(WORD) ((bitcount+7)/8); // 计算每像素字节数
image->bpl=(WORD) ((wid*bitcount+31)/32*4); // 计算每行字节数
size=40+palette+image->bpl*hei+64; // 计算DIB尺寸
if (bitcount<=8) offset=40+palette; // 计算DIB中像素数据起始位置偏移
else offset=40;
image->hdib=GlobalAlloc(GPTR, size); // 申请内存空间
image->lpbi=(BITMAPINFO *) GlobalLock(image->hdib); // 得位图信息指针
image->lpbits=(LPSTR) image->lpbi + offset;
// 得DIB中像素数据起始位置
bmi.biWidth=wid; // 宽度、高度、每像素位数填入位图信息头
bmi.biHeight=hei;
bmi.biBitCount=(WORD) bitcount;
memcpy(&image->lpbi->bmiHeader,&bmi,40); // 传入DIB的位图信息头
}
void ImageClose(struct IMAGE * image) // 关闭DIB
{
GlobalUnlock(image->hdib);
GlobalFree(image->hdib); // 释放内存空间
image->hdib=NULL; // 指针清零
}
int LoadBMP(struct IMAGE * image, char *str) // 打开并读入BMP图像文件
{
BITMAPFILEHEADER bfhead;
BITMAPINFOHEADER bmi;
HFILE fh;
int wid,hei,bitcount;
DWORD biSize,offset, compression, size;
fh=_lopen(str, OF_READ); // 打开图像文件
if (fh==-1) return 1; // 文件不存在,退出
_llseek(fh, 0, SEEK_SET);
_lread(fh, &bfhead, 14); // 读入位图文件头
_lread(fh, &bmi, 40); // 读入位图信息头
offset=bfhead.bfOffBits; // 从位图文件头中得像素数据位置
biSize =bmi.biSize; // 得位图信息头字节数
wid =bmi.biWidth; // 得位图宽度
hei =bmi.biHeight; // 得位图高度
bitcount=bmi.biBitCount; // 得每像素位数
compression=bmi.biCompression; // 得压缩类型
if (compression) {
_lclose(fh);
return 2; // 是压缩文件,退出
}
ImageCreate(image,wid,hei,bitcount);
offset-=14; // 除去位图文件头,偏移减少14字节
size=image->bpl*hei; // 计算像素数据字节数
_llseek(fh,14,SEEK_SET); // 指向文件的位图信息位置
_hread(fh,(BYTE*)image->lpbi,offset); // 位图信息读入内存DIB
_hread(fh,(BYTE*)image->lpbits,size); // 像素数据读入内存DIB
_lclose(fh); // 关闭图像文件
return 0;
}
int LoadTGA(struct IMAGE * image,char *str)
{
BITMAPINFOHEADER bmi={40,1,1,1,8,0,0,0,0,0,0};
HFILE fh;
BYTE *buf,buf1[1024];
int i,j,pos,bplt,bpl,palette;
int wid,hei,bits,type;
DWORD size,offset;
if (image->hdib) ImageClose(image);
fh=_lopen(str,OF_READ);
if (fh==-1) {
image->hdib=NULL;
return 1;
}
_llseek(fh,2,SEEK_SET);
_lread(fh,&type,1);
if (type & 0x08) {
_lclose(fh);
return 2;
}
_llseek(fh,12,SEEK_SET);
_lread(fh,&wid,2);
_lread(fh,&hei,2);
_lread(fh,&bits,1);
ImageCreate(image,wid,hei,bits);
if (bits==8)
palette = 1024;
else
palette = 0;
offset = 40 + palette;
bpl=((wid*bits+7)/8+3)/4*4;
if (bits==24) {
size=bpl*hei+offset;
bplt=3*wid;
}
else {
size=bpl*hei+offset;
bplt=wid;
}
pos=18;
_llseek(fh,18,SEEK_SET);
buf=(BYTE*)image->lpbi;
buf+=40;
if (type==1) {
_hread(fh,buf1,768);
for (i=0;i<256;i++) {
for (j=0;j<3;j++) buf[4*i+j]=buf1[3*i+j];
}
buf+=1024;
pos=18+768;
}
else if (type==3) {
for (i=0;i<256;i++) {
for (j=0;j<3;j++) buf[4*i+j]=(BYTE) i;
}
buf+=1024;
}
_llseek(fh,pos,SEEK_SET);
for (i=0;i<hei;i++) {
_hread(fh,buf,bplt);
buf+=bpl;
}
_lclose(fh);
return 0;
}
int ImageOpen(struct IMAGE * image, char *str) // 打开并读入图像文件
{
int m,n;
strupr(str);
n=strlen(str);
if (strcmp(&str[n-3], "BMP")==0) // 检查文件名后缀
m=LoadBMP(image, str); // 打开并读入BMP图像文件
else if (strcmp(&str[n-3], "TGA")==0) // 检查文件名后缀
m=LoadTGA(image, str); // 打开并读入TGA图像文件
return m;
}
void ImageSave(struct IMAGE * image, char *str) // 存储图像文件
{
BITMAPFILEHEADER bfhead = { 0x4d42,0,0,0,0}; // 位图文件头初始值
HFILE fh;
OFSTRUCT of;
int palette;
DWORD size, offset;
if (image->hdib==NULL) return; // DIB为空时返回
fh = OpenFile(str, &of, OF_CREATE | OF_READWRITE); // 打开图像文件
if (fh==-1) return; // 文件不存在,则返回
if (image->bitcount<=8) palette = 1<<(image->bitcount+2); // 计算调色板数据字节数
else palette = 0;
offset = 40 + palette; // 计算位图信息字节数
image->bpl=(WORD) ((image->wid*image->bitcount+31)/32*4); // 计算每行字节数
size = image->bpl*image->hei; // 计算像素数据字节数
bfhead.bfOffBits = 14 + offset; // 计算像素数据在文件中的位置
bfhead.bfSize = 14 + offset + size; // 计算BMP图像文件总字节数
_llseek(fh, 0, SEEK_SET);
_hwrite(fh, (LPSTR) &bfhead, 14); // 存位图文件头
_hwrite(fh, (LPSTR) image->lpbi, offset); // 存DIB位图信息
_hwrite(fh, image->lpbits, size); // 存DIB像素数据
_lclose(fh); // 关闭图像文件
}
DWORD pixel(struct IMAGE * image,int x,int y,DWORD c)
{
BYTE *hp;
DWORD le,dd=0;
int yy;
if (image->bitcount<8) return 0;
if ((x<0)||(y<0)||(x>=(int) image->wid)||
(y>=(int) image->hei)) return 0;
x *= image->bpp; yy = image->hei-1-y;
le = (DWORD) image->bpl*yy+x;
hp = (BYTE *) image->lpbits + le;
if (c==0xffffffff) {
memcpy(&dd,hp,image->bpp);
}
else memcpy(hp,&c,image->bpp);
return(dd);
}
DWORD getpixel(struct IMAGE * image,int x,int y)
{
return(pixel(image,x,y,0xffffffff));
}
void setpixel(struct IMAGE * image,int x,int y,DWORD c)
{
pixel(image,x,y,c);
}
COLORREF DWORD2CLRREF(DWORD c)
{
BYTE i;
union COLOR {
COLORREF clrref;
BYTE c[4];
} col;
col.clrref=c;
i=col.c[0]; col.c[0]=col.c[2];
col.c[2]=i; c=col.clrref;
return(c);
}
void putpixel(HWND hWnd,struct IMAGE * image,int px,int py,
DWORD c,int sx,int sy)
{
HDC hdc;
int r,g,b;
setpixel(image,px,py,c);
hdc = GetDC(hWnd);
if (image->bitcount==8) {
getpalette(image,(int)c,&r,&g,&b);
c=RGB(r,g,b);
}
else {
c=DWORD2CLRREF(c);
}
SetPixel(hdc,sx,sy,c);
ReleaseDC(hWnd,hdc);
}
void getset(struct IMAGE * image,int x,int y,int Dx,int Dy,BYTE* buf,int flag)
{
BYTE *lp;
int i,dw,dh,delta=0;
if ((image->bitcount<8)||(x+Dx<=0)) return;
if (x<0) { // 左边越界
delta=-x; x=0;
}
if ((x<0)||(y<0)||(x>=(int) image->wid)||
(y>=(int) image->hei)) return;
Dx *= image->bpp; // 像素地址转换成字节地址
delta *= image->bpp; // 左边不显示的部分
dw=min(Dx,(int) image->bpl-image->bpp*x);
dh=min(Dy,(int) image->hei-y);
buf += delta; // 调整输入输出像素数据首地址
dw -= delta; // 调整实际显示宽度
lp = DibAddress(image,x,y);
for (i=0;i<dh;i++) {
if (flag==0) {
memcpy(lp,buf,dw); // 写入数据
}
else {
memcpy(buf,lp,dw); // 读出数据
}
buf += Dx; lp -= image->bpl;
}
}
void getimage(struct IMAGE * image,int x,int y,int Dx,int Dy,BYTE* buf)
{
getset(image,x,y,Dx,Dy,buf,1);
}
void setimage(struct IMAGE * image,int x,int y,int Dx,int Dy,BYTE* buf)
{
getset(image,x,y,Dx,Dy,buf,0);
}
void putimage(HWND hWnd,struct IMAGE * image,int px,int py,
int Dx,int Dy,BYTE* buf,int sx,int sy)
{
setimage(image,px,py,Dx,Dy,buf);
WriteDDB(image,sx,sy,px,py,Dx,Dy);
}
BYTE* DibAddress(struct IMAGE * image,int x,int y)
{
BYTE *lp;
DWORD le;
int yy;
if (image->bitcount<8) return 0;
if ((x<0)||(y<0)||((WORD) x>=image->wid)||((WORD) y>=image->hei)) return 0;
yy = image->hei-1-y;
le = (DWORD) image->bpl*yy+image->bpp*x;
lp = (BYTE *) image->lpbits + le;
return(lp);
}
void setwin(struct IMAGE * image,int x,int y,int Dx,int Dy,DWORD color)
{
int i,dw,dh,k,len;
HANDLE hbuf;
BYTE* buf;
if (image->bitcount<8) return;
if ((x<0)||(y<0)||(x>=(int) image->wid)||
(y>=(int) image->hei)) return;
dw=min(Dx,(int) image->bpl/image->bpp-x);
dh=min(Dy,(int) image->hei-y);
if (dw<dh) len=dh;
else len=dw;
hbuf=GlobalAlloc(LMEM_FIXED,len*image->bpp);
buf=(BYTE*)GlobalLock(hbuf);
if (image->bpp==1) memset(buf,(BYTE)color,len);
else {
for (i=0,k=0;i<len;i++,k+=image->bpp)
memcpy(&buf[k],&color,image->bpp);
}
if (dw==1)
setimage(image,x,y,1,dh,(BYTE*) buf);
else {
for (i=0;i<dh;i++) {
setimage(image,x,y+i,dw,1,(BYTE*) buf);
}
}
GlobalUnlock(hbuf);
GlobalFree(hbuf);
}
void fillw(HWND hWnd,struct IMAGE * image,int x,int y,int Dx,int Dy,DWORD color)
{
setwin(image,x,y,Dx,Dy,color);
WriteDDB(image,x,y,x,y,Dx,Dy);
}
void getpalette(struct IMAGE * image,int n,int *pr,int *pg,int *pb)
{
BYTE *hpal;
if (image->bitcount>8) return;
hpal=(BYTE *) image->lpbi + 40;
*pb=hpal[4*n];
*pg=hpal[4*n+1];
*pr=hpal[4*n+2];
}
void setpalette(struct IMAGE * image,int n,int r,int g,int b)
{
BYTE *hpal;
if (image->bitcount>8) return;
hpal=(BYTE *) image->lpbi + 40;
hpal[4*n] =(BYTE) b;
hpal[4*n+1]=(BYTE) g;
hpal[4*n+2]=(BYTE) r;
}
void putpalette(HWND hWnd,struct IMAGE * image,int n,int r,int g,int b)
{
setpalette(image,n,r,g,b);
WriteDDB(image,0,0,0,0,image->wid,image->hei);
}
void GetSysParam(HDC hdc)
{
nHorz =GetDeviceCaps(hdc,HORZRES);
nVert =GetDeviceCaps(hdc,VERTRES);
nPal_f =GetDeviceCaps(hdc,RASTERCAPS) & RC_PALETTE;
nBits =GetDeviceCaps(hdc,BITSPIXEL);
if (nPal_f)
nColors=1<<(nBits*GetDeviceCaps(hdc,PLANES));
else nColors=0;
}
HBITMAP CreateDDB(HWND hWnd,int nHorz,int nVert)
{
HDC hDC;
HBITMAP hBitmap;
hDC = GetDC(hWnd);
hBitmap=CreateCompatibleBitmap(hDC,nHorz,nVert);
ReleaseDC(hWnd,hDC);
return hBitmap;
}
void DeleteDDB(HBITMAP hBitmap)
{
if (hBitmap)
DeleteObject(hBitmap);
}
HDC CreateMemDC(void)
{
HDC hMemDC;
hMemDC =CreateCompatibleDC(NULL);
SelectObject(hMemDC,hBitmap);
return hMemDC;
}
void DeleteMemDC(HDC hMemDC)
{
if (hMemDC) {
DeleteObject(hMemDC);
DeleteDC(hMemDC);
}
}
void ClearDDB(void) // 清除内存设备内容
{
hMemDC =CreateMemDC(); // 建立内存设备
PatBlt(hMemDC, 0, 0, nHorz, nVert, WHITENESS); // 用白色清除内存设备原来内容
DeleteMemDC(hMemDC); // 释放内存设备
}
void WriteDDB(struct IMAGE * image,int sx,int sy,
int px,int py,int Dx,int Dy)
{
hMemDC =CreateMemDC(); // 建立内存设备
StretchDIBits(hMemDC,sx,sy,Dx,Dy,px,image->hei-(Dy+py),Dx,Dy,
image->lpbits,image->lpbi,DIB_RGB_COLORS,SRCCOPY);
DeleteMemDC(hMemDC); // 释放内存设备
}
void DisplayDDB(HWND hWnd)
{
HDC hDC;
hDC = GetDC(hWnd);
hMemDC=CreateMemDC();
BitBlt(hDC,0,0,nHorz,nVert,hMemDC,0,0,SRCCOPY);
DeleteMemDC(hMemDC); // 释放内存设备
ReleaseDC(hWnd,hDC);
}
void CMUFileOpen(HWND hWnd,char *str)
{
OPENFILENAME ofnTemp;
DWORD Errval;
char buf[5];
char Errstr[50]="GetOpenFileName returned Error #";
char szTemp[] = "BMP Files (*.bmp)\0*.bmp\0TGA Files (*.tga)\0*.tga\0";
ofnTemp.lStructSize = sizeof( OPENFILENAME );
ofnTemp.hwndOwner = hWnd;
ofnTemp.hInstance = 0;
ofnTemp.lpstrFilter = (LPSTR)szTemp;
ofnTemp.lpstrCustomFilter = NULL;
ofnTemp.nMaxCustFilter = 0;
ofnTemp.nFilterIndex = 1;
ofnTemp.lpstrFile = (LPSTR)szName;
ofnTemp.nMaxFile = sizeof( szName );
ofnTemp.lpstrFileTitle = NULL;
ofnTemp.nMaxFileTitle = 0;
ofnTemp.lpstrInitialDir = NULL;
ofnTemp.lpstrTitle=str;
ofnTemp.Flags = OFN_FILEMUSTEXIST |
OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
ofnTemp.nFileOffset = 0;
ofnTemp.nFileExtension = 0;
ofnTemp.lpstrDefExt = "*";
ofnTemp.lCustData = 0L;
ofnTemp.lpfnHook = NULL;
ofnTemp.lpTemplateName = NULL;
if (GetOpenFileName( &ofnTemp ) != TRUE) {
Errval=CommDlgExtendedError();
if (Errval!=0) {
sprintf(buf,"%ld",Errval);
strcat(Errstr,buf);
MessageBox(hWnd,Errstr,"WARNING",MB_OK|MB_ICONSTOP);
}
}
InvalidateRect( hWnd, NULL, TRUE );
}
void CMUSaveFile(HWND hWnd,char *str)
{
OPENFILENAME ofnTemp;
DWORD Errval;
char buf[5];
char Errstr[50]="GetOpenFileName returned Error #";
char szTemp[] = "BMP Files (*.bmp)\0*.bmp\0";
ofnTemp.lStructSize = sizeof( OPENFILENAME );
ofnTemp.hwndOwner = hWnd;
ofnTemp.hInstance = 0;
ofnTemp.lpstrFilter = (LPSTR)szTemp;
ofnTemp.lpstrCustomFilter = NULL;
ofnTemp.nMaxCustFilter = 0;
ofnTemp.nFilterIndex = 1;
ofnTemp.lpstrFile = (LPSTR)szName;
ofnTemp.nMaxFile = sizeof( szName );
ofnTemp.lpstrFileTitle = NULL;
ofnTemp.nMaxFileTitle = 0;
ofnTemp.lpstrInitialDir = NULL;
ofnTemp.lpstrTitle=str;
ofnTemp.Flags = OFN_FILEMUSTEXIST |
OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
ofnTemp.nFileOffset = 0;
ofnTemp.nFileExtension = 0;
ofnTemp.lpstrDefExt = "*";
ofnTemp.lCustData = 0L;
ofnTemp.lpfnHook = NULL;
ofnTemp.lpTemplateName = NULL;
if (GetSaveFileName( &ofnTemp ) != TRUE) {
Errval=CommDlgExtendedError();
if (Errval!=0) {
sprintf(buf,"%ld",Errval);
strcat(Errstr,buf);
MessageBox(hWnd,Errstr,"WARNING",MB_OK|MB_ICONSTOP);
}
}
InvalidateRect( hWnd, NULL, TRUE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -