📄 picture.cpp
字号:
// Picture.cpp: implementation of the CImageProcess class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "lane_new.h"
#include "Picture.h"
#include "DSStream.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define HAVE_BOOLEAN
#include "jpeglib.h"
#ifdef __cplusplus
}
#endif // __cplusplus
extern CLane_newApp theApp;
extern BYTE * pData;
#include <setjmp.h>
#include <AfxOle.h>
struct ErrorStruct {
struct jpeg_error_mgr pub; // "public" fields
jmp_buf setjmp_buffer; // for return to caller
};
typedef struct ErrorStruct *JpegErrorPtr;
METHODDEF(void) ErrorExit(j_common_ptr Info);
METHODDEF(void) ErrorExit(j_common_ptr Info)
{
JpegErrorPtr Err=(JpegErrorPtr)Info->err;
char Buffer[JMSG_LENGTH_MAX];
(*Info->err->format_message)(Info,Buffer);
DWORD i=1;
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"生成JPEG文件出错\n",SMTO_BLOCK,200,&i);
longjmp(Err->setjmp_buffer,1);
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageProcess::CImageProcess()
{
}
/* 从剪切板中读取图象数据 */
void CImageProcess::ProcessPicture(char *FileName,int Quality)
{
DWORD RetValue=1;
try{
/*if(strlen(FileName)<20) return;
COleDataObject OleData;
if(OleData.AttachClipboard()==0){ //将剪切板联系到OLE类
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"无法和剪贴板联结\n",SMTO_BLOCK,200,&RetValue);
return;
}
if(OleData.IsDataAvailable(CF_DIB)==0){//剪切板数据是否为BMP图片?
OleData.Release();
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"剪贴板上不是图片数据\n",SMTO_BLOCK,200,&RetValue);
return;
}
HGLOBAL hObj=OleData.GetGlobalData(CF_DIB);//获取OLE类句柄
if(hObj==NULL){
OleData.Release();
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"获取剪贴板数据失败\n",SMTO_BLOCK,200,&RetValue);
return;
}
pData=(unsigned char *)GlobalLock(hObj);//锁定类句柄并获取图象数据
unsigned char *pData=NULL;
if(pData==NULL){
OleData.Release();
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"转换HGLOBAL为指针失败\n",SMTO_BLOCK,200,&RetValue);
return;
}*/
if(pData!=NULL){
CompressPicture((unsigned char *)pData,FileName,Quality);//将BMP图象压缩为JPEG图象
delete [] pData;
pData=NULL;
}
//GlobalUnlock(hObj); //解锁类句柄
//GlobalFree(hObj); //释放类句柄
//OleData.Release(); //释放剪切板数据
}
catch(...){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"CImageProcess::ProcessPicture()出现异常\n",SMTO_BLOCK,500,&RetValue);
}
}
/* 利用外来的函数库压缩图片 */
void CImageProcess::CompressPicture(unsigned char *pData,char *FileName,int Quality)
{
DWORD RetValue=1;
try{
BITMAPINFOHEADER BmpInfoHeader;
int Length=sizeof(BITMAPINFOHEADER);
memmove(&BmpInfoHeader,pData,Length);
int ReadCount=Length;
if((BmpInfoHeader.biCompression==BI_RLE4)||(BmpInfoHeader.biCompression==BI_RLE8)){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"剪贴板中的图片为压缩格式\n",SMTO_BLOCK,200,&RetValue);
return;
}
if(BmpInfoHeader.biSizeImage==0){ //BI_RGB格式的BMP文件该值可以为0
BmpInfoHeader.biSizeImage=(((BmpInfoHeader.biWidth*BmpInfoHeader.biBitCount+31)>>8)<<2)*BmpInfoHeader.biHeight;
}
// if(BmpInfoHeader.biBitCount!=24){
// SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"剪贴板中的图片非24为BMP格式\n",SMTO_BLOCK,200,&RetValue);
// return;
// }
unsigned char *DataBuff=NULL;;
if((DataBuff=new unsigned char[BmpInfoHeader.biWidth*BmpInfoHeader.biHeight*3])==NULL){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"内存不足无法压缩图片\n",SMTO_BLOCK,200,&RetValue);
return;
}
long RowSize=BmpInfoHeader.biWidth*3;
unsigned char tmpStr[14];
int Row,Col,tmpValue;
for(Row=BmpInfoHeader.biHeight-1;Row>=0;Row--){
switch(BmpInfoHeader.biBitCount){
case 24:
/* 24位图象每个像素用三个字节表示,分别为蓝、绿、红 */
for(Col=0;Col<BmpInfoHeader.biWidth;Col++){
memmove(tmpStr,pData+ReadCount,3);
*(DataBuff+Row*RowSize+Col*3)=tmpStr[2];
*(DataBuff+Row*RowSize+Col*3+1)=tmpStr[1];
*(DataBuff+Row*RowSize+Col*3+2)=tmpStr[0];
ReadCount+=3;
}
while(ReadCount&3){
ReadCount++;
}
break;
case 16:
/* 16位图象每个像素用2个字节表示,红、绿、蓝各用5位,最高位未用
如果直接将红、绿、蓝的颜色值取出进行压缩,因为每种颜色的色度
范围为0-255,而我们只使用了0-31,从而导致图片趋向黑色。如果
人为地将色度值乘以8,则图象色彩失真很厉害,因此我认为必须使用
调色板,但我在图象数据中无法找到调色板信息(暂时将色度值扩展8
倍,以后如果确实需要处理16位图象,再想办法) */
if(BmpInfoHeader.biCompression==BI_RGB){
for(Col=0;Col<BmpInfoHeader.biWidth;Col++){
tmpValue=pData[ReadCount]*256+pData[ReadCount+1];
*(DataBuff+Row*RowSize+Col*3)=((tmpValue&0x7c00)>>10)+128;
*(DataBuff+Row*RowSize+Col*3+1)=((tmpValue&0x3e0)>>5)+128;
*(DataBuff+Row*RowSize+Col*3+2)=(tmpValue&0x1f)+128;
ReadCount+=2;
}
while(ReadCount&2){
ReadCount++;
}
}
break;
}
}
/***********************************************************/
/* RGBQUAD *ColorMap=NULL;
switch(BmpInfoHeader.biBitCount){
case 24: //24位真彩色BMP文件无调色板
break;
case 1:
case 4:
case 8:
if(BmpInfoHeader.biClrUsed==0){ //若为0,调色板颜色数目用最大值
BmpInfoHeader.biClrUsed=1<<BmpInfoHeader.biBitCount;
}
Length=BmpInfoHeader.biClrUsed;
if((ColorMap=new RGBQUAD[BmpInfoHeader.biClrUsed])==NULL){
SendMessage(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"内存不足,图片压缩忽略\n");
return;
}
for(int i=0;i<Length;i++){
ColorMap[i].rgbBlue=pData[ReadCount+i*4];
ColorMap[i].rgbGreen=pData[ReadCount+i*4+1];
ColorMap[i].rgbRed=pData[ReadCount+i*4+2];
ColorMap[i].rgbRed=pData[ReadCount+i*4+3];
}
ReadCount+=4*Length;
break;
}
unsigned char *DataBuff=NULL;;
if((DataBuff=new unsigned char[BmpInfoHeader.biWidth*BmpInfoHeader.biHeight*3])==NULL){
if(ColorMap!=NULL) delete [] ColorMap;
ColorMap=NULL;
SendMessage(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"内存不足,图片压缩忽略\n");
return;
}
long RowSize=BmpInfoHeader.biWidth*3;
char tmpStr[3];
int Row,Col;
for(Row=BmpInfoHeader.biHeight-1;Row>=0;Row--){
if(BmpInfoHeader.biBitCount==24){
for(Col=0;Col<BmpInfoHeader.biWidth;Col++){
memmove(tmpStr,pData+ReadCount,3);
*(DataBuff+Row*RowSize+Col*3)=tmpStr[2];
*(DataBuff+Row*RowSize+Col*3+1)=tmpStr[1];
*(DataBuff+Row*RowSize+Col*3+2)=tmpStr[0];
ReadCount=ReadCount+3;
}
} else {
UINT PixelMask=(1<<BmpInfoHeader.biBitCount)-1;
for(Col=0;Col<BmpInfoHeader.biWidth;Col++){
tmpStr[0]=pData[ReadCount];
ReadCount++;
int Index=(tmpStr[0]>>BmpInfoHeader.biBitCount)&PixelMask;
*(DataBuff+Row*RowSize+Col*3+2)=ColorMap[Index].rgbBlue;
*(DataBuff+Row*RowSize+Col*3+1)=ColorMap[Index].rgbGreen;
*(DataBuff+Row*RowSize+Col*3)=ColorMap[Index].rgbRed;
}
}
}
if(ColorMap!=NULL){
delete [] ColorMap;
ColorMap=NULL; */
/*******************************************/
iImageWidth=BmpInfoHeader.biWidth;
OverlayPlazaNO(DataBuff);
// 从文件名中获取车辆信息而不从CTransInfo中获取的原因有:
// 1、避免不同线程间访问冲突
// 2、此时CTransInfo中的数据可能已经被清空
int nLen=strlen(PICTURE_PATH)+1;
// 获取车道号码
memset(tmpStr,0,14);
memmove(tmpStr,FileName+nLen+P_LANE_NO,2);
OverlayLaneNO(DataBuff,tmpStr);
// 获取当前时间
memset(tmpStr,0,14);
memmove(tmpStr,FileName+nLen+P_DATE,12);
OverlayTime(DataBuff,tmpStr);
// 获取收费员号码
memset(tmpStr,0,14);
memmove(tmpStr,FileName+nLen+P_COLLECT_NO,5);
OverlayCollectNO(DataBuff,tmpStr);
// 获取车型
memset(tmpStr,0,14);
tmpStr[0]=FileName[nLen+P_BUS_CLASS];
OverlayBusClass(DataBuff,tmpStr[0]-'0');
// 获取车情
memset(tmpStr,0,14);
tmpStr[0]=FileName[nLen+P_BUS_TYPE];
// 如果有违章,则车情改为违章,用'9'表示;若有更改,则车情改为
// 更改,用'8'表示
if(FileName[nLen+P_MODIFY]!='0') tmpStr[0]='8';
if(FileName[nLen+P_VIOLATE]!='0') tmpStr[0]='9';
OverlayBusType(DataBuff,tmpStr[0]);
// 获取车牌
memset(tmpStr,0,14);
memmove(tmpStr,FileName+nLen+P_BUS_NO,10);
OverlayBusNO(DataBuff,tmpStr);
// 获取价格
memset(tmpStr,0,14);
memmove(tmpStr,FileName+nLen+P_FARE,4);
OverlayFare(DataBuff,tmpStr);
// 将文件名中的价格项扣除
memset(FileName+nLen+P_FARE,0,4);
FILE *fp1;
if((fp1=fopen(FileName,"wb"))==NULL){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"产生JPEG文件错误\n",SMTO_BLOCK,200,&RetValue);
return;
}
struct jpeg_compress_struct Info; //以下完成JEPG文件的压缩
struct ErrorStruct JpegError;
Info.err=jpeg_std_error(&JpegError.pub);
JpegError.pub.error_exit=ErrorExit;
if(setjmp(JpegError.setjmp_buffer)) {
fclose(fp1);
jpeg_destroy_compress(&Info); //压缩失败,上传BMP文件
return;
}
jpeg_create_compress(&Info); //初始化JPEG压缩类
jpeg_stdio_dest(&Info,fp1);
Info.image_width=BmpInfoHeader.biWidth;
Info.image_height=BmpInfoHeader.biHeight;
Info.input_components=3; //对RGB图象,每象素3个元素
Info.in_color_space=JCS_RGB;
jpeg_set_defaults(&Info);
jpeg_set_quality(&Info,Quality,TRUE);
jpeg_start_compress(&Info,TRUE);
int RowStep=BmpInfoHeader.biWidth*3;
while(Info.next_scanline<Info.image_height){
LPBYTE OutRow;
OutRow=DataBuff+(Info.next_scanline*BmpInfoHeader.biWidth*3);
jpeg_write_scanlines(&Info,&OutRow,1);
}
jpeg_finish_compress(&Info);
fclose(fp1);
jpeg_destroy_compress(&Info);
if(DataBuff!=NULL){
delete [] DataBuff; //压缩成功,上传JPEG文件
DataBuff=NULL;
}
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_SEND_PICTURE,0,(LPARAM)FileName,SMTO_BLOCK,500,&RetValue);
}
catch(...){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"CImageProcess::CompressPicture()出现异常\n",SMTO_BLOCK,500,&RetValue);
}
}
void CImageProcess::CreateHZK()
{
bOverlayOK=FALSE;
DWORD RetValue=1;
try{
FILE *fp1;
char strFileName[130];
memset(strFileName,0,130);
theApp.GetFullPath(strFileName);
strcat(strFileName,"hzk24k");
// 将要叠加的汉字从字库文件中读入内存
if((fp1=fopen(strFileName,"rb"))==NULL){
SendMessageTimeout(AfxGetMainWnd()->m_hWnd,WM_ABNORMAL,0,(LPARAM)"无法打开24点阵字库文件\n",SMTO_BLOCK,500,&RetValue);
return;
}
char tmpStr[MAX_SYMBOL_COUNT];
// 将交易汉字读入内存
memset(tmpStr,0,MAX_SYMBOL_COUNT);
memmove(tmpStr,"正常车免征车月票车军警车违章车型车道车队\
收费员价格更改\
闽粤军警浙新冀晋苏黄吉琼宁皖鲁豫蓝川渝贵云藏陕京\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -