mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
495 lines
20 KiB
495 lines
20 KiB
/***********************************************************************
|
|
TWAIN source code:
|
|
Copyright (C) '92-'93 Wang Laboratories, Inc.:
|
|
All rights reserved.
|
|
|
|
Author: Ken Spina
|
|
Project: TWAIN Scanner Support in O/i Client
|
|
Module: NATIVE.C - Code module for native transfers to O/i Wndw
|
|
Comments: Transfer to O/i window from IMGTwainProcessDCMessage
|
|
|
|
History of Revisions:
|
|
|
|
$Log: S:\products\msprods\oiwh\oitwain\native.c_v $
|
|
*
|
|
* Rev 1.4 08 May 1996 16:48:46 BG
|
|
* Modified NativeTransfer() to return an error if the IMGOpenDisplayCGBW()
|
|
* call fails. This API has a limitation of 18000 pixels maximum width or
|
|
* height. If this was exceeded by scan, we were ignoring the error and bad
|
|
* things would happen. Now we return the error back to the Scan OCX and
|
|
* result in a "Invalid Option Specified" error. This closes bug #6413.
|
|
*
|
|
* Rev 1.4 08 May 1996 15:11:10 BG
|
|
* Modified NativeTransfer() to return an error if the IMGOpenDisplayCGBW()
|
|
* call fails. This API has a limitation of 18000 pixels maximum width or
|
|
* height. If this was exceeded by scan, we were ignoring the error and bad
|
|
* things would happen. Now we return the error back to the Scan OCX and
|
|
* result in a "Invalid Option Specified" error. This closes bug #6413.
|
|
*
|
|
* Rev 1.3 09 Oct 1995 10:36:20 BG
|
|
*
|
|
* This fix closes bug #4573 against the SCAN OCX!
|
|
* Must init a the ImgParms structure prior to calling IMGSetParmsCGBW!
|
|
* The first page of a scan may have repaint problems if this is not
|
|
* inited to 0. Any subsequent scan will clear the problem, however.
|
|
* This fix is in MEMORY.C and NATIVE.C of OITWA400.DLL.
|
|
*
|
|
* Rev 1.2 21 Aug 1995 15:53:18 KFS
|
|
* Fix for filing with no display while scanning to a multi page file,
|
|
* Paul found that the same image was being written per ea. page.
|
|
*
|
|
* Need to ClearWindow since not doing it in high level ScantoFile call for
|
|
* multipage scanning. See corresponding change for memory block transfers,
|
|
* this fixes TWAIN native mode transfers, Bitmap image transfer from TWAIN.
|
|
*
|
|
* Rev 1.1 20 Jul 1995 12:07:50 KFS
|
|
* changed oitwain.h engoitwa.h and display.h engdisp.h
|
|
*
|
|
* Rev 1.0 20 Jul 1995 10:29:36 KFS
|
|
* Initial entry
|
|
*
|
|
* Rev 1.2 23 Aug 1994 16:08:54 KFS
|
|
* No code change, added vlog comments to file on checkin
|
|
*
|
|
|
|
REV# INITIALS DATE CHANGES
|
|
|
|
1 kfs 03/11/93 Extracted from dca_acq.c
|
|
2 kfs 03/12/93 added define of WINVER 0x30a for hmemcpy
|
|
for now, will add my own latter
|
|
3 kfs 03/17/93 (1)deleted #include wiissubs.h,
|
|
(2)implemented native mode transfer for RGB
|
|
data, (3) finally found out why HP color and
|
|
position was wrong, it provides a color table
|
|
with bitmap. (this took a while)
|
|
4 kfs 05/28/93 support for scan to file w/o display
|
|
5 kfs 08/27/93 fix for scale being off, attempt to fix
|
|
repaint's from not being received after
|
|
scan on initial scan, (sporadically happens
|
|
on 1st scan w/o an image in display)
|
|
6 kfs 10/12/93 found error in file transfer, not clearing
|
|
existing image on screen
|
|
7 kfs 10/19/93 found archive bit not set correctly
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
// needed for windows definitions
|
|
#include "nowin.h" // eliminate not used Window definitions
|
|
#include <windows.h> // Windows definitions
|
|
#include "TWAIN.h" // needed for TWAIN definitions
|
|
//#include "oitwain.h" // public function prototypes & defs for OITWAIN
|
|
#include "engoitwa.h" // Prototypes & defs for other DLL,s (OITWAIN.H)
|
|
#include "internal.h" // non public prototypes & defs for OITWAIN
|
|
#include "dca_acq.h" // contain TWAIN sample support code
|
|
#include "strings.h" // string constants for module
|
|
|
|
#include "oifile.h" // O/i definition files
|
|
#include "oidisp.h"
|
|
#include "oiadm.h"
|
|
//#include "oiwind.h" /* removed, need only for OiUICreate update */
|
|
//#include "privwind.h"
|
|
// Imports - Globals from other modules need here
|
|
extern char szOiTwainProp[];
|
|
#ifdef WANG_THUNK
|
|
extern DSMENTRYPROC lpnDSM_Entry; // function pointer to Source Mang. entry
|
|
#else
|
|
extern DSMENTRYPROC lpDSM_Entry; // entry point to the SM
|
|
#define lpnDSM_Entry lpDSM_Entry
|
|
#endif
|
|
|
|
extern TW_UINT16 DCDSOpen; // access to status for dca_glue.c
|
|
extern HANDLE hLibInst; // current instance
|
|
|
|
// Exports - Globals to other modules
|
|
|
|
// Local Global variables within Module
|
|
|
|
|
|
TW_UINT16 NativeTransfer(pSTR_OiXFERINFO pXferInfo,
|
|
pTWAIN_SUPPORT pOiSupport,
|
|
pTW_IMAGEINFO pdcImageInfo)
|
|
{
|
|
TW_UINT32 hBitMap;
|
|
TW_UINT16 dcRC = TWRC_SUCCESS;
|
|
HANDLE hbm_acq; // handle to image from Source to ret to App
|
|
LPSTR pImgBuf = 0L;
|
|
LPSTR lpbiCreated;
|
|
char szCaption[MAX_CAPTION_LENGTH];
|
|
int nImgType;
|
|
int nPalEntry = 0;
|
|
RGBQUAD far * lpPalTab = NULL;
|
|
IMGPARMS ImgParms;
|
|
WORD wOiImageType;
|
|
WORD wColorUsed;
|
|
WORD wSizeofBiHeader = sizeof(BITMAPINFOHEADER);
|
|
DWORD dwColorTableSize;
|
|
int status;
|
|
HANDLE hBuffer;
|
|
DWORD dwbuffers;
|
|
PARM_SCROLL_STRUCT Scroll;
|
|
WORD i, j;
|
|
|
|
// BG 10/9/95 Need to init this struct else repaints may not occur properly
|
|
memset(&ImgParms, 0, sizeof(ImgParms));
|
|
|
|
dcRC = (*lpnDSM_Entry)(&pOiSupport->AppID,
|
|
&pOiSupport->DsID,
|
|
DG_IMAGE,
|
|
DAT_IMAGENATIVEXFER,
|
|
MSG_GET,
|
|
(TW_MEMREF)&hBitMap);
|
|
switch (dcRC)
|
|
{
|
|
case TWRC_XFERDONE:
|
|
// Got the handle in TW_INT32, extract it.
|
|
hbm_acq = (HBITMAP)/*LOWORD*/(hBitMap); // for WIN32 no longer 16 bit
|
|
|
|
// DIB handle returned iff valid handle
|
|
if (hbm_acq >= (HANDLE) HINSTANCE_ERROR) // use HINSTANCE_ERROR FOR VALID_HANDLE changed
|
|
{
|
|
DWORD scanLines;
|
|
DWORD partialLines;
|
|
DWORD SizeofbiMap;
|
|
DWORD SizeofbiMap2;
|
|
char * hupImage;
|
|
char * pSrc;
|
|
LPSTR pDest;
|
|
DWORD maxBytes;
|
|
DWORD lastByteCount;
|
|
LPSTR pImgBuf1;
|
|
DWORD BitsPerLine;
|
|
DWORD BytesPerLine;
|
|
DWORD OiBytesPerLine;
|
|
WORD boundadjust;
|
|
DWORD BytesWritten;
|
|
|
|
// hbm_acq valid, lets break it up and sent it to O/i
|
|
if (lpbiCreated = GlobalLock(hbm_acq))
|
|
{
|
|
// We've got the image in memory we can now eject page or non auto,
|
|
// ... user needs to negotiate CAP_CLEARPAGE to use it in state 5
|
|
if (pOiSupport->dwFlags & OI_TWAIN_POSTPREEJECT) // POST PREEJECT
|
|
PostMessage ((pOiSupport->dcUI).hParent, PM_PREEJECT, (WPARAM) hbm_acq, 0);
|
|
else // SEND PREEJECT
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_PREEJECT, (WPARAM) hbm_acq, 0);
|
|
|
|
switch (pdcImageInfo->BitsPerPixel)
|
|
{
|
|
default:
|
|
case 1:
|
|
wColorUsed = 2;
|
|
nImgType = ITYPE_BI_LEVEL;
|
|
wOiImageType = BWFORMAT;
|
|
// Bits with padding for 32 bit boundary
|
|
BitsPerLine = (WORD)(pdcImageInfo->ImageWidth +
|
|
(32 - (pdcImageInfo->ImageWidth % 32)));
|
|
// Bytes per line on 32 bit boundary
|
|
BytesPerLine = BitsPerLine / 8;
|
|
break;
|
|
|
|
case 4:
|
|
wColorUsed = 16;
|
|
if (pdcImageInfo->PixelType == TWPT_GRAY)
|
|
{
|
|
nImgType = ITYPE_GRAY4;
|
|
wOiImageType = GRAYFORMAT;
|
|
}
|
|
else
|
|
{
|
|
nImgType = ITYPE_PAL4;
|
|
nPalEntry = wColorUsed;
|
|
wOiImageType = COLORFORMAT;
|
|
lpPalTab = (RGBQUAD far *)(lpbiCreated + wSizeofBiHeader);
|
|
}
|
|
// bound adjust must be corrected if value = 32, for its actually 0
|
|
if ((boundadjust = (WORD)(32 - ((pdcImageInfo->ImageWidth * 4) % 32))) == 32)
|
|
boundadjust = 0;
|
|
// Bits with padding for 32 bit boundary including color bits
|
|
BitsPerLine = boundadjust + pdcImageInfo->ImageWidth * 4;
|
|
// Bytes per line on 32 bit boundary
|
|
BytesPerLine = BitsPerLine / 8;
|
|
// Image widith in physical pixels for OpenDisplay
|
|
BitsPerLine = pdcImageInfo->ImageWidth + boundadjust/4;
|
|
break;
|
|
|
|
case 8:
|
|
// Some TWAIN Sources specify 8 for RGB when it should be 24, for
|
|
// ... example the Epson sources
|
|
if (pdcImageInfo->PixelType == TWPT_RGB)
|
|
{
|
|
wColorUsed = 0;
|
|
pdcImageInfo->BitsPerPixel = 24;
|
|
}
|
|
else
|
|
{
|
|
wColorUsed = 256;
|
|
if (pdcImageInfo->PixelType == TWPT_GRAY)
|
|
{
|
|
nImgType = ITYPE_GRAY8;
|
|
wOiImageType = GRAYFORMAT;
|
|
}
|
|
else
|
|
{
|
|
nImgType = ITYPE_PAL8;
|
|
nPalEntry = wColorUsed;
|
|
wOiImageType = COLORFORMAT;
|
|
lpPalTab = (RGBQUAD far *)(lpbiCreated + wSizeofBiHeader);
|
|
}
|
|
// bound adjust must be corrected if value = 32, for its actually 0
|
|
if ((boundadjust = (WORD)(32 - ((pdcImageInfo->ImageWidth * 8) % 32))) == 32)
|
|
boundadjust = 0;
|
|
// Bits with padding for 32 bit boundary including color bits
|
|
BitsPerLine = boundadjust + pdcImageInfo->ImageWidth * 8;
|
|
// Bytes per line on 32 bit boundary
|
|
BytesPerLine = BitsPerLine / 8;
|
|
// Image widith in physical pixels for OpenDisplay
|
|
BitsPerLine = pdcImageInfo->ImageWidth + boundadjust/8;
|
|
}
|
|
break;
|
|
|
|
case 24:
|
|
// A 24 bitcount DIB has no color table
|
|
wColorUsed = 0;
|
|
nImgType = ITYPE_BGR24; // ITYPE_RGB24;
|
|
wOiImageType = COLORFORMAT;
|
|
// bound adjust must be corrected if value = 32, for its actually 0
|
|
if ((boundadjust = (WORD)(32 - ((pdcImageInfo->ImageWidth * 24) % 32))) == 32)
|
|
boundadjust = 0;
|
|
// Bits with padding for 32 bit boundary including color bits
|
|
BitsPerLine = boundadjust + pdcImageInfo->ImageWidth * 24;
|
|
// Bytes per line on 32 bit boundary
|
|
BytesPerLine = BitsPerLine / 8;
|
|
// Image widith in physical pixels for OpenDisplay
|
|
BitsPerLine = pdcImageInfo->ImageWidth;
|
|
}
|
|
IMGGetFileType(pXferInfo->hWnd, wOiImageType, (LPINT) &ImgParms.file_type, FALSE);
|
|
if (IMGGetParmsCgbw(pXferInfo->hImageWnd, PARM_SCALE, (LPWORD) &ImgParms.image_scale, 0))
|
|
{
|
|
status = IMGGetParmsCgbw(pXferInfo->hImageWnd, PARM_SCALE, &ImgParms.image_scale,
|
|
PARM_WINDOW_DEFAULT | PARM_CONSTANT);
|
|
}
|
|
else
|
|
{ // if image on screen, get parms and clear image, may need
|
|
status = IMGGetParmsCgbw(pXferInfo->hImageWnd, PARM_IMGPARMS, &ImgParms, 0);
|
|
//Remove the if on OI_DONT_REPAINT, need to do it all the time for mult page
|
|
//... cannot count on on close of file, since hidden window can be used again
|
|
//if (pXferInfo->dwDispFlag != OI_DONT_REPAINT) //don't clear it
|
|
// {
|
|
if (status = IMGClearWindow(pXferInfo->hImageWnd))
|
|
{
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_XFERDONE, (WPARAM) NULL, 0);
|
|
return (dcRC = TWRC_FAILURE);
|
|
}
|
|
if (pXferInfo->dwDispFlag != OI_DONT_REPAINT) // put to fit to window
|
|
if (ImgParms.image_scale > 12) // if any scale value > fit to
|
|
ImgParms.image_scale = 12;
|
|
// }
|
|
}
|
|
|
|
// set scale to window default
|
|
status = IMGSetParmsCgbw(pXferInfo->hImageWnd, PARM_SCALE, &ImgParms.image_scale, 0);
|
|
|
|
status = IMGOpenDisplayCgbw(pXferInfo->hImageWnd,
|
|
pXferInfo->dwDispFlag,
|
|
pdcImageInfo->ImageLength,
|
|
BitsPerLine, // physical pixels on a 32 bit boundary, no depth
|
|
nImgType,
|
|
nPalEntry,
|
|
lpPalTab);
|
|
// Dont go any farther if display open fails!
|
|
if (status) return status;
|
|
|
|
|
|
ImgParms.x_resolut = (unsigned int)(pdcImageInfo->XResolution).Whole;
|
|
ImgParms.y_resolut = (unsigned int)(pdcImageInfo->YResolution).Whole;
|
|
status = IMGSetParmsCgbw(pXferInfo->hImageWnd, PARM_RESOLUTION, &ImgParms.x_resolut, 0);
|
|
|
|
if (pXferInfo->pCaption)
|
|
{
|
|
lstrcpy(szCaption, pXferInfo->pCaption);
|
|
// only put up the caption if we get to OpenDisplay
|
|
if (pXferInfo->dwDispFlag != OI_DONT_REPAINT)
|
|
LoadString(hLibInst, IDS_CAP_UNTITLED,
|
|
&szCaption[lstrlen(szCaption)], MAX_CAPTION_LENGTH);
|
|
else // take out " - ", for
|
|
szCaption[lstrlen(szCaption) - 3] = 0; // ... no display up
|
|
|
|
SetWindowText(pXferInfo->hImageWnd, szCaption);
|
|
}
|
|
|
|
if (pdcImageInfo->PixelType == TWPT_PALETTE)
|
|
{
|
|
unsigned int nDispPalette;
|
|
|
|
nDispPalette = DISP_PALETTE_CUSTOM;
|
|
status = IMGSetParmsCgbw(pXferInfo->hImageWnd, PARM_DISPLAY_PALETTE, &nDispPalette, 0);
|
|
}
|
|
|
|
// appears, need to set it again after open
|
|
status = IMGSetParmsCgbw(pXferInfo->hImageWnd, PARM_SCALE,
|
|
&ImgParms.image_scale, 0);
|
|
|
|
// alloc and lock buffer for image data to O/i thru WriteDisplay
|
|
if (hBuffer = GlobalAlloc(
|
|
GMEM_NOT_BANKED | GMEM_ZEROINIT | GMEM_MOVEABLE,
|
|
0xffff)) // 1 byte short of 64K BLOCK
|
|
{
|
|
if (!(pImgBuf = GlobalLock(hBuffer)))
|
|
{
|
|
GlobalFree(hBuffer);
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_XFERDONE, (WPARAM) NULL, 0);
|
|
return (dcRC = TWRC_FAILURE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_XFERDONE, (WPARAM) NULL, 0);
|
|
return (dcRC = TWRC_FAILURE);
|
|
}
|
|
|
|
// initial max lines per buffer size
|
|
scanLines = 0xffff / BytesPerLine;
|
|
|
|
// max bytes per buffer
|
|
maxBytes = BytesPerLine * scanLines;
|
|
|
|
// Buffer size of global memory for bit map
|
|
SizeofbiMap2 = GlobalSize(hbm_acq);
|
|
// Buffer size of image
|
|
SizeofbiMap = BytesPerLine * pdcImageInfo->ImageLength;
|
|
|
|
if (SizeofbiMap >= maxBytes)
|
|
BytesWritten = maxBytes; // max buffer lines can move
|
|
else // image less than max bytes that can fit in a buffer
|
|
{
|
|
BytesWritten = SizeofbiMap;
|
|
maxBytes = BytesWritten;
|
|
// change for image size
|
|
scanLines = (WORD)(BytesWritten / BytesPerLine);
|
|
}
|
|
dwbuffers = SizeofbiMap / maxBytes; // buffers minus any partial
|
|
partialLines = (lastByteCount = SizeofbiMap % maxBytes) / BytesPerLine;
|
|
OiBytesPerLine = BytesPerLine;
|
|
|
|
if (!wColorUsed)
|
|
{
|
|
// adustment needed for 24 bit RGB color data when not on DWORD boundary
|
|
if (boundadjust)
|
|
{
|
|
DWORD coadjustedBytes;
|
|
WORD coByteadjPerLine = (boundadjust >> 3);
|
|
|
|
OiBytesPerLine = BytesPerLine - coByteadjPerLine;
|
|
coadjustedBytes = scanLines * coByteadjPerLine;
|
|
BytesWritten -= coadjustedBytes;
|
|
lastByteCount -= coadjustedBytes;
|
|
}
|
|
if ((SizeofbiMap2 - SizeofbiMap) > 1024) // HP throws in a 256 color table
|
|
wColorUsed = 256; // ... so lets correct pointer
|
|
}
|
|
|
|
// Color table size
|
|
dwColorTableSize = wColorUsed * sizeof(RGBQUAD);
|
|
|
|
// init pointer to 1st byte of image data
|
|
hupImage = (char *)((char *)lpbiCreated + (DWORD)wSizeofBiHeader +
|
|
dwColorTableSize + (DWORD)(SizeofbiMap - BytesPerLine));
|
|
|
|
|
|
pImgBuf1 = pImgBuf; // set initial value of dest buffer
|
|
|
|
for (j = 0;j < (WORD)dwbuffers; j++)
|
|
{
|
|
for (i = 0; i < (WORD)scanLines; i++)
|
|
{
|
|
pDest = pImgBuf1;
|
|
pSrc = hupImage;
|
|
memcpy(pDest, (char *)pSrc, OiBytesPerLine);
|
|
hupImage -= BytesPerLine;
|
|
pImgBuf1 += OiBytesPerLine;
|
|
}
|
|
status = IMGWriteDisplay(pXferInfo->hImageWnd, pImgBuf,
|
|
&((UINT)BytesWritten));
|
|
pImgBuf1 = pImgBuf;
|
|
}
|
|
if (partialLines)
|
|
{
|
|
BytesWritten = lastByteCount; // last block count
|
|
scanLines = partialLines;
|
|
for (i = 0; i < (WORD)scanLines; i++)
|
|
{
|
|
pDest = pImgBuf1;
|
|
pSrc = hupImage;
|
|
memcpy(pDest, (char *)pSrc, OiBytesPerLine);
|
|
hupImage -= BytesPerLine;
|
|
pImgBuf1 += OiBytesPerLine;
|
|
}
|
|
status = IMGWriteDisplay(pXferInfo->hImageWnd, pImgBuf,
|
|
&((UINT)BytesWritten));
|
|
}
|
|
|
|
//DeleteDC(hdcMem);
|
|
|
|
//GlobalUnlock(hbm);
|
|
//GlobalFree(hbm);
|
|
GlobalUnlock(hBuffer);
|
|
GlobalFree(hBuffer);
|
|
GlobalUnlock(hbm_acq);
|
|
GlobalFree(hbm_acq);
|
|
|
|
// Set the values needed, all others 0 or NULL
|
|
ImgParms.cabinet_name[0] = '\0';
|
|
ImgParms.drawer_name[0] = '\0';
|
|
ImgParms.folder_name[0] = '\0';
|
|
ImgParms.doc_name[0] = '\0';
|
|
ImgParms.file_name[0] = '\0';
|
|
IMGGetParmsCgbw(pXferInfo->hImageWnd, PARM_ARCHIVE, &ImgParms.archive, 0);
|
|
// ImgParms.archive = FALSE;
|
|
ImgParms.page_num = 1;
|
|
ImgParms.total_num_pages = 1;
|
|
|
|
// file_type filled in previously
|
|
// x&y_resolut filled in previously
|
|
status = IMGSetParmsCgbw(pXferInfo->hImageWnd, PARM_IMGPARMS, &ImgParms, 0);
|
|
|
|
Scroll.lHorz = Scroll.lVert = 0;
|
|
IMGSetParmsCgbw(pXferInfo->hImageWnd, PARM_SCROLL,
|
|
&Scroll,
|
|
PARM_ABSOLUTE | PARM_REPAINT);
|
|
|
|
// Updates Menu items for IMGCreateWindowXX()
|
|
/* Pull out for not using UIEVENTS for WIN32
|
|
if (pXferInfo->dwDispFlag != OI_DONT_REPAINT) // only if on display
|
|
IMGFileSetDisplay(pXferInfo->hWnd);
|
|
Pull out complete, may cause problem - kfs */
|
|
}
|
|
else
|
|
{ // failed to lock it down
|
|
GlobalFree(hbm_acq);
|
|
hbm_acq = 0;
|
|
dcRC = TWRC_FAILURE;
|
|
}
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_XFERDONE, (WPARAM) hbm_acq, 0);
|
|
}
|
|
else
|
|
{
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_XFERDONE, (WPARAM) NULL, 0);
|
|
dcRC = TWRC_FAILURE;
|
|
}
|
|
|
|
// CHANGE: I would do a little error handling in App on handle
|
|
break;
|
|
|
|
case TWRC_CANCEL:
|
|
// the user canceled or wants to rescan the image
|
|
case TWRC_FAILURE:
|
|
default:
|
|
// something wrong, abort the transfer and delete the image
|
|
// pass a null ptr back to App
|
|
SendMessage ((pOiSupport->dcUI).hParent, PM_XFERDONE, (WPARAM) NULL, 0);
|
|
break;
|
|
}
|
|
return dcRC;
|
|
} // end NativeTransfer()
|
|
|