一个基于C的底层实现的图片库
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string>
#include <fstream>
using namespace std;
#define DIFF 40
struct COLOR{int R,B,G;};
class IMAGE{
private:
int height;
int width;
int img_step;
vector<COLOR>pixel;
public:
HBITMAP hbmp;
IMAGE();
IMAGE(HBITMAP hbmp);
~IMAGE();
int getwidth();
int getheight();
void setimagestep(int val);
int getimagestep();
COLOR getpixel(int x,int y);
void operator =(const IMAGE &img);
int print(){printf("%d\n",pixel.size());}
};
IMAGE GetScreen();
IMAGE loadimage(const char* filename);
void saveimage(const char* filename,IMAGE img);
IMAGE getimage(IMAGE img,int ax,int ay,int cx,int cy);
void CompImageFeature(IMAGE img1,IMAGE img2);
int ColorValMapping(int val);
double CompImageSimilarity_(IMAGE img1,IMAGE img2);
double CompImageSimilarity(IMAGE img0,IMAGE img1);
IMAGE::IMAGE(){this->width=0;this->height=0;this->hbmp=NULL;this->pixel.clear();}
IMAGE::~IMAGE(){}
int IMAGE::getheight(){return height;}
int IMAGE::getwidth(){return width;}
COLOR IMAGE::getpixel(int x,int y){return pixel[x*width+y];}
void IMAGE::setimagestep(int val){img_step=val;}
int IMAGE::getimagestep(){return img_step;}
void IMAGE::operator =(const IMAGE &img){
this->hbmp=img.hbmp;
this->width=img.width;
this->height=img.height;
this->pixel=img.pixel;
}
IMAGE::IMAGE(HBITMAP hbmp){
BITMAP bmp;
this->hbmp=hbmp;
HDC dc=GetDC(NULL);
SelectObject(dc,hbmp);
GetObject(hbmp,sizeof(BITMAP),(LPBYTE)&bmp);
this->height=bmp.bmHeight;
this->width=bmp.bmWidth;
this->img_step=1;
ReleaseDC(NULL,dc);
int nbyte=bmp.bmBitsPixel/8;
BITMAPINFO bi;
bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth=bmp.bmWidth;
bi.bmiHeader.biHeight=-bmp.bmHeight;
bi.bmiHeader.biPlanes=1;
bi.bmiHeader.biBitCount=bmp.bmBitsPixel;
bi.bmiHeader.biCompression=BI_RGB;
bi.bmiHeader.biSizeImage=bmp.bmWidth*bmp.bmHeight*nbyte;
bi.bmiHeader.biClrUsed=0;
bi.bmiHeader.biClrImportant=0;
HDC hdc=::GetDC(NULL);
BYTE* pBits=(BYTE*)new BYTE[bmp.bmWidth*bmp.bmHeight*nbyte];
::ZeroMemory(pBits,bmp.bmWidth*bmp.bmHeight*nbyte);
if(!::GetDIBits(hdc,hbmp,0,bmp.bmHeight,pBits,&bi,DIB_RGB_COLORS)){
delete pBits;
pBits=NULL;
}
pixel.clear();
for(int i=0;i<bmp.bmWidth;++i){
for(int j=0;j<bmp.bmHeight;++j){
BYTE r=pBits[i*nbyte+j*bmp.bmWidthBytes+2];
BYTE g=pBits[i*nbyte+j*bmp.bmWidthBytes+1];
BYTE b=pBits[i*nbyte+j*bmp.bmWidthBytes+0];
COLOR ns=COLOR{r,b,g};
pixel.push_back(ns);
}
}
int sz=pixel.size();
delete pBits;
pBits=NULL;
ReleaseDC(NULL,dc);
DeleteObject(hbmp);
}
int ColorValMapping(int val){
int mapVal=0;
if (val>223)mapVal=7;
else if (val>191)mapVal=6;
else if (val>159)mapVal=5;
else if (val>129)mapVal=4;
else if (val>95)mapVal=3;
else if (val>63)mapVal=2;
else if (val>31)mapVal=1;
else mapVal=0;
return mapVal;
}
void CompImageFeature(IMAGE img, int *pImgFeature){
int index=0;
int w=img.getwidth();
int h=img.getheight();
int map_b=0,map_g=0,map_r=0;
for (int i=0;i<h;i+=img.getimagestep()){
for (int j=0;j<w;j+=img.getimagestep()){
COLOR color=img.getpixel(i,j);
int r=color.R,b=color.B,g=color.G;
map_r=ColorValMapping(r);
map_b=ColorValMapping(b);
map_g=ColorValMapping(g);
index=64*map_b+8*map_g+map_r;
pImgFeature[index]++;
}
}
}
double CompImageSimilarity_(IMAGE img1,IMAGE img2){
int h=img1.getheight(),w=img1.getwidth();
int cnt=0;
for(int i=0;i<h;i++)
for(int j=0;j<w;j++){
int r1=img1.getpixel(i,j).R,b1=img1.getpixel(i,j).B,g1=img1.getpixel(i,j).G;
int r2=img2.getpixel(i,j).R,b2=img2.getpixel(i,j).B,g2=img2.getpixel(i,j).G;
if(r1-r2>DIFF||r2-r1>DIFF)++cnt;
if(b1-b2>DIFF||b2-b1>DIFF)++cnt;
if(g1-g2>DIFF||g2-g1>DIFF)++cnt;
}
return cnt*1.0/(h*3.0*w);
}
double CompImageSimilarity(IMAGE img0, IMAGE img1){
int imgFeature0[512]={0};
int imgFeature1[512]={0};
CompImageFeature(img0,imgFeature0);
CompImageFeature(img1,imgFeature1);
double sum_square0=0.0,sum_square1=0.0,sum_multiply=0.0;
for(int i=0;i<512;i++){
sum_square0+=imgFeature0[i]*imgFeature0[i];
sum_square1+=imgFeature1[i]*imgFeature1[i];
sum_multiply+=imgFeature0[i]*imgFeature1[i];
}
double ret=sum_multiply/(sqrt(sum_square0)*sqrt(sum_square1));
return ret;
}
IMAGE GetScreen(){
HDC hdc=GetDC(NULL);
RECT rect={0};
int32_t ScrWidth=0,ScrHeight=0;
ScrWidth=GetDeviceCaps(hdc,HORZRES);
ScrHeight=GetDeviceCaps(hdc,VERTRES);
HDC hmdc=CreateCompatibleDC(hdc);
ScrWidth=1920;ScrHeight=1080;
HBITMAP hBmpScreen=CreateCompatibleBitmap(hdc,ScrWidth,ScrHeight);
SelectObject(hmdc,hBmpScreen);
BitBlt(hmdc,0,0,ScrWidth,ScrHeight,hdc,rect.left,rect.top,SRCCOPY);
IMAGE ret(hBmpScreen);
ReleaseDC(NULL,hdc);
DeleteDC(hmdc);
return ret;
}
IMAGE loadimage(const char* filename){
HBITMAP hbmp=(HBITMAP)LoadImageA(NULL,filename,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
IMAGE ret(hbmp);
ret.print();
return ret;
}
void saveimage(const char* filename,IMAGE img){
HBITMAP hBitmap=img.hbmp;
HDC hDC;
int iBits;
WORD wBitCount;
DWORD dwPaletteSize=0,dwBmBitsSize=0,dwDIBSize=0,dwWritten=0;
BITMAP Bitmap;
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
HANDLE fh,hDib,hPal,hOldPal=NULL;
hDC=CreateDC("DISPLAY",NULL,NULL,NULL);
iBits=GetDeviceCaps(hDC,BITSPIXEL)*GetDeviceCaps(hDC,PLANES);
DeleteDC(hDC);
if(iBits<=1)wBitCount=1;
else if(iBits<=4)wBitCount=4;
else if(iBits<=8)wBitCount=8;
else wBitCount=24;
GetObject(hBitmap,sizeof(Bitmap),(LPSTR)&Bitmap);
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth=Bitmap.bmWidth;
bi.biHeight=Bitmap.bmHeight;
bi.biPlanes=1;
bi.biBitCount=wBitCount;
bi.biCompression=BI_RGB;
bi.biSizeImage=0;
bi.biXPelsPerMeter=0;
bi.biYPelsPerMeter=0;
bi.biClrImportant=0;
bi.biClrUsed=0;
dwBmBitsSize=((Bitmap.bmWidth *wBitCount+31)/32)*4* Bitmap.bmHeight;
hDib=GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi=(LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi=bi;
hPal=GetStockObject(DEFAULT_PALETTE);
if(hPal){
hDC=::GetDC(NULL);
hOldPal=::SelectPalette(hDC,(HPALETTE)hPal,FALSE);
RealizePalette(hDC);
}
GetDIBits(hDC,hBitmap, 0,(UINT)Bitmap.bmHeight,
(LPSTR)lpbi+ sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(BITMAPINFO *)lpbi,DIB_RGB_COLORS);
if(hOldPal){
::SelectPalette(hDC,(HPALETTE)hOldPal,TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL,hDC);
}
fh=CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
bmfHdr.bfType=0x4D42;
dwDIBSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwPaletteSize+dwBmBitsSize;
bmfHdr.bfSize=dwDIBSize;
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+(DWORD)sizeof(BITMAPINFOHEADER)+dwPaletteSize;
WriteFile(fh,(LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
WriteFile(fh,(LPSTR)lpbi,dwDIBSize,&dwWritten,NULL);
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
}
IMAGE getimage(IMAGE img,int ax,int ay,int cx,int cy){
HDC hdc=GetDC(NULL);
int Width=cx,Height=cy;
HBITMAP hBmp=img.hbmp;
SelectObject(hdc,hBmp);
HDC hmdc=CreateCompatibleDC(hdc);
HBITMAP hbmp=CreateCompatibleBitmap(hdc,cx,cy);
SelectObject(hmdc,hbmp);
BitBlt(hmdc,0,0,cx,cy,hdc,ax,ay,SRCCOPY);
IMAGE ret(hbmp);
ReleaseDC(NULL,hdc);
DeleteDC(hmdc);
DeleteObject(hbmp);
return ret;
}
|