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

📄 setscanner.cpp

📁 又VC++实现的基于TWAIN的扫描仪图像输入处理软件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
         lp2=lp2+BytesPerRow;
	}

      lpBits2=lpStart2;
      memcpy(lpBits2,lp1,y1*BytesPerRow);
	  lpBits2=lpBits2+y1*BytesPerRow;
	  lp1=lp1+y1*BytesPerRow;   
	}//结束写文件
 
	count++;
	bytesout+=BytesWritten;
  	RowsWritten=bytesout/BytesPerRow;
    
}//执行循环,直到结束读取数据 

//写文件
//彩色图像RGB的数值在存储文件时对调为BGR,这是BMP文件格式的要求
  if(pScanner->m_nColor==16777216)
  {
    PreviewBitmap.Write(lpStart3+y1*dwBytesInLine, dwBytesBMP-y1*dwBytesInLine);
  }
  else	//存储灰度或者黑白图像文件
  {
     PreviewBitmap.Write(lpStart3+y1*dwBytesInLineH, dwBytesBMPH-y1*dwBytesInLineH);
  }
  PreviewBitmap.Close();  
  //删除进程条,释放内存  	
  delete pScanningProgress;
 
  GlobalUnlock(hbuffer2);
  GlobalFree(hbuffer2);
  GlobalUnlock(hMem);
  GlobalFree(hMem);
}

//--------------------2004年2月18日增加---------------------------------//
//				扫描校正方式设置及校正参数获取							//
//  Twain 扫描、文件扫描及预览扫描时调用,用于一次扫描任务前设定扫描校	//
//  正方式,下传的相关校正用参数及偏色系数由jiaose.ini内的相关参数项获取//
//	返回:1-->底层校正设置正常			0-->底层校正设置出现故障		//
//----------------------------------------------------------------------// 
int CSetScanner::Scan_JZMode()		//设置扫描校正方式SCSI命令包:扫描校正方式设置及校正参数获取
{
	//从jiaose.ini中读取扫描校正方式字节
//	int JZMode= GetPrivateProfileInt("ScanCai_Mod ScnCaiMod","JZMode",1,InitDir2);

/*底层使用的说明校正方式字节的定义:
	0-底层校正扫描
	1-底层校正精扫描
	2-校正参数扫描
	3-校正参数精扫描
	4-不校正扫描
	6-感光校正参数扫描
	8-偏移校正参数扫描
	10-增益校正参数扫描
上层选择输入值为:0~7(8项选择输入选项),下传时需进行有效性判断和转换:
	JZMode>7,强制JZMode=2
	JZMode=5、6、7时,分别转换为6、8、10后再下传
*/
	int JZMode= GetPrivateProfileInt("ScanCai_Mod","ScnCaiMod",1,InitDir2);
	switch (JZMode)
		{
            case 0:
            case 1:
            case 2:
            case 3:
			case 4:
				break;

            case 5:
				JZMode=6;
				break;
            case 6:
				JZMode=8;
				break;
            case 7:
				JZMode=10;
				break;

            default:
				JZMode=2;
				break;
		}

	Stp_Para_INI();					//初始化Def_Stp_Para数组内300字节的缺省和分步校正参数
	//加入在参数输入对话框中显示“进入下传分步校正参数包SCSI命令程序”功能
	
	//初始化SCSI调用缓冲区
	ASPI32Status=0xff;	
    
 	for(int i=0;i<16;i++)
    mySRBEIO.SenseArea[i]=0;

	int ASPI_Host_Adapter_ID;
	ASPI_Host_Adapter_ID=GetPrivateProfileInt("ASPI_Adapter","ASPI",0,InitDir2);

	mySRBEIO.SRB_Cmd		=SC_EXEC_SCSI_CMD;	
	mySRBEIO.SRB_Status		=0;					
	mySRBEIO.SRB_HaId		=ASPI_Host_Adapter_ID;	
	mySRBEIO.SRB_Flags		=SRB_DIR_SCSI;		
	mySRBEIO.SRB_Hdr_Rsvd	=0;				
	mySRBEIO.SRB_Target		=6;					
	mySRBEIO.SRB_Lun		=0;				
	mySRBEIO.SRB_Rsvd1		=0;	
	//分步校正下传参数包Def_Stp_Para缓冲区的300个字节:150字节的缺省参数及150字节的分步参数
	mySRBEIO.SRB_BufLen	    =300;
	mySRBEIO.SRB_BufPointer =(unsigned char *)Def_Stp_Para;
	mySRBEIO.SRB_SenseLen	=SENSE_LEN;		
	mySRBEIO.SRB_CDBLen		=10;			
	mySRBEIO.SRB_HaStat		=0;					
	mySRBEIO.SRB_TargStat	=0;                
    mySRBEIO.SRB_Rsvd2		=0;
	
	mySRBEIO.CDBByte[0]		=0x2A;	//设置扫描校正方式SCSI命令包 CDBLen=10。命令码=2AH
	mySRBEIO.CDBByte[1]		=0x00;
	mySRBEIO.CDBByte[2]		=LOBYTE(JZMode);	//设置扫描校正方式字节
    mySRBEIO.CDBByte[3]		=0x00;
    mySRBEIO.CDBByte[4]		=0x00;
    mySRBEIO.CDBByte[5]		=0x00;
    mySRBEIO.CDBByte[6]		=0x00;
    mySRBEIO.CDBByte[7]		=HIBYTEOFWORD(300);
    mySRBEIO.CDBByte[8]		=LOBYTEOFWORD(300);
    mySRBEIO.CDBByte[9]		=0;

	mySRBEIO.SRB_PostProc	=0;
	ASPI32Status =SendASPI32Command( (LPSRB) &mySRBEIO);
	while(mySRBEIO.SRB_Status==SS_PENDING);
	if(mySRBEIO.SRB_Status==SS_ERR)
	{
	   MessageBox("SRB_Status==ss_error");
	  // return 0;
	}
    if(mySRBEIO.SRB_TargStat==0x02)    //约定GOOD为00H,检查出错为02H
	{
	   SCSI_CHECK();
	}

   return 1;
}

//////////////////////////////////////////////////////////////
//发送SETWINDOWS命令
//////////////////////////////////////////////////////////////
void CSetScanner::SetWindow(int n,int m)
{
   	ASPI32Status=0xff;	
	
	char DataBuffer[90];
    char chBrightness;
	char chThreashold;
	char chContrast;

	int i;
	int  nResolution,nTop,nLeft,nWidth,nLength,nWidth2;
	int ymaxFBL,ymaxFBL_Adj;

	WORD wHalfTone=0;

	int y1;
    int gray;
    int scannermode;

    int shuzu;
    shuzu=GetPrivateProfileInt("Shuzu","shuzu",1200,InitDir2); 
   
    ymaxFBL_Adj=GetPrivateProfileInt("ymax","ymaxFBL_Adj",5000,InitDir2);
    ymaxFBL=GetPrivateProfileInt("ymax","ymaxFBL",5000,InitDir2)+ymaxFBL_Adj;
	
//************************************************************
//以下代码是准备向SCSI接口传递的数据
//************************************************************
 
   

	//从\\windows\\twacker.ini文件中,获取扫描分辨率初值
	//并且根据分辨率确定色拼齐数值
	if(m==1)//扫描时参数
	{
     pScanner->m_nDPI= GetPrivateProfileInt("resoultion","reso",100,InitDir2);
     nResolution =pScanner->m_nDPI;
     pScanner->m_nColor = GetPrivateProfileInt("color num","color",16777216,InitDir2);
	}
	if(m==0)//预览时参数
	{
      pScanner->m_nDPI=100;
      nResolution =100;
      pScanner->m_nColor=16777216;
	}

	//由于存在奇偶拼,因此必须考虑奇偶行的差距
	//目前认为差距为pScanner->m_nDPI/100
     int reso1;
	 int x1;
	 x1=0;
	 y1=0;
	 reso1=25;
	 while(pScanner->m_nDPI>reso1)
	 {
		 reso1=reso1+50;
		 x1++;
		 y1=2*x1;
	 }
	int pjrow;
//	 pjrow=(int)(pScanner->m_nDPI/100.0+0.5);
	 pjrow=(int)(pScanner->m_nDPI/100.0);
	y1=y1+pjrow;
   
	//确定扫描图像的扫描区域,起始点的纵向以电机走步为单位,水平方向以600DPI为单位的象素点数目
	//扫描长度为实际分辨率下象素点为为单位 
	nTop	= n;
	nLeft	= (int)((pScanner->m_rtScanZoom).left/FuMian*shuzu);
	nWidth	= (int)(((pScanner->m_rtScanZoom).right-(pScanner->m_rtScanZoom).left)/FuMian*shuzu);
    //真彩色时的长度,用于实现行拼和奇偶拼
	nLength= (int)((((pScanner->m_rtScanZoom).bottom-(pScanner->m_rtScanZoom).top)/FuMian)*(pScanner->m_nDPI)+y1);
	//根据需要而下传的一个参数,表示当前分辨率下的实际象素点数目
	nWidth2	=(int)(((pScanner->m_rtScanZoom).right-(pScanner->m_rtScanZoom).left)/FuMian*(pScanner->m_nDPI));
	//传递数据时,灰度和黑白处理方式不同,不过黑白送上来的数据是0或者FF。
	if(pScanner->m_nColor==2)
	{
      nWidth2=(nWidth2/8)*8;   
      nWidth=(nWidth2*shuzu)/pScanner->m_nDPI;
      //仅仅是奇偶拼色
	  nLength= (int)((((pScanner->m_rtScanZoom).bottom-(pScanner->m_rtScanZoom).top)/FuMian)*(pScanner->m_nDPI)+pjrow);
	}
    if(pScanner->m_nColor==256)
	{
      //仅仅是奇偶拼色
	  nLength=(int)((((pScanner->m_rtScanZoom).bottom-(pScanner->m_rtScanZoom).top)/FuMian)*(pScanner->m_nDPI)+pjrow);
	}

	//下传的校正数值等
	chBrightness = '\0';
	chThreashold = '\0';
	chContrast   = '\0';

 
	UpdateData(TRUE);

	for(i=0;i<90;i++)
	 DataBuffer[i]=0;

	DataBuffer[0] = 0;
	DataBuffer[1] = 7;
	DataBuffer[6] = HIBYTEOFWORD(82);
    DataBuffer[7] = LOBYTEOFWORD(82);

    DataBuffer[8+0] = 0;
    DataBuffer[8+1] = 0;
    //X和Y轴的分辨率 
	DataBuffer[8+2] = HIBYTEOFWORD(nResolution);
	DataBuffer[8+3] = LOBYTEOFWORD(nResolution);
	DataBuffer[8+4] = HIBYTEOFWORD(nResolution);
	DataBuffer[8+5] = LOBYTEOFWORD(nResolution);
	
    //X和Y轴的左上角位置 
	DataBuffer[8+6] = FIRSTBYTEOFDWORD(nLeft);
	DataBuffer[8+7] = SECONDBYTEOFDWORD(nLeft);
	DataBuffer[8+8] = THIRDBYTEOFDWORD(nLeft);
	DataBuffer[8+9] = LASTBYTEOFDWORD(nLeft);

	DataBuffer[8+10] = FIRSTBYTEOFDWORD(nTop);
	DataBuffer[8+11] = SECONDBYTEOFDWORD(nTop);
	DataBuffer[8+12] = THIRDBYTEOFDWORD(nTop);
	DataBuffer[8+13] = LASTBYTEOFDWORD(nTop);
    //窗口的宽度和长度
	DataBuffer[8+14] = FIRSTBYTEOFDWORD(nWidth);
	DataBuffer[8+15] = SECONDBYTEOFDWORD(nWidth);
	DataBuffer[8+16] = THIRDBYTEOFDWORD(nWidth);
	DataBuffer[8+17] = LASTBYTEOFDWORD(nWidth);

	DataBuffer[8+18] = FIRSTBYTEOFDWORD(nLength);
	DataBuffer[8+19] = SECONDBYTEOFDWORD(nLength);
	DataBuffer[8+20] = THIRDBYTEOFDWORD(nLength);
	DataBuffer[8+21] = LASTBYTEOFDWORD(nLength);
	
    //明度、线程和对比度
	DataBuffer[8+22] = chBrightness;
	DataBuffer[8+23] = chThreashold;  //阈值
	DataBuffer[8+24] = chContrast;
    DataBuffer[8+25] = 0x05;          //图像数据的组合方式
	switch(pScanner->m_nColor)
	{
	  case  16777216:
        DataBuffer[8+26] = 24;
        scannermode=0x80;  //彩色扫描方式
		break;
      case  256:
         gray=GetPrivateProfileInt("xianzhen","channel",42,InitDir2);
         DataBuffer[8+26] =8;
		 if(gray==44)
		 {
           scannermode=0x44;
		 }
	     if(gray==42)
		 {
           scannermode=0x42;
		 }
         if(gray==41)
		 {
           scannermode=0x41;
		 } 
		 break;
	  case 2:
         DataBuffer[8+26] =1;
         gray=GetPrivateProfileInt("xianzhen","channel",42,InitDir2);
         if(gray==44)
		 {
           scannermode=0x24;
		 }
		 if(gray==42)
		 {
           scannermode=0x22;
		 }
        if(gray==41)
		{
           scannermode=0x21;
		}  
		break;
	  default:
        DataBuffer[8+26] = 24;
        scannermode=0x80;  //彩色扫描方式
		break;
	}
	
	DataBuffer[8+27] = HIBYTE(wHalfTone);
	DataBuffer[8+28] = LOBYTE(wHalfTone);	 
	DataBuffer[8+29] = (char)(0x80);
    DataBuffer[8+30] = 0;
    DataBuffer[8+31] = 0;
    DataBuffer[8+32] = 0;   //图像压缩代码
    
	//以下为扩展部分
	//	*****  头尾重叠下传参数  *****
	int	Head,End,Adj;
	char HStr[10],EStr[9],AStr[9];
	strcpy(HStr,"Head_CNT1");
	strcpy(EStr,"End_CNT1");
	strcpy(AStr,"END1_Adj");

	i=48;
	for (int j=1;j<=8;j++)
	{
		HStr[8]=LOBYTE(0x30+j);
		EStr[7]=LOBYTE(0x30+j);
		AStr[3]=LOBYTE(0x30+j);
		Head=GetPrivateProfileInt("CCD_Pj",HStr,10,InitDir2);
		End=GetPrivateProfileInt("CCD_Pj",EStr,10,InitDir2);
		Adj=GetPrivateProfileInt("CCD_Adjust",AStr,0,InitDir2);
		DataBuffer[i+0]=HIBYTE(Head);		//头部重叠区象素数
		DataBuffer[i+1]=LOBYTE(Head);
		DataBuffer[i+2]=HIBYTE(End+Adj);	//尾部重叠区象素数
		DataBuffer[i+3]=LOBYTE(End+Adj);
		i=i+4;
	}
	//修改第一头的头部重叠数:将头部剪切量加进去
	Head=GetPrivateProfileInt("CCD_Pj","Head_CNT1",10,InitDir2);
    Adj=GetPrivateProfileInt("CCD_Adjust","Head_Adj",10,InitDir2);
	DataBuffer[48]=HIBYTE(Head+Adj);		//头部重叠区象素数+头部剪切量
	DataBuffer[49]=LOBYTE(Head+Adj);

    //A0扫描仪:将尾部修改剪切量加到第五头的尾部剪切值中去
	//A1扫描仪:将尾部修改剪切量加到第三头的尾部剪切值中去
	End=GetPrivateProfileInt("CCD_Pj","End_CNT5",10,InitDir2);
    Adj=GetPrivateProfileInt("CCD_Adjust","END5_Adj",10,InitDir2);
	DataBuffer[66]=HIBYTE(End+Adj);		//第5头尾部重叠区象素数+尾部剪切量
	DataBuffer[67]=LOBYTE(End+Adj);

	DataBuffer[8+72] = scannermode;  //RGB彩色模式以及选择的线阵

    DataBuffer[8+73]=HIBYTE(nWidth2);  //一行扫描线在设定扫描分辨率下的实际象素点数目
    DataBuffer[8+74]=LOBYTE(nWidth2); 
   
    DataBuffer[8+75]=HIBYTE(shuzu);  // X走向最大分辨率
    DataBuffer[8+76]=LOBYTE(shuzu);

    DataBuffer[8+77]=HIBYTE(ymaxFBL);  // Y走向最大步数
    DataBuffer[8+78]=LOBYTE(ymaxFBL);

//************************************************************
//以下代码是向SCSI接口传递数据
//************************************************************
  	ASPI_Host_Adapter_ID=GetPrivateProfileInt("ASPI_Adapter","ASPI",0,InitDir2);
	
	for(i=0;i<16;i++)
	mySRBEIO.SenseArea[i]=0;
	
	//定义SCSI的SC_EXEC_SCSI_CMD命令块
	mySRBEIO.SRB_Cmd		=SC_EXEC_SCSI_CMD;	
	mySRBEIO.SRB_Status		=0;					
	mySRBEIO.SRB_HaId		=ASPI_Host_Adapter_ID;	
	mySRBEIO.SRB_Flags		=SRB_DIR_SCSI;		
	mySRBEIO.SRB_Hdr_Rsvd	=0;				
	mySRBEIO.SRB_Target		=6;					
	mySRBEIO.SRB_Lun		=0;				
	mySRBEIO.SRB_Rsvd1		=0;					
	mySRBEIO.SRB_BufLen		=90;				
	mySRBEIO.SRB_BufPointer	=(unsigned char *)DataBuffer;
	mySRBEIO.SRB_SenseLen	=SENSE_LEN;		
	mySRBEIO.SRB_CDBLen		=10;			
	mySRBEIO.SRB_HaStat		=0;					
	mySRBEIO.SRB_TargStat	=0;                
	mySRBEIO.SRB_Rsvd2	    =0;					

	//定义SETWINDOW命令
	mySRBEIO.CDBByte[0]		=0x24;
	mySRBEIO.CDBByte[1]		=0;
	mySRBEIO.CDBByte[2]		=0;
	mySRBEIO.CDBByte[3]		=0;
	mySRBEIO.CDBByte[4]		=0;
	mySRBEIO.CDBByte[5]		=0;
	mySRBEIO.CDBByte[6]		=FIRSTBYTEOFDWORD(90);
	mySRBEIO.CDBByte[7]		=THIRDBYTEOFDWORD(90);
	mySRBEIO.CDBByte[8]		=LASTBYTEOFDWORD(90);
	mySRBEIO.CDBByte[9]		=0;
	mySRBEIO.SRB_PostProc=0;
    //调用SCSI函数包,向SCSI发送命令
	ASPI32Status =SendASPI32Command( (LPSRB) &mySRBEIO);
	//检测SCSI返回状态
	while(mySRBEIO.SRB_Status==SS_PENDING);
	if(mySRBEIO.SRB_Status==SS_ERR)
	{
	   MessageBox("SRB_Status==ss_error");
	}
    if(mySRBEIO.SRB_TargStat==0x02)    //约定GOOD为00H,检查出错为02H
	{
	   SCSI_CHECK();
	}
		//测试,用于扫描起始显示时间   
    time_t date1_t;
	time(&date1_t);		
	int Hour,Minute,Second;
	CTime time1(date1_t);
      
    pTesttime = new Ctesttime();
	pTesttime->Create( );

	//获取系统时间,并在对话框中显示扫描起始时间
	Hour=time1.GetHour();
  	Minute=time1.GetMinute();
    Second=time1.GetSecond();
    pTesttime->start(Hour,Minute,Second); 
}

/*--------------------------------------------------------------/
/					SCSI 图像数据读取命令						/	
/		由CSetScanner::cunchu()调用,用于文件扫描				/
/	参数:	LPSTR lp	--> 读取图像数据缓冲区					/
/			int bytes   --> 读取图像数据的长度(字节数)		/
/			int bytes1  --> 一次Read SCSI命令上传图象象素点数	/
/			int n		--> 本次READ命令所读取的扫描行数		/
/			int m		-->

⌨️ 快捷键说明

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