Here is a solution, starting from your code but arrange it a little bit.
Java Part...
Image im = null;
float left = 10.0f;
float right = 11.9f;
float top = 1.7f;
float bottom = 8.7f;
int resolution = 1000;
im = JTwain.preset(left,
right,
top,
bottom,
resolution);
JNI C++ Part... Excuse for the formating I don't realy have time to make it beautiful in that little box, but you can copy/paste into a C++ editor. By the way I was using Visual C++ 6.0, for Java it's Eclipse 3.1.2 but in Java it doesn't matter. The scanner I use is CanoScan 3000/3000F and like you with your example it was not working. Now it work perfectly. Take in note that you have a full example, because you have to change the PIXEL_TYPE before changing the ICAP_FRAMES. There is only two pixel type who's working TWUN_CENTIMETERS and TWUN_INCHES.
Good luck.
André Laberge.
JNIEXPORT jobject JNICALL Java_JTwain_preset(JNIEnv *env,
jclass clazz,
jfloat jLeft,
jfloat jRight,
jfloat jTop,
jfloat jBottom,
jint resolution){
// Create a static window whose handle is passed to DSM_Entry() when we
// open the data source manager.
cout << "Create windows" << endl;
HWND hwnd = CreateWindow ("STATIC",
"",
WS_POPUPWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_DESKTOP,
0,
g_hinstDLL,
0);
// If window could not be created, throw exception. Because the exception
// is not actually thrown until execution returns to Java, we must return
// a value -- (jobject) 0 was chosen to represent Image null. This value
// will not be seen in the Java code because of the exception.
if (hwnd == 0)
{
throwJTE (env, "Unable to create private window (preset)");
return (jobject) 0;
}
// Ensure that the default data source's dialog box does not disappear
// behind other windows, which can be very disconcerting to the user. We do
// that by making the hwnd -- created above and passed to DSM_Entry() below
// -- the handle of the topmost window.
SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE);
TW_UINT16 rc;
jobject image = 0;
cout << "Enter block 1" << endl;
BLOCK_BEGIN(1)
// Open the data source manager.
rc = (*g_pDSM_Entry) (&g_AppID,
0,
DG_CONTROL,
DAT_PARENT,
MSG_OPENDSM,
(TW_MEMREF) &hwnd);
// If data source manager could not be opened, throw exception. Because the
// exception is not actually thrown until execution returns to Java, we
// first exit current block to destroy previously-created window and return
// a value (which isn't seen in the Java code).
if (rc != TWRC_SUCCESS)
{
throwJTE (env, "Unable to open data source manager (preset)");
EXIT_CURRENT_BLOCK
}
cout << "Enter block 2" << endl;
BLOCK_BEGIN(2)
// Get the default data source's name.
TW_IDENTITY srcID;
ZeroMemory (&srcID, sizeof(srcID));
rc = (*g_pDSM_Entry) (&g_AppID,
0,
DG_CONTROL,
DAT_IDENTITY,
MSG_GETDEFAULT,
&srcID);
// If failure occurred, prepare to throw an exception, which is only thrown
// after this function ends.
if (rc == TWRC_FAILURE)
{
throwJTE (env, "Unable to obtain default data source name (preset)");
EXIT_CURRENT_BLOCK
}
// Open the default data source.
rc = (*g_pDSM_Entry) (&g_AppID,
0,
DG_CONTROL,
DAT_IDENTITY,
MSG_OPENDS,
&srcID);
cout << "srcID = " << srcID.ProductName << endl;
// If default data source could not be opened, throw exception. Because the
// exception is not actually thrown until execution returns to Java, we
// first exit current block to close data source manager and destroy the
// previously-created window.
if (rc != TWRC_SUCCESS)
{
throwJTE (env, "Unable to open default data source (preset)");
EXIT_CURRENT_BLOCK
}
cout << "Data source enabled" << endl;
cout << "Try to set capabilities" << endl;
// Set the current value of the ICAP_FRAMES capability.
TW_CAPABILITY cap;
memset(&cap, 0, sizeof(TW_CAPABILITY));
cap.ConType = TWON_ONEVALUE;
cap.Cap = ICAP_FRAMES;
//
//
// Set the ICAP_XRESOLUTION
//
//
cout << "Try to set ICAP_XRESOLUTION" << endl;
pTW_ONEVALUE pval = NULL;
cap.Cap = ICAP_XRESOLUTION;
cap.ConType = TWON_ONEVALUE;
cap.hContainer = GlobalAlloc(GHND, sizeof(TW_ONEVALUE));
pval = (pTW_ONEVALUE)GlobalLock(cap.hContainer);
pval->ItemType = TWTY_FIX32;
pval->Item = resolution;
// Application must allocate memory for the capability container.
GlobalUnlock(cap.hContainer);
TW_INT16 status = TWRC_FAILURE;
status = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_CAPABILITY,
MSG_SET,
(TW_MEMREF) &cap);
GlobalFree((HANDLE)cap.hContainer);
if (status != TWRC_SUCCESS)
{
throwJTE (env, "Unable to set ICAP_XRESOLUTION (setPreset)");
} else {
cout << "ICAP_XRESOLUTION change accept" << endl;
}
//
//
// Set the ICAP_YRESOLUTION
//
//
memset(&cap, 0, sizeof(TW_CAPABILITY));
cap.ConType = TWON_ONEVALUE;
cap.Cap = ICAP_FRAMES;
cout << "Try to set ICAP_YRESOLUTION" << endl;
pval = NULL;
cap.Cap = ICAP_YRESOLUTION;
cap.ConType = TWON_ONEVALUE;
cap.hContainer = GlobalAlloc(GHND, sizeof(TW_ONEVALUE));
pval = (pTW_ONEVALUE)GlobalLock(cap.hContainer);
pval->ItemType = TWTY_FIX32;
pval->Item = resolution;
// Application must allocate memory for the capability container.
GlobalUnlock(cap.hContainer);
status = TWRC_FAILURE;
status = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_CAPABILITY,
MSG_SET,
(TW_MEMREF) &cap);
GlobalFree((HANDLE)cap.hContainer);
if (status != TWRC_SUCCESS)
{
throwJTE (env, "Unable to set ICAP_YRESOLUTION (setPreset)");
} else {
cout << "ICAP_YRESOLUTION change accept" << endl;
}
//
//
// Set the ICAP_PIXELTYPE
//
//
memset(&cap, 0, sizeof(TW_CAPABILITY));
cap.ConType = TWON_ONEVALUE;
cap.Cap = ICAP_FRAMES;
cout << "Try to set ICAP_PIXELTYPE" << endl;
pval = NULL;
cap.Cap = ICAP_PIXELTYPE;
cap.ConType = TWON_ONEVALUE;
cap.hContainer = GlobalAlloc(GHND, sizeof(TW_ONEVALUE));
pval = (pTW_ONEVALUE)GlobalLock(cap.hContainer);
pval->ItemType = TWTY_UINT16;
pval->Item = TWPT_GRAY;
// Application must allocate memory for the capability container.
GlobalUnlock(cap.hContainer);
status = TWRC_FAILURE;
status = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_CAPABILITY,
MSG_SET,
(TW_MEMREF) &cap);
GlobalFree((HANDLE)cap.hContainer);
if (status != TWRC_SUCCESS)
{
throwJTE (env, "Unable to set ICAP_PIXELTYPE (setPreset)");
} else {
cout << "ICAP_PIXELTYPE change accept" << endl;
}
//
//
// Set the ICAP_UNITS
//
//
memset(&cap, 0, sizeof(TW_CAPABILITY));
cap.ConType = TWON_ONEVALUE;
cap.Cap = ICAP_FRAMES;
cout << "Try to set ICAP_UNITS" << endl;
pval = NULL;
cap.Cap = ICAP_UNITS;
cap.ConType = TWON_ONEVALUE;
cap.hContainer = GlobalAlloc(GHND, sizeof(TW_ONEVALUE));
pval = (pTW_ONEVALUE)GlobalLock(cap.hContainer);
pval->ItemType = TWTY_UINT16;
pval->Item = TWUN_CENTIMETERS; // Only TWUN_CENTIMETERS and TWUN_INCHES working
// Application must allocate memory for the capability container.
GlobalUnlock(cap.hContainer);
status = TWRC_FAILURE;
status = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_CAPABILITY,
MSG_SET,
(TW_MEMREF) &cap);
GlobalFree((HANDLE)cap.hContainer);
if (status != TWRC_SUCCESS)
{
throwJTE (env, "Unable to set ICAP_UNITS (setPreset)");
} else {
cout << "ICAP_UNITS change accept" << endl;
}
//
//
// Set the ICAP_FRAMES
//
//
cout << "Try to set ICAP_FRAMES" << endl;
TW_CAPABILITY pCap;
pCap.Cap = ICAP_FRAMES;
pCap.ConType = TWTY_FRAME;
TW_FRAME Frame ;
memset(&Frame, 0, sizeof(TW_FRAME));
memset(&pCap, 0, sizeof(TW_CAPABILITY));
pCap.ConType = TWON_ONEVALUE;
pCap.Cap = ICAP_FRAMES;
// This part is only to be clean
float cLeft = jLeft;
float cTop = jTop;
float cRight = jRight;
float cBottom = jBottom;
Frame.Left = FloatToFix32(cLeft);
Frame.Top = FloatToFix32(cTop);
Frame.Right = FloatToFix32(cRight);
Frame.Bottom = FloatToFix32(cBottom);
// Application must allocate memory for the capability container.
pCap.hContainer = GlobalAlloc(GHND,(sizeof(TW_ONEVALUE)+sizeof(TW_FRAME)));
if (pCap.hContainer == 0)
{
throwJTE (env, "Insufficient memory (ICAP_FRAMES)");
return (jobject) 0;
}
// Lock memory handle so that container's fields can be populated.
TW_ONEVALUE * pTWOneValue = (pTW_ONEVALUE) GlobalLock (pCap.hContainer);
char string[64];
memset(string, 0, 64);
TABLECAP *pTableCap;
// Populate container with appropriate data type and Physical Width
pTWOneValue->ItemType = TWTY_FRAME;
//pTWOneValue->Item = *((pTW_UINT32) pFrame);
memcpy(&pTWOneValue->Item, &Frame, sizeof(TW_FRAME));
// Unlock memory handle.
GlobalUnlock(pCap.hContainer);
rc = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_CAPABILITY,
MSG_SET,
(TW_MEMREF) &pCap);
cout << "Result of (ICAP_FRAMES) = " << rc << endl;
// If new current value could not be set, throw an appropriate exception.
if (rc != TWRC_SUCCESS)
{
// Determine if new current value could not be set because capability
// is not supported.
TW_STATUS status;
int rc = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_STATUS,
MSG_GET,
(TW_MEMREF) &status);
// Throw appropriate exception.
if (rc == TWRC_SUCCESS && status.ConditionCode == TWCC_BADCAP){
cout << "Bad capabilities (ICAP_FRAMES)" << endl;
} else {
cout << "Unable to set capability (ICAP_FRAMES) = " << rc << endl;
cout << "Unable to set capability (ICAP_FRAMES) status.ConditionCode = " << status.ConditionCode << endl;
throwJTE (env, "Unable to set capability (setFrames)");
}
}
// Application is responsible for freeing any memory that it allocates. The
// data source is not responsible for this task.
GlobalFree(pCap.hContainer);
//
//
// Do the acquisition
//
//
BLOCK_BEGIN(3)
// Prepare to enable the default data source. Make sure to show the data
// source's own user interface (dialog box).
TW_USERINTERFACE ui;
ui.ShowUI = FALSE;
ui.ModalUI = FALSE;
ui.hParent = hwnd;
// Enable the default data source.
rc = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_USERINTERFACE,
MSG_ENABLEDS,
&ui);
// If default data source could not be enabled, throw exception. Because
// the exception is not actually thrown until execution returns to Java, we
// first exit current block to close data source, close data source
// manager and destroy the previously-created window.
if (rc != TWRC_SUCCESS)
{
throwJTE (env, "Unable to enable default data source (acquire)");
EXIT_CURRENT_BLOCK
}
// Begin the event-handling loop. Data transfer takes place in this loop.
MSG msg;
TW_EVENT event;
TW_PENDINGXFERS pxfers;
while (GetMessage ((LPMSG) &msg, 0, 0, 0))
{
// Each window message must be forwarded to the default data source.
event.pEvent = (TW_MEMREF) &msg;
event.TWMessage = MSG_NULL;
rc = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_EVENT,
MSG_PROCESSEVENT,
(TW_MEMREF) &event);
// If the message does not correspond to a data source event, we must
// dispatch it to the appropriate Windows window.
if (rc == TWRC_NOTDSEVENT)
{
TranslateMessage ((LPMSG) &msg);
DispatchMessage ((LPMSG) &msg);
continue;
}
// If the default data source is requesting that the data source's
// dialog box be closed (user pressed Cancel), we must break out of the
// message loop.
if (event.TWMessage == MSG_CLOSEDSREQ)
break;
// If the default data source is requesting that it is ready to begin
// the data transfer, we must perform that transfer.
if (event.TWMessage == MSG_XFERREADY)
{
// Obtain information about the first image to be transferred.
TW_IMAGEINFO ii;
rc = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_IMAGE,
DAT_IMAGEINFO,
MSG_GET,
(TW_MEMREF) &ii);
// If unable to obtain image information ...
if (rc == TWRC_FAILURE)
{
// Cancel all transfers.
(*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_PENDINGXFERS,
MSG_RESET,
(TW_MEMREF) &pxfers);
// Throw exception upon return to Java and break out of event
// loop.
throwJTE (env, "Unable to obtain image information (acquire)");
break;
}
// If image is compressed or is not 8-bit color and not 24-bit
// color ...
if (ii.Compression != TWCP_NONE ||
ii.BitsPerPixel != 8 &&
ii.BitsPerPixel != 24)
{
// Cancel all transfers.
(*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_PENDINGXFERS,
MSG_RESET,
(TW_MEMREF) &pxfers);
// Throw exception upon return to Java and break out of event
// loop.
throwJTE (env, "Image compressed or not 8-bit/24-bit "
"(acquire)");
break;
}
// Perform the transfer.
TW_UINT32 handle;
rc = (*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_IMAGE,
DAT_IMAGENATIVEXFER,
MSG_GET,
(TW_MEMREF) &handle);
// If image not successfully transferred ...
if (rc != TWRC_XFERDONE)
{
// Cancel all remaining transfers.
(*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_PENDINGXFERS,
MSG_RESET,
(TW_MEMREF) &pxfers);
// Throw exception upon return to Java and break out of event
// loop.
throwJTE (env, "User aborted transfer or failure (acquire)");
break;
}
// Transfer Windows-based DIB to a Java-based Image (via a
// MemoryImageSource).
LPBITMAPINFOHEADER lpbmih;
lpbmih = (LPBITMAPINFOHEADER) GlobalLock ((HANDLE) handle);
if (ii.BitsPerPixel == 8)
image = xferDIB8toImage (lpbmih, env);
else
image = xferDIB24toImage (lpbmih, env);
// If unable to transfer image, throw an exception upon return to
// Java.
if (image == 0)
throwJTE (env, "Could not transfer DIB to Image (acquire)");
GlobalUnlock ((HANDLE) handle);
GlobalFree ((HANDLE) handle);
// Cancel all remaining transfers.
(*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_PENDINGXFERS,
MSG_RESET,
(TW_MEMREF) &pxfers);
// Convert TWRC_XFERDONE to TWRC_SUCCESS so that appropriate value
// is returned.
rc = TWRC_SUCCESS;
break;
}
}
// Disable the data source.
(*g_pDSM_Entry) (&g_AppID,
&srcID,
DG_CONTROL,
DAT_USERINTERFACE,
MSG_DISABLEDS,
&ui);
BLOCK_END(3)
// Close the data source.
(*g_pDSM_Entry) (&g_AppID,
0,
DG_CONTROL,
DAT_IDENTITY,
MSG_CLOSEDS,
&srcID);
BLOCK_END(2)
// Close the data source manager.
(*g_pDSM_Entry) (&g_AppID,
0,
DG_CONTROL,
DAT_PARENT,
MSG_CLOSEDSM,
(TW_MEMREF) &hwnd);
BLOCK_END(1)
// Destroy window.
DestroyWindow (hwnd);
return (rc == TWRC_SUCCESS) ? image : (jobject) 0;
} |