Initial checkin of Pika from heckimp
This commit is contained in:
92
plug-ins/twain/README
Normal file
92
plug-ins/twain/README
Normal file
@ -0,0 +1,92 @@
|
||||
TWAIN Plug-in
|
||||
Copyright (C) 1999 Craig Setera
|
||||
Craig Setera <setera@home.com>
|
||||
03/31/1999
|
||||
|
||||
Updated for Mac OS X support
|
||||
Brion Vibber <brion@pobox.com>
|
||||
07/22/2004
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Based on (at least) the following plug-ins:
|
||||
Screenshot
|
||||
GIF
|
||||
Randomize
|
||||
|
||||
Any suggestions, bug-reports or patches are welcome.
|
||||
|
||||
This plug-in interfaces to the TWAIN support library in order
|
||||
to capture images from TWAIN devices directly into PIKA images.
|
||||
The plug-in is capable of acquiring the following type of
|
||||
images:
|
||||
- B/W (1 bit images translated to grayscale B/W)
|
||||
- Grayscale up to 16 bits per pixel
|
||||
- RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
- Paletted images (both Gray and RGB)
|
||||
|
||||
Prerequisites:
|
||||
Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
also on 10.2).
|
||||
|
||||
Known problems:
|
||||
|
||||
- Multiple image transfers will hang the plug-in. The current
|
||||
configuration compiles with a maximum of single image transfers.
|
||||
- On Mac OS X, canceling doesn't always close things out fully.
|
||||
- Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
|
||||
Debugging:
|
||||
There are two different versions of the program included, a standard
|
||||
version and a version built for debugging. The debugging version is
|
||||
a special version capable of capturing the TWAIN datasource data to
|
||||
a file for later processing. This feature can be used to create a data
|
||||
dump that can be sent to me if for some reason the plug-in fails for
|
||||
your TWAIN datasource. The function of the plug-in is controlled by
|
||||
the name of the executable file. The plug-in should be placed in your
|
||||
plug-ins directory and named as follows:
|
||||
|
||||
twain.exe - This is the standard (non-debugging) version. This file will
|
||||
not behave differently if renamed. This version is intended to be used
|
||||
unless your TWAIN datasource has some problem.
|
||||
|
||||
gtwain.exe - This is the debugging version of the program shipped along.
|
||||
If this program is used as named, it will behave the same as "twain.exe"
|
||||
except that the file C:\twain.log will be written. This file is a text
|
||||
file with very little information available for debugging.
|
||||
|
||||
dtwain.exe - Renaming "gtwain.exe" to "dtwain.exe" in your plug-ins directory
|
||||
will change the behavior of the plug-in. The menu option will be registered
|
||||
as "TWAIN Acquire (Dump)..." and will cause the TWAIN acquire operation to
|
||||
be dumped to the file "C:\twaincap.bin". This file contains all of the data
|
||||
necessary to recreate the capture on another system (such as my machine). The
|
||||
image will not be displayed, as it might cause the plug-in to crash making
|
||||
the data useless. Instead, a message will be displayed that the image
|
||||
information was dumped to a file.
|
||||
|
||||
rtwain.exe - Renaming "gtwain.exe" to "rtwain.exe" in your plug-ins directory
|
||||
will change the behavior of the plug-in. The menu option will be registered
|
||||
as "TWAIN Acquire (Read)..." and will cause the TWAIN acquire operation to
|
||||
read a previously dumped (using dtwain.exe) TWAIN acquire from
|
||||
"C:\twaincap.bin".
|
||||
|
||||
If you find that you are unable to capture data from you datasource (the plug-in
|
||||
crashes or the image is wrong), please capture data using the following steps:
|
||||
|
||||
1) Copy gtwain.exe to your plug-ins directory as "dtwain.exe".
|
||||
2) Run PIKA.
|
||||
3) Choose Xtns->TWAIN Acquire (Dump)...
|
||||
4) Choose the datasource settings that are causing problems.
|
||||
5) Choose a *SMALL* sample image.
|
||||
6) Zip up "C:\twaincap.bin" and "C:\twain.log" and send them to me.
|
35
plug-ins/twain/meson.build
Normal file
35
plug-ins/twain/meson.build
Normal file
@ -0,0 +1,35 @@
|
||||
if not platform_windows
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
plugin_name = 'twain'
|
||||
|
||||
plugin_sources = [
|
||||
'tw_func.c',
|
||||
'tw_util.c',
|
||||
'tw_win.c',
|
||||
'twain.c',
|
||||
]
|
||||
|
||||
plugin_sources += windows.compile_resources(
|
||||
pika_plugins_rc,
|
||||
args: [
|
||||
'--define', 'ORIGINALFILENAME_STR="@0@"'.format(plugin_name+'.exe'),
|
||||
'--define', 'INTERNALNAME_STR="@0@"' .format(plugin_name),
|
||||
'--define', 'TOP_SRCDIR="@0@"' .format(meson.project_source_root()),
|
||||
],
|
||||
include_directories: [
|
||||
rootInclude, appInclude,
|
||||
],
|
||||
)
|
||||
|
||||
twain = executable(plugin_name,
|
||||
plugin_sources,
|
||||
dependencies: [
|
||||
libpika_dep,
|
||||
glib,
|
||||
gtk3,
|
||||
],
|
||||
install: true,
|
||||
install_dir: pikaplugindir / 'plug-ins' / plugin_name,
|
||||
)
|
BIN
plug-ins/twain/pika-twain.png
Normal file
BIN
plug-ins/twain/pika-twain.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
273
plug-ins/twain/tw_dump.c
Normal file
273
plug-ins/twain/tw_dump.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
* also on 10.2).
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
* - On Mac OS X, canceling doesn't always close things out fully.
|
||||
* - Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
* (07/23/04) v0.6 Added Mac OS X support.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "libpika/pika.h"
|
||||
|
||||
#include "tw_dump.h"
|
||||
#include "tw_func.h"
|
||||
#include "tw_util.h"
|
||||
|
||||
/* File variables */
|
||||
static FILE *outputFile = NULL;
|
||||
extern pTW_SESSION twSession;
|
||||
|
||||
/*
|
||||
* dumpPreTransferCallback
|
||||
*
|
||||
* This callback function is called before any images
|
||||
* are transferred. Set up the one time only stuff.
|
||||
*/
|
||||
void
|
||||
dumpPreTransferCallback(void *clientData)
|
||||
{
|
||||
/* Open our output file... Not settable... Always
|
||||
* write to the root directory. Simplistic, but
|
||||
* gets the job done.
|
||||
*/
|
||||
outputFile = g_fopen(DUMP_FILE, "wb");
|
||||
}
|
||||
|
||||
/*
|
||||
* dumpBeginTransferCallback
|
||||
*
|
||||
* The following function is called at the beginning
|
||||
* of each image transfer.
|
||||
*/
|
||||
int
|
||||
dumpBeginTransferCallback(pTW_IMAGEINFO imageInfo, void *clientData)
|
||||
{
|
||||
logBegin(imageInfo, clientData);
|
||||
|
||||
/* Dump the image information */
|
||||
fwrite((void *) imageInfo, sizeof(TW_IMAGEINFO), 1, outputFile);
|
||||
|
||||
/* Keep going */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dumpDataTransferCallback
|
||||
*
|
||||
* The following function is called for each memory
|
||||
* block that is transferred from the data source.
|
||||
*/
|
||||
int
|
||||
dumpDataTransferCallback(pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData)
|
||||
{
|
||||
int flag = 1;
|
||||
|
||||
logData(imageInfo, imageMemXfer, clientData);
|
||||
|
||||
/* Write a flag that says that this is a data packet */
|
||||
fwrite((void *) &flag, sizeof(int), 1, outputFile);
|
||||
|
||||
/* Dump the memory information */
|
||||
fwrite((void *) imageMemXfer, sizeof(TW_IMAGEMEMXFER), 1, outputFile);
|
||||
fwrite((void *) imageMemXfer->Memory.TheMem,
|
||||
1, imageMemXfer->BytesWritten, outputFile);
|
||||
|
||||
/* Keep going */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dumpEndTransferCallback
|
||||
*
|
||||
* The following function is called at the end of the
|
||||
* image transfer. The caller will be handed
|
||||
* the image transfer completion state. The
|
||||
* following values (defined in twain.h) are
|
||||
* possible:
|
||||
*
|
||||
* TWRC_XFERDONE
|
||||
* The transfer completed successfully
|
||||
* TWRC_CANCEL
|
||||
* The transfer was completed by the user
|
||||
* TWRC_FAILURE
|
||||
* The transfer failed.
|
||||
*/
|
||||
int
|
||||
dumpEndTransferCallback(int completionState, int pendingCount, void *clientData)
|
||||
{
|
||||
int flag = 0;
|
||||
|
||||
/* Write a flag that says that this is a data packet */
|
||||
fwrite((void *) &flag, sizeof(int), 1, outputFile);
|
||||
|
||||
/* Write the necessary data */
|
||||
fwrite(&completionState, sizeof(int), 1, outputFile);
|
||||
fwrite(&pendingCount, sizeof(int), 1, outputFile);
|
||||
|
||||
/* Only ever transfer a single image */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dumpPostTransferCallback
|
||||
*
|
||||
* This callback function will be called
|
||||
* after all possible images have been
|
||||
* transferred.
|
||||
*/
|
||||
void
|
||||
dumpPostTransferCallback(int pendingCount, void *clientData)
|
||||
{
|
||||
char buffer[128];
|
||||
|
||||
/* Shut things down. */
|
||||
if (pendingCount != 0)
|
||||
cancelPendingTransfers(twSession);
|
||||
|
||||
/* This will close the datasource and datasource
|
||||
* manager. Then the message queue will be shut
|
||||
* down and the run() procedure will finally be
|
||||
* able to finish.
|
||||
*/
|
||||
disableDS(twSession);
|
||||
closeDS(twSession);
|
||||
closeDSM(twSession);
|
||||
|
||||
/* Close the dump file */
|
||||
fclose(outputFile);
|
||||
|
||||
/* Tell the user */
|
||||
sprintf(buffer, "Image dumped to file %s\n", DUMP_FILE);
|
||||
pika_message(buffer);
|
||||
|
||||
/* Post a message to close up the application */
|
||||
twainQuitApplication ();
|
||||
}
|
||||
|
||||
/*
|
||||
* readDumpedImage
|
||||
*
|
||||
* Get a previously dumped image.
|
||||
*/
|
||||
void readDumpedImage(pTW_SESSION twSession)
|
||||
{
|
||||
int moreData;
|
||||
int completionState;
|
||||
int pendingCount;
|
||||
|
||||
TW_IMAGEINFO imageInfo;
|
||||
TW_IMAGEMEMXFER imageMemXfer;
|
||||
|
||||
/* Open our output file... Not settable... Always
|
||||
* write to the root directory. Simplistic, but
|
||||
* gets the job done.
|
||||
*/
|
||||
FILE *inputFile = g_fopen(DUMP_FILE, "rb");
|
||||
|
||||
/*
|
||||
* Inform our application that we are getting ready
|
||||
* to transfer images.
|
||||
*/
|
||||
(*twSession->transferFunctions->preTxfrCb)(NULL);
|
||||
|
||||
/* Read the image information */
|
||||
fread((void *) &imageInfo, sizeof(TW_IMAGEINFO), 1, inputFile);
|
||||
|
||||
/* Call the begin transfer callback */
|
||||
if (!(*twSession->transferFunctions->txfrBeginCb)(&imageInfo, twSession->clientData))
|
||||
return;
|
||||
|
||||
/* Read all of the data packets */
|
||||
fread((void *) &moreData, sizeof(int), 1, inputFile);
|
||||
while (moreData) {
|
||||
/* Read the memory information */
|
||||
fread((void *) &imageMemXfer, sizeof(TW_IMAGEMEMXFER), 1, inputFile);
|
||||
imageMemXfer.Memory.TheMem = (TW_MEMREF) g_malloc (imageMemXfer.BytesWritten);
|
||||
fread((void *) imageMemXfer.Memory.TheMem,
|
||||
1, imageMemXfer.BytesWritten, inputFile);
|
||||
|
||||
/* Call the data transfer callback function */
|
||||
if (!(*twSession->transferFunctions->txfrDataCb)
|
||||
(&imageInfo,
|
||||
&imageMemXfer,
|
||||
twSession->clientData))
|
||||
return;
|
||||
|
||||
/* Clean up the memory */
|
||||
g_free (imageMemXfer.Memory.TheMem);
|
||||
|
||||
/* Check for continuation */
|
||||
fread((void *) &moreData, sizeof(int), 1, inputFile);
|
||||
}
|
||||
|
||||
/* Grab the final information */
|
||||
fread(&completionState, sizeof(int), 1, inputFile);
|
||||
fread(&pendingCount, sizeof(int), 1, inputFile);
|
||||
|
||||
if (twSession->transferFunctions->txfrEndCb)
|
||||
(*twSession->transferFunctions->txfrEndCb)(completionState, 0,
|
||||
twSession->clientData);
|
||||
|
||||
/* Post a message to close up the application */
|
||||
twainQuitApplication ();
|
||||
}
|
70
plug-ins/twain/tw_dump.h
Normal file
70
plug-ins/twain/tw_dump.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* This plug-in will not compile on anything other than a Win32
|
||||
* platform. Although the TWAIN documentation implies that there
|
||||
* is TWAIN support available on Macintosh, I neither have a
|
||||
* Macintosh nor the interest in porting this. If anyone else
|
||||
* has an interest, consult www.twain.org for more information on
|
||||
* interfacing to TWAIN.
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
*/
|
||||
|
||||
#include "tw_platform.h"
|
||||
#include "tw_func.h"
|
||||
|
||||
void dumpPreTransferCallback(void *clientData);
|
||||
int dumpBeginTransferCallback(pTW_IMAGEINFO imageInfo, void *clientData);
|
||||
int dumpDataTransferCallback(pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData);
|
||||
int dumpEndTransferCallback(int completionState, int pendingCount, void *clientData);
|
||||
void dumpPostTransferCallback(int pendingCount, void *clientData);
|
||||
void readDumpedImage(pTW_SESSION twSession);
|
||||
|
878
plug-ins/twain/tw_func.c
Normal file
878
plug-ins/twain/tw_func.c
Normal file
@ -0,0 +1,878 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
* also on 10.2).
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
* - On Mac OS X, canceling doesn't always close things out fully.
|
||||
* - Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
* (07/23/04) v0.6 Added Mac OS X support.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h> /* Needed when compiling with gcc */
|
||||
|
||||
#include "tw_func.h"
|
||||
#include "tw_util.h"
|
||||
#include "tw_local.h"
|
||||
|
||||
/*
|
||||
* Twain error code to string mappings
|
||||
*/
|
||||
static int twainErrorCount = 0;
|
||||
static char *twainErrors[] = {
|
||||
"No error",
|
||||
"Failure due to unknown causes",
|
||||
"Not enough memory to perform operation",
|
||||
"No Data Source",
|
||||
"DS is connected to max possible apps",
|
||||
"DS or DSM reported error, application shouldn't",
|
||||
"Unknown capability",
|
||||
"Unrecognized MSG DG DAT combination",
|
||||
"Data parameter out of range",
|
||||
"DG DAT MSG out of expected sequence",
|
||||
"Unknown destination App/Src in DSM_Entry",
|
||||
"Capability not supported by source",
|
||||
"Operation not supported by capability",
|
||||
"Capability has dependency on other capability",
|
||||
"File System operation is denied (file is protected)",
|
||||
"Operation failed because file already exists.",
|
||||
"File not found",
|
||||
"Operation failed because directory is not empty",
|
||||
"The feeder is jammed",
|
||||
"The feeder detected multiple pages",
|
||||
"Error writing the file (disk full?)",
|
||||
"The device went offline prior to or during this operation",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* FloatToFix32
|
||||
*
|
||||
* Convert a floating point value into a FIX32.
|
||||
*/
|
||||
TW_FIX32 FloatToFIX32(float floater)
|
||||
{
|
||||
TW_FIX32 Fix32_value;
|
||||
TW_INT32 value = (TW_INT32) (floater * 65536.0 + 0.5);
|
||||
Fix32_value.Whole = value >> 16;
|
||||
Fix32_value.Frac = value & 0x0000ffffL;
|
||||
return (Fix32_value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix32ToFloat
|
||||
*
|
||||
* Convert a FIX32 value into a floating point value.
|
||||
*/
|
||||
float FIX32ToFloat(TW_FIX32 fix32)
|
||||
{
|
||||
float floater;
|
||||
floater = (float) fix32.Whole + (float) fix32.Frac / 65536.0;
|
||||
return floater;
|
||||
}
|
||||
|
||||
/*
|
||||
* twainError
|
||||
*
|
||||
* Return the TWAIN error message associated
|
||||
* with the specified error code.
|
||||
*/
|
||||
char *
|
||||
twainError(int errorCode)
|
||||
{
|
||||
/* Check whether we've counted */
|
||||
if (twainErrorCount == 0)
|
||||
while (twainErrors[twainErrorCount++]) {}
|
||||
|
||||
/* Check out of bounds */
|
||||
if (errorCode >= twainErrorCount)
|
||||
return "Unknown TWAIN Error Code";
|
||||
else
|
||||
return twainErrors[errorCode];
|
||||
}
|
||||
|
||||
/*
|
||||
* currentTwainError
|
||||
*
|
||||
* Return the current TWAIN error message.
|
||||
*/
|
||||
char *
|
||||
currentTwainError(pTW_SESSION twSession)
|
||||
{
|
||||
TW_STATUS twStatus;
|
||||
|
||||
/* Get the current status code from the DSM */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_STATUS, MSG_GET,
|
||||
(TW_MEMREF) &twStatus);
|
||||
|
||||
/* Return the mapped error code */
|
||||
return twainError(twStatus.ConditionCode);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getImage
|
||||
*
|
||||
* This is a "high-level" function that can be called in order
|
||||
* to take all of the steps necessary to kick off an image-transfer
|
||||
* from a user-specified TWAIN datasource. The data will be passed
|
||||
* back to the callback function specified in the session structure.
|
||||
*/
|
||||
int
|
||||
getImage(pTW_SESSION twSession)
|
||||
{
|
||||
/* Do some sanity checking first and bail
|
||||
* if necessary.
|
||||
*/
|
||||
|
||||
if (!twainIsAvailable()) {
|
||||
LogMessage("TWAIN is not available for image capture\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* One step at a time */
|
||||
if (!openDSM(twSession)) {
|
||||
LogMessage("Unable to open data source manager\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!selectDS(twSession)) {
|
||||
LogMessage("Data source not selected\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!openDS(twSession)) {
|
||||
LogMessage("Unable to open datasource\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
requestImageAcquire(twSession, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* openDSM
|
||||
*
|
||||
* Open the data source manager
|
||||
*/
|
||||
int
|
||||
openDSM(pTW_SESSION twSession)
|
||||
{
|
||||
/* Make sure that we aren't already open */
|
||||
if (DSM_IS_OPEN(twSession))
|
||||
return TRUE;
|
||||
|
||||
/* Open the data source manager */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), NULL,
|
||||
DG_CONTROL, DAT_PARENT, MSG_OPENDSM,
|
||||
(TW_MEMREF) &(twSession->hwnd));
|
||||
|
||||
/* Check the return code */
|
||||
switch (twSession->twRC) {
|
||||
case TWRC_SUCCESS:
|
||||
/* We are now at state 3 */
|
||||
twSession->twainState = 3;
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case TWRC_FAILURE:
|
||||
default:
|
||||
LogMessage("OpenDSM failure\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* selectDS
|
||||
*
|
||||
* Select a datasource using the TWAIN user
|
||||
* interface.
|
||||
*/
|
||||
int
|
||||
selectDS(pTW_SESSION twSession)
|
||||
{
|
||||
/* The datasource manager must be open */
|
||||
if (DSM_IS_CLOSED(twSession)) {
|
||||
LogMessage("Can't select data source with closed source manager\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Ask TWAIN to present the source select dialog */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), NULL,
|
||||
DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT,
|
||||
(TW_MEMREF) DS_IDENTITY(twSession));
|
||||
|
||||
/* Check the return to determine what the user decided
|
||||
* to do.
|
||||
*/
|
||||
switch (twSession->twRC) {
|
||||
case TWRC_SUCCESS:
|
||||
LogMessage("Data source %s selected\n", DS_IDENTITY(twSession)->ProductName);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case TWRC_CANCEL:
|
||||
LogMessage("User cancelled TWAIN source selection\n");
|
||||
break;
|
||||
|
||||
case TWRC_FAILURE:
|
||||
default:
|
||||
LogMessage("Error \"%s\" during TWAIN source selection\n",
|
||||
currentTwainError(twSession));
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* selectDefaultDS
|
||||
*
|
||||
* Select the default datasource.
|
||||
*/
|
||||
int
|
||||
selectDefaultDS(pTW_SESSION twSession)
|
||||
{
|
||||
/* The datasource manager must be open */
|
||||
if (DSM_IS_CLOSED(twSession)) {
|
||||
LogMessage("Can't select data source with closed source manager\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Ask TWAIN to present the source select dialog */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), NULL,
|
||||
DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT,
|
||||
(TW_MEMREF) DS_IDENTITY(twSession));
|
||||
|
||||
/* Check the return code */
|
||||
return (twSession->twRC == TWRC_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* openDS
|
||||
*
|
||||
* Open a data source using the TWAIN user interface.
|
||||
*/
|
||||
int
|
||||
openDS(pTW_SESSION twSession)
|
||||
{
|
||||
TW_IDENTITY *dsIdentity;
|
||||
|
||||
/* The datasource manager must be open */
|
||||
if (DSM_IS_CLOSED(twSession)) {
|
||||
LogMessage("openDS: Cannot open data source... manager closed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Is the data source already open? */
|
||||
if (DS_IS_OPEN(twSession)) {
|
||||
LogMessage("openDS: Data source already open\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Open the TWAIN datasource */
|
||||
dsIdentity = DS_IDENTITY(twSession);
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), NULL,
|
||||
DG_CONTROL, DAT_IDENTITY, MSG_OPENDS,
|
||||
(TW_MEMREF) dsIdentity);
|
||||
|
||||
/* Check the return to determine what the user decided
|
||||
* to do.
|
||||
*/
|
||||
switch (twSession->twRC) {
|
||||
case TWRC_SUCCESS:
|
||||
/* We are now in TWAIN state 4 */
|
||||
twSession->twainState = 4;
|
||||
LogMessage("Data source %s opened\n", DS_IDENTITY(twSession)->ProductName);
|
||||
LogMessage("\tVersion.MajorNum = %d\n", dsIdentity->Version.MajorNum);
|
||||
LogMessage("\tVersion.MinorNum = %d\n", dsIdentity->Version.MinorNum);
|
||||
LogMessage("\tVersion.Info = %s\n", dsIdentity->Version.Info);
|
||||
LogMessage("\tProtocolMajor = %d\n", dsIdentity->ProtocolMajor);
|
||||
LogMessage("\tProtocolMinor = %d\n", dsIdentity->ProtocolMinor);
|
||||
LogMessage("\tManufacturer = %s\n", dsIdentity->Manufacturer);
|
||||
LogMessage("\tProductFamily = %s\n", dsIdentity->ProductFamily);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LogMessage("Error \"%s\" opening data source\n", currentTwainError(twSession));
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* setBufferedXfer
|
||||
*/
|
||||
static int
|
||||
setBufferedXfer(pTW_SESSION twSession)
|
||||
{
|
||||
TW_CAPABILITY bufXfer;
|
||||
pTW_ONEVALUE pvalOneValue;
|
||||
|
||||
/* Make sure the data source is open first */
|
||||
if (DS_IS_CLOSED(twSession))
|
||||
return FALSE;
|
||||
|
||||
/* Create the capability information */
|
||||
bufXfer.Cap = ICAP_XFERMECH;
|
||||
bufXfer.ConType = TWON_ONEVALUE;
|
||||
bufXfer.hContainer = twainAllocHandle(sizeof(TW_ONEVALUE));
|
||||
|
||||
pvalOneValue = (pTW_ONEVALUE) twainLockHandle(bufXfer.hContainer);
|
||||
pvalOneValue->ItemType = TWTY_UINT16;
|
||||
pvalOneValue->Item = TWSX_MEMORY;
|
||||
twainUnlockHandle(bufXfer.hContainer);
|
||||
|
||||
/* Make the call to the source manager */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_CAPABILITY, MSG_SET,
|
||||
(TW_MEMREF) &bufXfer);
|
||||
|
||||
/* Free the container */
|
||||
twainFreeHandle(bufXfer.hContainer);
|
||||
|
||||
/* Let the caller know what happened */
|
||||
return (twSession->twRC==TWRC_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* requestImageAcquire
|
||||
*
|
||||
* Request that the acquire user interface
|
||||
* be displayed. This may or may not cause
|
||||
* an image to actually be transferred.
|
||||
*/
|
||||
int
|
||||
requestImageAcquire(pTW_SESSION twSession, gboolean showUI)
|
||||
{
|
||||
/* Make sure in the correct state */
|
||||
if (DS_IS_CLOSED(twSession)) {
|
||||
LogMessage("Can't acquire image with closed datasource\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
twainSetupCallback(twSession);
|
||||
|
||||
/* Set the transfer mode */
|
||||
if (setBufferedXfer(twSession)) {
|
||||
TW_USERINTERFACE ui;
|
||||
|
||||
/* Set the UI information */
|
||||
ui.ShowUI = TRUE;
|
||||
ui.ModalUI = TRUE;
|
||||
/* In Windows, the callbacks are sent to the window message handler */
|
||||
ui.hParent = twSession->hwnd;
|
||||
|
||||
/* Make the call to the source manager */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_USERINTERFACE, MSG_ENABLEDS,
|
||||
(TW_MEMREF) &ui);
|
||||
|
||||
if (twSession->twRC == TWRC_SUCCESS) {
|
||||
/* We are now at a new twain state */
|
||||
twSession->twainState = 5;
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
LogMessage("Error during data source enable\n");
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
LogMessage("Unable to set buffered transfer mode: %s\n",
|
||||
currentTwainError(twSession));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* disableDS
|
||||
*
|
||||
* Disable the datasource associated with twSession.
|
||||
*/
|
||||
int
|
||||
disableDS(pTW_SESSION twSession)
|
||||
{
|
||||
TW_USERINTERFACE ui;
|
||||
|
||||
/* Verify the datasource is enabled */
|
||||
if (DS_IS_DISABLED(twSession)) {
|
||||
LogMessage("disableDS: Data source not enabled\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set the UI information */
|
||||
ui.ShowUI = TRUE;
|
||||
ui.ModalUI = TRUE;
|
||||
ui.hParent = twSession->hwnd;
|
||||
|
||||
/* Make the call to the source manager */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_USERINTERFACE, MSG_DISABLEDS,
|
||||
(TW_MEMREF) &ui);
|
||||
|
||||
if (twSession->twRC == TWRC_SUCCESS) {
|
||||
/* We are now at a new twain state */
|
||||
twSession->twainState = 4;
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
LogMessage("Error during data source disable\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* closeDS
|
||||
*
|
||||
* Close the datasource associated with the
|
||||
* specified session.
|
||||
*/
|
||||
int
|
||||
closeDS(pTW_SESSION twSession)
|
||||
{
|
||||
/* Can't close a closed data source */
|
||||
if (DS_IS_CLOSED(twSession)) {
|
||||
LogMessage("closeDS: Data source already closed\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Open the TWAIN datasource */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), NULL,
|
||||
DG_CONTROL, DAT_IDENTITY, MSG_CLOSEDS,
|
||||
(TW_MEMREF) DS_IDENTITY(twSession));
|
||||
|
||||
/* Check the return to determine what the user decided
|
||||
* to do.
|
||||
*/
|
||||
switch (twSession->twRC) {
|
||||
case TWRC_SUCCESS:
|
||||
/* We are now in TWAIN state 3 */
|
||||
twSession->twainState = 3;
|
||||
LogMessage("Data source %s closed\n", DS_IDENTITY(twSession)->ProductName);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
LogMessage("Error \"%s\" closing data source\n", currentTwainError(twSession));
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* closeDSM
|
||||
*
|
||||
* Close the data source manager
|
||||
*/
|
||||
int
|
||||
closeDSM(pTW_SESSION twSession)
|
||||
{
|
||||
if (DSM_IS_CLOSED(twSession)) {
|
||||
LogMessage("closeDSM: Source Manager not open\n");
|
||||
return FALSE;
|
||||
} else {
|
||||
if (DS_IS_OPEN(twSession)) {
|
||||
LogMessage("closeDSM: Can't close source manager with open source\n");
|
||||
return FALSE;
|
||||
} else {
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), NULL,
|
||||
DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM,
|
||||
(TW_MEMREF)&(twSession->hwnd));
|
||||
|
||||
if (twSession->twRC != TWRC_SUCCESS) {
|
||||
LogMessage("CloseDSM failure -- %s\n", currentTwainError(twSession));
|
||||
}
|
||||
else {
|
||||
|
||||
/* We are now in state 2 */
|
||||
twSession->twainState = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Let the caller know what happened */
|
||||
return (twSession->twRC==TWRC_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* beginImageTransfer
|
||||
*
|
||||
* Begin an image transfer.
|
||||
*/
|
||||
static int
|
||||
beginImageTransfer(pTW_SESSION twSession, pTW_IMAGEINFO imageInfo)
|
||||
{
|
||||
/* Clear our structures */
|
||||
memset(imageInfo, 0, sizeof(TW_IMAGEINFO));
|
||||
|
||||
/* Query the image information */
|
||||
twSession->twRC = callDSM(
|
||||
APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_IMAGE, DAT_IMAGEINFO, MSG_GET,
|
||||
(TW_MEMREF) imageInfo);
|
||||
|
||||
/* Check the return code */
|
||||
if (twSession->twRC != TWRC_SUCCESS) {
|
||||
LogMessage("Get Image Info failure - %s\n", currentTwainError(twSession));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Call the begin transfer callback if registered */
|
||||
if (twSession->transferFunctions->txfrBeginCb)
|
||||
if (!(*twSession->transferFunctions->txfrBeginCb)(imageInfo, twSession->clientData))
|
||||
return FALSE;
|
||||
|
||||
/* We should continue */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* transferImage
|
||||
*
|
||||
* The Source indicated it is ready to transfer data. It is
|
||||
* waiting for the application to inquire about the image details,
|
||||
* initiate the actual transfer, and, hence, transition the session
|
||||
* from State 6 to 7. Return the reason for exiting the transfer.
|
||||
*/
|
||||
static void
|
||||
transferImage(pTW_SESSION twSession, pTW_IMAGEINFO imageInfo)
|
||||
{
|
||||
TW_SETUPMEMXFER setupMemXfer;
|
||||
TW_IMAGEMEMXFER imageMemXfer;
|
||||
char *buffer;
|
||||
|
||||
/* Clear our structures */
|
||||
memset(&setupMemXfer, 0, sizeof(TW_SETUPMEMXFER));
|
||||
memset(&imageMemXfer, 0, sizeof(TW_IMAGEMEMXFER));
|
||||
|
||||
/* Find out how the source would like to transfer... */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_SETUPMEMXFER, MSG_GET,
|
||||
(TW_MEMREF) &setupMemXfer);
|
||||
|
||||
/* Allocate the buffer for the transfer */
|
||||
buffer = g_new (char, setupMemXfer.Preferred);
|
||||
imageMemXfer.Memory.Flags = TWMF_APPOWNS | TWMF_POINTER;
|
||||
imageMemXfer.Memory.Length = setupMemXfer.Preferred;
|
||||
imageMemXfer.Memory.TheMem = (TW_MEMREF) buffer;
|
||||
|
||||
/* Get the data */
|
||||
do {
|
||||
/* Setup for the memory transfer */
|
||||
imageMemXfer.Compression = TWON_DONTCARE16;
|
||||
imageMemXfer.BytesPerRow = TWON_DONTCARE32;
|
||||
imageMemXfer.Columns = TWON_DONTCARE32;
|
||||
imageMemXfer.Rows = TWON_DONTCARE32;
|
||||
imageMemXfer.XOffset = TWON_DONTCARE32;
|
||||
imageMemXfer.YOffset = TWON_DONTCARE32;
|
||||
imageMemXfer.BytesWritten = TWON_DONTCARE32;
|
||||
|
||||
/* Get the next block of memory */
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_IMAGE, DAT_IMAGEMEMXFER, MSG_GET,
|
||||
(TW_MEMREF) &imageMemXfer);
|
||||
|
||||
if ((twSession->twRC == TWRC_SUCCESS) ||
|
||||
(twSession->twRC == TWRC_XFERDONE)) {
|
||||
/* Call the callback function */
|
||||
if (!(*twSession->transferFunctions->txfrDataCb) (
|
||||
imageInfo,
|
||||
&imageMemXfer,
|
||||
twSession->clientData)) {
|
||||
/* Callback function requested to cancel */
|
||||
twSession->twRC = TWRC_CANCEL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (twSession->twRC == TWRC_SUCCESS);
|
||||
|
||||
/* Free the memory buffer */
|
||||
g_free (imageMemXfer.Memory.TheMem);
|
||||
}
|
||||
|
||||
/*
|
||||
* endPendingTransfer
|
||||
*
|
||||
* Cancel the currently pending transfer.
|
||||
* Return the count of pending transfers.
|
||||
*/
|
||||
static int
|
||||
endPendingTransfer(pTW_SESSION twSession)
|
||||
{
|
||||
TW_PENDINGXFERS pendingXfers;
|
||||
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_PENDINGXFERS, MSG_ENDXFER,
|
||||
(TW_MEMREF) &pendingXfers);
|
||||
|
||||
if (!pendingXfers.Count)
|
||||
twSession->twainState = 5;
|
||||
|
||||
return pendingXfers.Count;
|
||||
}
|
||||
|
||||
/*
|
||||
* cancelPendingTransfers
|
||||
*
|
||||
* Cancel all pending image transfers.
|
||||
*/
|
||||
void
|
||||
cancelPendingTransfers(pTW_SESSION twSession)
|
||||
{
|
||||
TW_PENDINGXFERS pendingXfers;
|
||||
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET,
|
||||
(TW_MEMREF) &pendingXfers);
|
||||
}
|
||||
|
||||
/*
|
||||
* endImageTransfer
|
||||
*
|
||||
* Finish transferring an image. Return the count
|
||||
* of pending images.
|
||||
*/
|
||||
static int
|
||||
endImageTransfer(pTW_SESSION twSession, int *pendingCount)
|
||||
{
|
||||
gboolean continueTransfers = FALSE;
|
||||
int exitCode = twSession->twRC;
|
||||
|
||||
/* Have now exited the transfer for some reason... Figure out
|
||||
* why and what to do about it
|
||||
*/
|
||||
switch (twSession->twRC) {
|
||||
case TWRC_XFERDONE:
|
||||
case TWRC_CANCEL:
|
||||
LogMessage("Xfer done received\n");
|
||||
*pendingCount = endPendingTransfer(twSession);
|
||||
break;
|
||||
|
||||
case TWRC_FAILURE:
|
||||
LogMessage("Failure received\n");
|
||||
*pendingCount = endPendingTransfer(twSession);
|
||||
break;
|
||||
|
||||
default:
|
||||
*pendingCount = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call the end transfer callback */
|
||||
if (twSession->transferFunctions->txfrEndCb)
|
||||
continueTransfers =
|
||||
(*twSession->transferFunctions->txfrEndCb)(exitCode,
|
||||
*pendingCount,
|
||||
twSession->clientData);
|
||||
|
||||
return (*pendingCount && continueTransfers);
|
||||
}
|
||||
|
||||
/*
|
||||
* transferImages
|
||||
*
|
||||
* Transfer all of the images that are available from the
|
||||
* datasource.
|
||||
*/
|
||||
static void
|
||||
transferImages(pTW_SESSION twSession)
|
||||
{
|
||||
TW_IMAGEINFO imageInfo;
|
||||
int pendingCount;
|
||||
|
||||
/* Check the image transfer callback function
|
||||
* before even attempting to do the transfer
|
||||
*/
|
||||
if (!twSession->transferFunctions || !twSession->transferFunctions->txfrDataCb) {
|
||||
LogMessage("Attempting image transfer without callback function\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform our application that we are getting ready
|
||||
* to transfer images.
|
||||
*/
|
||||
if (twSession->transferFunctions->preTxfrCb)
|
||||
(*twSession->transferFunctions->preTxfrCb)(twSession->clientData);
|
||||
|
||||
/* Loop through the available images */
|
||||
do {
|
||||
/* Move to the new state */
|
||||
twSession->twainState = 6;
|
||||
|
||||
/* Begin the image transfer */
|
||||
if (!beginImageTransfer(twSession, &imageInfo))
|
||||
continue;
|
||||
|
||||
/* Call the image transfer function */
|
||||
transferImage(twSession, &imageInfo);
|
||||
|
||||
} while (endImageTransfer(twSession, &pendingCount));
|
||||
|
||||
/*
|
||||
* Inform our application that we are done
|
||||
* transferring images.
|
||||
*/
|
||||
if (twSession->transferFunctions->postTxfrCb)
|
||||
(*twSession->transferFunctions->postTxfrCb)(pendingCount,
|
||||
twSession->clientData);
|
||||
}
|
||||
|
||||
void
|
||||
processTwainMessage(TW_UINT16 message, pTW_SESSION twSession)
|
||||
{
|
||||
switch (message) {
|
||||
case MSG_XFERREADY:
|
||||
LogMessage("Source says that data is ready\n");
|
||||
transferImages(twSession);
|
||||
break;
|
||||
|
||||
case MSG_CLOSEDSREQ:
|
||||
/* Disable the datasource, Close the Data source
|
||||
* and close the data source manager
|
||||
*/
|
||||
LogMessage("CloseDSReq\n");
|
||||
disableDS(twSession);
|
||||
closeDS(twSession);
|
||||
closeDSM(twSession);
|
||||
break;
|
||||
|
||||
/* No message from the Source to the App break;
|
||||
* possible new message
|
||||
*/
|
||||
case MSG_NULL:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Session related functions
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
* newSession
|
||||
*
|
||||
* Create a new TWAIN session.
|
||||
*/
|
||||
pTW_SESSION
|
||||
newSession(pTW_IDENTITY appIdentity) {
|
||||
/* Create the structure */
|
||||
pTW_SESSION session = g_new (TW_SESSION, 1);
|
||||
|
||||
/* Set the structure fields */
|
||||
session->hwnd = 0;
|
||||
session->twRC = TWRC_SUCCESS;
|
||||
session->appIdentity = appIdentity;
|
||||
session->dsIdentity = g_new (TW_IDENTITY, 1);
|
||||
session->dsIdentity->Id = 0;
|
||||
session->dsIdentity->ProductName[0] = '\0';
|
||||
session->transferFunctions = NULL;
|
||||
|
||||
if (twainIsAvailable())
|
||||
session->twainState = 2;
|
||||
else
|
||||
session->twainState = 0;
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/*
|
||||
* registerWindowHandle
|
||||
*
|
||||
* Register the window handle to be used for this
|
||||
* session.
|
||||
*/
|
||||
void
|
||||
registerWindowHandle(pTW_SESSION session, TW_HANDLE hwnd)
|
||||
{
|
||||
session->hwnd = hwnd;
|
||||
}
|
||||
|
||||
/*
|
||||
* registerTransferCallback
|
||||
*
|
||||
* Register the callback to use when transferring
|
||||
* image data.
|
||||
*/
|
||||
void
|
||||
registerTransferCallbacks(pTW_SESSION session,
|
||||
pTXFR_CB_FUNCS txfrFuncs,
|
||||
void *clientData)
|
||||
{
|
||||
session->transferFunctions = txfrFuncs;
|
||||
session->clientData = clientData;
|
||||
}
|
||||
|
||||
/*
|
||||
* setClientData
|
||||
*
|
||||
* Set the client data associated with the specified
|
||||
* TWAIN session.
|
||||
*/
|
||||
void
|
||||
setClientData(pTW_SESSION session, void *clientData)
|
||||
{
|
||||
session->clientData = clientData;
|
||||
}
|
243
plug-ins/twain/tw_func.h
Normal file
243
plug-ins/twain/tw_func.h
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
* also on 10.2).
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
* - On Mac OS X, canceling doesn't always close things out fully.
|
||||
* - Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
* (07/23/04) v0.6 Added Mac OS X support.
|
||||
*/
|
||||
|
||||
#ifndef _TW_FUNC_H
|
||||
#define _TW_FUNC_H
|
||||
|
||||
#include "tw_platform.h"
|
||||
|
||||
/*
|
||||
* Pre-image transfer function type
|
||||
*
|
||||
* Sent to the caller before any of the
|
||||
* images are transferred to the application.
|
||||
*/
|
||||
typedef void (* TW_PRE_TXFR_CB)(void *);
|
||||
|
||||
/*
|
||||
* Image transfer begin function type
|
||||
*
|
||||
* Sent to the caller when an image transfer
|
||||
* is about to begin. The caller may return
|
||||
* FALSE if the transfer should not continue.
|
||||
* Otherwise, the function should return a
|
||||
* TRUE value.
|
||||
*/
|
||||
typedef int (* TW_TXFR_BEGIN_CB)(pTW_IMAGEINFO, void *);
|
||||
|
||||
/*
|
||||
* Image transfer callback function type
|
||||
*
|
||||
* Expected to return true if the image transfer
|
||||
* should continue. False if the transfer should
|
||||
* be cancelled.
|
||||
*/
|
||||
typedef int (* TW_TXFR_DATA_CB)(pTW_IMAGEINFO, pTW_IMAGEMEMXFER, void *);
|
||||
|
||||
/*
|
||||
* Image transfer end function type
|
||||
*
|
||||
* Sent to the caller when an image transfer
|
||||
* is completed. The caller will be handed
|
||||
* the image transfer completion state. The
|
||||
* following values (defined in twain.h) are
|
||||
* possible:
|
||||
*
|
||||
* TWRC_XFERDONE
|
||||
* The transfer completed successfully
|
||||
* TWRC_CANCEL
|
||||
* The transfer was completed by the user
|
||||
* TWRC_FAILURE
|
||||
* The transfer failed.
|
||||
*/
|
||||
typedef int (* TW_TXFR_END_CB)(int, int, void *);
|
||||
|
||||
/*
|
||||
* Post-image transfer callback
|
||||
*
|
||||
* This callback function is called after all
|
||||
* of the possible images have been transferred
|
||||
* from the datasource.
|
||||
*/
|
||||
typedef void (* TW_POST_TXFR_CB)(int, void *);
|
||||
|
||||
/*
|
||||
* The following structure defines the
|
||||
* three callback functions that are called
|
||||
* while an image is being transferred.
|
||||
* The types of these functions are defined
|
||||
* above. Any function that is NULL will just
|
||||
* not be called.
|
||||
*/
|
||||
typedef struct _TXFR_CB_FUNCS {
|
||||
/* Pre-transfer function */
|
||||
TW_PRE_TXFR_CB preTxfrCb;
|
||||
|
||||
/* Begin function */
|
||||
TW_TXFR_BEGIN_CB txfrBeginCb;
|
||||
|
||||
/* Data transfer */
|
||||
TW_TXFR_DATA_CB txfrDataCb;
|
||||
|
||||
/* End function */
|
||||
TW_TXFR_END_CB txfrEndCb;
|
||||
|
||||
/* Post-transfer function */
|
||||
TW_POST_TXFR_CB postTxfrCb;
|
||||
} TXFR_CB_FUNCS, *pTXFR_CB_FUNCS;
|
||||
|
||||
/*
|
||||
* Data representing a TWAIN
|
||||
* application to data source
|
||||
* session.
|
||||
*/
|
||||
typedef struct _TWAIN_SESSION {
|
||||
/* The window handle related to the TWAIN application on Win32 */
|
||||
TW_HANDLE hwnd;
|
||||
|
||||
/* The current TWAIN return code */
|
||||
TW_UINT16 twRC;
|
||||
|
||||
/* The application's TWAIN identity */
|
||||
pTW_IDENTITY appIdentity;
|
||||
|
||||
/* The datasource's TWAIN identity */
|
||||
pTW_IDENTITY dsIdentity;
|
||||
|
||||
/* The image data transfer functions */
|
||||
pTXFR_CB_FUNCS transferFunctions;
|
||||
|
||||
/* Client data that is associated with the image
|
||||
* transfer callback
|
||||
*/
|
||||
void *clientData;
|
||||
|
||||
/*
|
||||
* The following variable tracks the current state
|
||||
* as related to the TWAIN engine. The states are:
|
||||
*
|
||||
* 1) Pre-session: The DSM has not been loaded
|
||||
* 2) Source Manager Loaded (not opened)
|
||||
* 3) Source Manager Opened
|
||||
* 4) Source Open
|
||||
* 5) Source Enabled
|
||||
* 6) Transfer ready
|
||||
* 7) Transferring
|
||||
*/
|
||||
int twainState;
|
||||
|
||||
} TW_SESSION, *pTW_SESSION;
|
||||
|
||||
/* Session structure access
|
||||
* macros
|
||||
*/
|
||||
/* #define pAPP_IDENTITY(tw_session) (&(tw_session->appIdentity)) */
|
||||
#define APP_IDENTITY(tw_session) (tw_session->appIdentity)
|
||||
/* #define pDS_IDENTITY(tw_session) (&(tw_session->dsIdentity)) */
|
||||
#define DS_IDENTITY(tw_session) (tw_session->dsIdentity)
|
||||
|
||||
/* State macros... Each expects
|
||||
* a Twain Session pointer
|
||||
*/
|
||||
#define TWAIN_LOADED(tw_session) (tw_session->twainState >= 2)
|
||||
#define TWAIN_UNLOADED(tw_session) (tw_session->twainState < 2)
|
||||
#define DSM_IS_OPEN(tw_session) (tw_session->twainState >= 3)
|
||||
#define DSM_IS_CLOSED(tw_session) (tw_session->twainState < 3)
|
||||
#define DS_IS_OPEN(tw_session) (tw_session->twainState >= 4)
|
||||
#define DS_IS_CLOSED(tw_session) (tw_session->twainState < 4)
|
||||
#define DS_IS_ENABLED(tw_session) (tw_session->twainState >= 5)
|
||||
#define DS_IS_DISABLED(tw_session) (tw_session->twainState < 5)
|
||||
|
||||
/* Function declarations */
|
||||
char *twainError(int);
|
||||
char *currentTwainError(pTW_SESSION);
|
||||
int getImage(pTW_SESSION);
|
||||
int loadTwainLibrary(pTW_SESSION);
|
||||
int unloadTwainLibrary(pTW_SESSION twSession);
|
||||
int openDSM(pTW_SESSION);
|
||||
int selectDS(pTW_SESSION);
|
||||
int selectDefaultDS(pTW_SESSION);
|
||||
int openDS(pTW_SESSION);
|
||||
int requestImageAcquire(pTW_SESSION, gboolean);
|
||||
int disableDS(pTW_SESSION);
|
||||
int closeDS(pTW_SESSION);
|
||||
int closeDSM(pTW_SESSION);
|
||||
void cancelPendingTransfers(pTW_SESSION);
|
||||
int scanImage (void);
|
||||
|
||||
TW_FIX32 FloatToFIX32(float);
|
||||
float FIX32ToFloat(TW_FIX32);
|
||||
|
||||
void processTwainMessage(TW_UINT16 message, pTW_SESSION twSession);
|
||||
|
||||
pTW_SESSION newSession(pTW_IDENTITY);
|
||||
void registerWindowHandle(pTW_SESSION, TW_HANDLE);
|
||||
void registerTransferCallbacks(pTW_SESSION, pTXFR_CB_FUNCS, void *);
|
||||
void setClientData(pTW_SESSION session, void *clientData);
|
||||
pTW_SESSION initializeTwain(void);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
void LogLastWinError(void);
|
||||
BOOL InitApplication(HINSTANCE hInstance);
|
||||
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, pTW_SESSION twSession);
|
||||
#endif
|
||||
|
||||
#endif /* _TW_FUNC_H */
|
48
plug-ins/twain/tw_local.h
Normal file
48
plug-ins/twain/tw_local.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TW_LOCAL_H
|
||||
#define _TW_LOCAL_H
|
||||
|
||||
#include "tw_func.h"
|
||||
|
||||
/* Functions which the platform-independent code will call */
|
||||
|
||||
TW_UINT16 callDSM(pTW_IDENTITY, pTW_IDENTITY,
|
||||
TW_UINT32, TW_UINT16,
|
||||
TW_UINT16, TW_MEMREF);
|
||||
|
||||
int twainIsAvailable(void);
|
||||
void twainQuitApplication (void);
|
||||
gboolean twainSetupCallback (pTW_SESSION twSession);
|
||||
|
||||
TW_HANDLE twainAllocHandle(size_t size);
|
||||
TW_MEMREF twainLockHandle (TW_HANDLE handle);
|
||||
void twainUnlockHandle (TW_HANDLE handle);
|
||||
void twainFreeHandle (TW_HANDLE handle);
|
||||
|
||||
int twainMain (void);
|
||||
int scanImage (void);
|
||||
|
||||
#endif
|
35
plug-ins/twain/tw_platform.h
Normal file
35
plug-ins/twain/tw_platform.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TW_PLATFORM_H
|
||||
#define _TW_PLATFORM_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "twain.h"
|
||||
|
||||
/* The DLL to be loaded for TWAIN support */
|
||||
#define TWAIN_DLL_NAME_W L"TWAIN_32.DLL"
|
||||
#define TWAIN_DLL_NAME "TWAIN_32.DLL"
|
||||
#define DEBUG_LOGFILE "c:\\twain.log"
|
||||
#define DUMP_FILE "C:\\TWAINCAP.BIN"
|
||||
#define DUMP_NAME "DTWAIN.EXE"
|
||||
#define READDUMP_NAME "RTWAIN.EXE"
|
||||
|
||||
#endif
|
170
plug-ins/twain/tw_util.c
Normal file
170
plug-ins/twain/tw_util.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
* also on 10.2).
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
* - On Mac OS X, canceling doesn't always close things out fully.
|
||||
* - Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
* (07/23/04) v0.6 Added Mac OS X support.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h> /* Needed when compiling with gcc */
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tw_util.h"
|
||||
#ifdef _DEBUG
|
||||
#include "tw_func.h"
|
||||
FILE *logFile = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
/*
|
||||
* LogMessage
|
||||
*/
|
||||
void
|
||||
LogMessage(char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
time_t time_of_day;
|
||||
char *ctime_string;
|
||||
|
||||
/* Open the log file as necessary */
|
||||
if (!logFile)
|
||||
logFile = g_fopen(DEBUG_LOGFILE, "w");
|
||||
|
||||
time_of_day = time(NULL);
|
||||
ctime_string = ctime(&time_of_day);
|
||||
ctime_string[19] = '\0';
|
||||
|
||||
fprintf(logFile, "[%s] ", (ctime_string + 11));
|
||||
va_start(args, format);
|
||||
vfprintf(logFile, format, args);
|
||||
fflush(logFile);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
logBegin(pTW_IMAGEINFO imageInfo, void *clientData)
|
||||
{
|
||||
int i;
|
||||
char buffer[256];
|
||||
|
||||
LogMessage("\n");
|
||||
LogMessage("*************************************\n");
|
||||
LogMessage("\n");
|
||||
LogMessage("Image transfer begin:\n");
|
||||
/* LogMessage("\tClient data: %s\n", (char *) clientData); */
|
||||
|
||||
/* Log the image information */
|
||||
LogMessage("Image information:\n");
|
||||
LogMessage("\tXResolution: %f\n", FIX32ToFloat(imageInfo->XResolution));
|
||||
LogMessage("\tYResolution: %f\n", FIX32ToFloat(imageInfo->YResolution));
|
||||
LogMessage("\tImageWidth: %d\n", imageInfo->ImageWidth);
|
||||
LogMessage("\tImageLength: %d\n", imageInfo->ImageLength);
|
||||
LogMessage("\tSamplesPerPixel: %d\n", imageInfo->SamplesPerPixel);
|
||||
sprintf(buffer, "\tBitsPerSample: {");
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (imageInfo->BitsPerSample[i])
|
||||
strcat(buffer, "1");
|
||||
else
|
||||
strcat(buffer, "0");
|
||||
|
||||
if (i != 7)
|
||||
strcat(buffer, ",");
|
||||
}
|
||||
LogMessage("%s}\n", buffer);
|
||||
|
||||
LogMessage("\tBitsPerPixel: %d\n", imageInfo->BitsPerPixel);
|
||||
LogMessage("\tPlanar: %s\n", (imageInfo->Planar ? "TRUE" : "FALSE"));
|
||||
LogMessage("\tPixelType: %d\n", imageInfo->PixelType);
|
||||
/* Compression */
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
logData(pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData)
|
||||
{
|
||||
LogMessage("Image transfer callback called:\n");
|
||||
LogMessage("\tClient data: %s\n", (char *) clientData);
|
||||
LogMessage("Memory block transferred:\n");
|
||||
LogMessage("\tBytesPerRow = %d\n", imageMemXfer->BytesPerRow);
|
||||
LogMessage("\tColumns = %d\n", imageMemXfer->Columns);
|
||||
LogMessage("\tRows = %d\n", imageMemXfer->Rows);
|
||||
LogMessage("\tXOffset = %d\n", imageMemXfer->XOffset);
|
||||
LogMessage("\tYOffset = %d\n", imageMemXfer->YOffset);
|
||||
LogMessage("\tBytesWritten = %d\n", imageMemXfer->BytesWritten);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* LogMessage
|
||||
*/
|
||||
void
|
||||
LogMessage(char *format, ...)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
73
plug-ins/twain/tw_util.h
Normal file
73
plug-ins/twain/tw_util.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
* also on 10.2).
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
* - On Mac OS X, canceling doesn't always close things out fully.
|
||||
* - Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
* (07/23/04) v0.6 Added Mac OS X support.
|
||||
*/
|
||||
#ifndef __TW_UTIL_H
|
||||
#define __TW_UTIL_H
|
||||
|
||||
#include "tw_platform.h"
|
||||
|
||||
void LogMessage(char *, ...);
|
||||
|
||||
#ifdef _DEBUG
|
||||
void logBegin(pTW_IMAGEINFO, void *);
|
||||
void logData(pTW_IMAGEINFO, pTW_IMAGEMEMXFER, void *);
|
||||
#endif
|
||||
|
||||
#endif /* __TW_UTIL_H */
|
394
plug-ins/twain/tw_win.c
Normal file
394
plug-ins/twain/tw_win.c
Normal file
@ -0,0 +1,394 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Windows platform-specific code
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libpika/pika.h>
|
||||
|
||||
#include "tw_platform.h"
|
||||
#include "tw_func.h"
|
||||
#include "tw_util.h"
|
||||
#include "tw_local.h"
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
int twainMessageLoop(pTW_SESSION);
|
||||
int TwainProcessMessage(LPMSG lpMsg, pTW_SESSION twSession);
|
||||
|
||||
extern pTW_SESSION initializeTwain ();
|
||||
#ifdef _DEBUG
|
||||
extern void setRunMode(char *argv[]);
|
||||
#endif
|
||||
|
||||
|
||||
#define APP_NAME "TWAIN"
|
||||
#define SHOW_WINDOW 0
|
||||
#define WM_TRANSFER_IMAGE (WM_USER + 100)
|
||||
|
||||
/* main bits */
|
||||
static HWND hwnd = NULL;
|
||||
static HINSTANCE hInst = NULL;
|
||||
|
||||
/* Storage for the DLL handle */
|
||||
static HINSTANCE hDLL = NULL;
|
||||
|
||||
/* Storage for the entry point into the DSM */
|
||||
static DSMENTRYPROC dsmEntryPoint = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* callDSM
|
||||
*
|
||||
* Call the specified function on the data source manager.
|
||||
*/
|
||||
TW_UINT16
|
||||
callDSM(pTW_IDENTITY pOrigin,
|
||||
pTW_IDENTITY pDest,
|
||||
TW_UINT32 DG,
|
||||
TW_UINT16 DAT,
|
||||
TW_UINT16 MSG,
|
||||
TW_MEMREF pData)
|
||||
{
|
||||
/* Call the function */
|
||||
return (*dsmEntryPoint) (pOrigin, pDest, DG, DAT, MSG, pData);
|
||||
}
|
||||
|
||||
/*
|
||||
* twainIsAvailable
|
||||
*
|
||||
* Return boolean indicating whether TWAIN is available
|
||||
*/
|
||||
int
|
||||
twainIsAvailable(void)
|
||||
{
|
||||
/* Already loaded? */
|
||||
if (dsmEntryPoint) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Attempt to load the library */
|
||||
hDLL = LoadLibraryW (TWAIN_DLL_NAME_W);
|
||||
if (hDLL == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Look up the entry point for use */
|
||||
dsmEntryPoint = (DSMENTRYPROC) GetProcAddress(hDLL, "DSM_Entry");
|
||||
if (dsmEntryPoint == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
TW_HANDLE
|
||||
twainAllocHandle (size_t size)
|
||||
{
|
||||
return GlobalAlloc(GHND, size);
|
||||
}
|
||||
|
||||
TW_MEMREF
|
||||
twainLockHandle (TW_HANDLE handle)
|
||||
{
|
||||
return GlobalLock (handle);
|
||||
}
|
||||
|
||||
void
|
||||
twainUnlockHandle (TW_HANDLE handle)
|
||||
{
|
||||
GlobalUnlock (handle);
|
||||
}
|
||||
|
||||
void
|
||||
twainFreeHandle (TW_HANDLE handle)
|
||||
{
|
||||
GlobalFree (handle);
|
||||
}
|
||||
|
||||
gboolean
|
||||
twainSetupCallback (pTW_SESSION twSession)
|
||||
{
|
||||
/* Callbacks go through the window messaging system */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* unloadTwainLibrary
|
||||
*
|
||||
* Unload the TWAIN dynamic link library
|
||||
*/
|
||||
int
|
||||
unloadTwainLibrary(pTW_SESSION twSession)
|
||||
{
|
||||
/* Explicitly free the SM library */
|
||||
if (hDLL) {
|
||||
FreeLibrary(hDLL);
|
||||
hDLL=NULL;
|
||||
}
|
||||
|
||||
/* the data source id will no longer be valid after
|
||||
* twain is killed. If the id is left around the
|
||||
* data source can not be found or opened
|
||||
*/
|
||||
DS_IDENTITY(twSession)->Id = 0;
|
||||
|
||||
/* We are now back at state 1 */
|
||||
twSession->twainState = 1;
|
||||
LogMessage("Source Manager successfully closed\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* TwainProcessMessage
|
||||
*
|
||||
* Returns TRUE if the application should process message as usual.
|
||||
* Returns FALSE if the application should skip processing of this message
|
||||
*/
|
||||
int
|
||||
TwainProcessMessage(LPMSG lpMsg, pTW_SESSION twSession)
|
||||
{
|
||||
TW_EVENT twEvent;
|
||||
|
||||
twSession->twRC = TWRC_NOTDSEVENT;
|
||||
|
||||
/* Only ask Source Manager to process event if there is a Source connected. */
|
||||
if (DSM_IS_OPEN(twSession) && DS_IS_OPEN(twSession)) {
|
||||
/*
|
||||
* A Source provides a modeless dialog box as its user interface.
|
||||
* The following call relays Windows messages down to the Source's
|
||||
* UI that were intended for its dialog box. It also retrieves TWAIN
|
||||
* messages sent from the Source to our Application.
|
||||
*/
|
||||
twEvent.pEvent = (TW_MEMREF) lpMsg;
|
||||
twSession->twRC = callDSM(APP_IDENTITY(twSession), DS_IDENTITY(twSession),
|
||||
DG_CONTROL, DAT_EVENT, MSG_PROCESSEVENT,
|
||||
(TW_MEMREF) &twEvent);
|
||||
|
||||
/* Check the return code */
|
||||
if (twSession->twRC == TWRC_NOTDSEVENT) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Process the message as necessary */
|
||||
processTwainMessage(twEvent.TWMessage, twSession);
|
||||
}
|
||||
|
||||
/* tell the caller what happened */
|
||||
return (twSession->twRC == TWRC_DSEVENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* twainMessageLoop
|
||||
*
|
||||
* Process Win32 window messages and provide special handling
|
||||
* of TWAIN specific messages. This loop will not exit until
|
||||
* the application exits.
|
||||
*/
|
||||
int
|
||||
twainMessageLoop(pTW_SESSION twSession)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||
if (DS_IS_CLOSED(twSession) || !TwainProcessMessage(&msg, twSession)) {
|
||||
TranslateMessage((LPMSG)&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
/*
|
||||
* LogLastWinError
|
||||
*
|
||||
* Log the last Windows error as returned by
|
||||
* GetLastError.
|
||||
*/
|
||||
void
|
||||
LogLastWinError(void)
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
LogMessage("%s\n", lpMsgBuf);
|
||||
|
||||
/* Free the buffer. */
|
||||
LocalFree( lpMsgBuf );
|
||||
}
|
||||
|
||||
void twainQuitApplication (void)
|
||||
{
|
||||
PostQuitMessage (0);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* Win32 setup...
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
* InitApplication
|
||||
*
|
||||
* Initialize window data and register the window class
|
||||
*/
|
||||
BOOL
|
||||
InitApplication(HINSTANCE hInstance)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
BOOL retValue;
|
||||
|
||||
/*
|
||||
* Fill in window class structure with parameters to describe
|
||||
* the main window.
|
||||
*/
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = (WNDPROC) WndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
||||
wc.lpszClassName = APP_NAME;
|
||||
wc.lpszMenuName = NULL;
|
||||
|
||||
/* Register the window class and stash success/failure code. */
|
||||
retValue = RegisterClass(&wc);
|
||||
|
||||
/* Log error */
|
||||
if (!retValue)
|
||||
LogLastWinError();
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* InitInstance
|
||||
*
|
||||
* Create the main window for the application. Used to
|
||||
* interface with the TWAIN datasource.
|
||||
*/
|
||||
BOOL
|
||||
InitInstance(HINSTANCE hInstance, int nCmdShow, pTW_SESSION twSession)
|
||||
{
|
||||
/* Create our window */
|
||||
hwnd = CreateWindow(APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
|
||||
NULL, NULL, hInstance, NULL);
|
||||
|
||||
if (!hwnd) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* Register our window handle with the TWAIN
|
||||
* support.
|
||||
*/
|
||||
registerWindowHandle(twSession, hwnd);
|
||||
|
||||
/* Schedule the image transfer by posting a message */
|
||||
PostMessage(hwnd, WM_TRANSFER_IMAGE, 0, 0);
|
||||
|
||||
ShowWindow(hwnd, nCmdShow);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* twainWinMain
|
||||
*
|
||||
* This is the function that represents the code that
|
||||
* would normally reside in WinMain (see above). This
|
||||
* function will get called during run() in order to set
|
||||
* up the windowing environment necessary for TWAIN to
|
||||
* operate.
|
||||
*/
|
||||
int
|
||||
twainMain (void)
|
||||
{
|
||||
/* Initialize the twain information */
|
||||
pTW_SESSION twSession = initializeTwain();
|
||||
|
||||
/* Since we are not using our own WinMain anymore where we
|
||||
could get hInst we get it here using GetModuleHandleW. */
|
||||
if (!hInst)
|
||||
hInst = GetModuleHandleW(NULL);
|
||||
|
||||
/* Perform instance initialization */
|
||||
if (!InitApplication(hInst))
|
||||
return (FALSE);
|
||||
|
||||
/* Perform application initialization */
|
||||
if (!InitInstance(hInst, SHOW_WINDOW, twSession))
|
||||
return (FALSE);
|
||||
|
||||
/*
|
||||
* Call the main message processing loop...
|
||||
* This call will not return until the application
|
||||
* exits.
|
||||
*/
|
||||
return twainMessageLoop(twSession);
|
||||
}
|
||||
|
||||
/*
|
||||
* WndProc
|
||||
*
|
||||
* Process window message for the main window.
|
||||
*/
|
||||
LRESULT CALLBACK
|
||||
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
|
||||
case WM_TRANSFER_IMAGE:
|
||||
/* Get an image */
|
||||
scanImage ();
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
LogMessage("Exiting application\n");
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (DefWindowProc(hWnd, message, wParam, lParam));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
977
plug-ins/twain/twain.c
Normal file
977
plug-ins/twain/twain.c
Normal file
@ -0,0 +1,977 @@
|
||||
/*
|
||||
* TWAIN Plug-in
|
||||
* Copyright (C) 1999 Craig Setera
|
||||
* Craig Setera <setera@home.com>
|
||||
* 03/31/1999
|
||||
*
|
||||
* Updated for Mac OS X support
|
||||
* Brion Vibber <brion@pobox.com>
|
||||
* 07/22/2004
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Based on (at least) the following plug-ins:
|
||||
* Screenshot
|
||||
* GIF
|
||||
* Randomize
|
||||
*
|
||||
* Any suggestions, bug-reports or patches are welcome.
|
||||
*
|
||||
* This plug-in interfaces to the TWAIN support library in order
|
||||
* to capture images from TWAIN devices directly into PIKA images.
|
||||
* The plug-in is capable of acquiring the following type of
|
||||
* images:
|
||||
* - B/W (1 bit images translated to grayscale B/W)
|
||||
* - Grayscale up to 16 bits per pixel
|
||||
* - RGB up to 16 bits per sample (24, 30, 36, etc.)
|
||||
* - Paletted images (both Gray and RGB)
|
||||
*
|
||||
* Prerequisites:
|
||||
* Should compile and run on both Win32 and Mac OS X 10.3 (possibly
|
||||
* also on 10.2).
|
||||
*
|
||||
* Known problems:
|
||||
* - Multiple image transfers will hang the plug-in. The current
|
||||
* configuration compiles with a maximum of single image transfers.
|
||||
* - On Mac OS X, canceling doesn't always close things out fully.
|
||||
* - Epson TWAIN driver on Mac OS X crashes the plugin when scanning.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Revision history
|
||||
* (02/07/99) v0.1 First working version (internal)
|
||||
* (02/09/99) v0.2 First release to anyone other than myself
|
||||
* (02/15/99) v0.3 Added image dump and read support for debugging
|
||||
* (03/31/99) v0.5 Added support for multi-byte samples and paletted
|
||||
* images.
|
||||
* (07/23/04) v0.6 Added Mac OS X support.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h> /* Needed when compiling with gcc */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tw_platform.h"
|
||||
#include "tw_local.h"
|
||||
|
||||
#include "libpika/pika.h"
|
||||
#include "libpika/stdplugins-intl.h"
|
||||
|
||||
#include "tw_func.h"
|
||||
#include "tw_util.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#include "tw_dump.h"
|
||||
#endif /* _DEBUG */
|
||||
|
||||
/*
|
||||
* Plug-in Definitions
|
||||
*/
|
||||
#define PLUG_IN_NAME "twain-acquire"
|
||||
#define PLUG_IN_DESCRIPTION _("Capture an image from a TWAIN datasource")
|
||||
#define PLUG_IN_HELP N_("This plug-in will capture an image from a TWAIN datasource")
|
||||
#define PLUG_IN_AUTHOR "Craig Setera (setera@home.com)"
|
||||
#define PLUG_IN_COPYRIGHT "Copyright 2004 by Craig Setera"
|
||||
#define PLUG_IN_VERSION "v0.6 (07/22/2004)"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define PLUG_IN_D_NAME "twain-acquire-dump"
|
||||
#define PLUG_IN_R_NAME "twain-acquire-read"
|
||||
#endif /* _DEBUG */
|
||||
|
||||
/*
|
||||
* Application definitions
|
||||
*/
|
||||
#define MAX_IMAGES 1
|
||||
|
||||
/*
|
||||
* Definition of the run states
|
||||
*/
|
||||
#define RUN_STANDARD 0
|
||||
#define RUN_DUMP 1
|
||||
#define RUN_READDUMP 2
|
||||
|
||||
/* Global variables */
|
||||
pTW_SESSION twSession = NULL;
|
||||
|
||||
#ifdef _DEBUG
|
||||
static int twain_run_mode = RUN_STANDARD;
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
void preTransferCallback (void *clientData);
|
||||
int beginTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
void *clientData);
|
||||
int dataTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData);
|
||||
int endTransferCallback (int completionState,
|
||||
int pendingCount,
|
||||
void *clientData);
|
||||
void postTransferCallback (int pendingCount,
|
||||
void *clientData);
|
||||
|
||||
|
||||
typedef struct _Twain Twain;
|
||||
typedef struct _TwainClass TwainClass;
|
||||
|
||||
struct _Twain
|
||||
{
|
||||
PikaPlugIn parent_instance;
|
||||
};
|
||||
|
||||
struct _TwainClass
|
||||
{
|
||||
PikaPlugInClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
#define TWAIN_TYPE (twain_get_type ())
|
||||
#define TWAIN (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TWAIN_TYPE, Twain))
|
||||
|
||||
GType twain_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GList * twain_query_procedures (PikaPlugIn *plug_in);
|
||||
static PikaProcedure * twain_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static PikaValueArray * twain_run (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data);
|
||||
|
||||
G_DEFINE_TYPE (Twain, twain, PIKA_TYPE_PLUG_IN)
|
||||
|
||||
PIKA_MAIN (TWAIN_TYPE)
|
||||
DEFINE_STD_SET_I18N
|
||||
|
||||
|
||||
static void
|
||||
twain_class_init (TwainClass *klass)
|
||||
{
|
||||
PikaPlugInClass *plug_in_class = PIKA_PLUG_IN_CLASS (klass);
|
||||
|
||||
plug_in_class->query_procedures = twain_query_procedures;
|
||||
plug_in_class->create_procedure = twain_create_procedure;
|
||||
plug_in_class->set_i18n = STD_SET_I18N;
|
||||
}
|
||||
|
||||
static void
|
||||
twain_init (Twain *twain)
|
||||
{
|
||||
}
|
||||
|
||||
static GList *
|
||||
twain_query_procedures (PikaPlugIn *plug_in)
|
||||
{
|
||||
return g_list_append (NULL, g_strdup (PLUG_IN_NAME));
|
||||
}
|
||||
|
||||
static PikaProcedure *
|
||||
twain_create_procedure (PikaPlugIn *plug_in,
|
||||
const gchar *name)
|
||||
{
|
||||
PikaProcedure *procedure = NULL;
|
||||
|
||||
if (! strcmp (name, PLUG_IN_NAME))
|
||||
{
|
||||
procedure = pika_image_procedure_new (plug_in, name,
|
||||
PIKA_PDB_PROC_TYPE_PLUGIN,
|
||||
twain_run, NULL, NULL);
|
||||
|
||||
pika_procedure_set_image_types (procedure, "*");
|
||||
pika_procedure_set_sensitivity_mask (procedure,
|
||||
PIKA_PROCEDURE_SENSITIVE_DRAWABLE |
|
||||
PIKA_PROCEDURE_SENSITIVE_DRAWABLES |
|
||||
PIKA_PROCEDURE_SENSITIVE_NO_DRAWABLES |
|
||||
PIKA_PROCEDURE_SENSITIVE_NO_IMAGE);
|
||||
|
||||
pika_procedure_set_menu_label (procedure, _("_Scanner/Camera..."));
|
||||
pika_procedure_add_menu_path (procedure, "<Image>/File/Create");
|
||||
|
||||
pika_procedure_set_documentation (procedure,
|
||||
PLUG_IN_DESCRIPTION,
|
||||
PLUG_IN_HELP,
|
||||
name);
|
||||
pika_procedure_set_attribution (procedure,
|
||||
PLUG_IN_AUTHOR,
|
||||
PLUG_IN_COPYRIGHT,
|
||||
PLUG_IN_VERSION);
|
||||
|
||||
PIKA_PROC_VAL_INT (procedure, "image-count",
|
||||
"Number of acquired images",
|
||||
"Number of acquired images",
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
PIKA_PROC_VAL_OBJECT_ARRAY (procedure, "images",
|
||||
"Array of acquired images",
|
||||
"Array of acquired images",
|
||||
PIKA_TYPE_IMAGE,
|
||||
G_PARAM_READWRITE);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/* Data structure holding data between runs */
|
||||
/* Currently unused... Eventually may be used
|
||||
* to track dialog data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
gchar sourceName[34];
|
||||
gfloat xResolution;
|
||||
gfloat yResolution;
|
||||
gint xOffset;
|
||||
gint yOffset;
|
||||
gint width;
|
||||
gint height;
|
||||
gint imageType;
|
||||
} TwainValues;
|
||||
|
||||
/* Default Twain values */
|
||||
static TwainValues twainvals =
|
||||
{
|
||||
"",
|
||||
100.0, 100.0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
TWPT_RGB
|
||||
};
|
||||
|
||||
/* The standard callback functions */
|
||||
TXFR_CB_FUNCS standardCbFuncs =
|
||||
{
|
||||
preTransferCallback,
|
||||
beginTransferCallback,
|
||||
dataTransferCallback,
|
||||
endTransferCallback,
|
||||
postTransferCallback
|
||||
};
|
||||
|
||||
/******************************************************************
|
||||
* Dump handling
|
||||
******************************************************************/
|
||||
|
||||
#ifdef _DEBUG
|
||||
/* The dumper callback functions */
|
||||
TXFR_CB_FUNCS dumperCbFuncs =
|
||||
{
|
||||
dumpPreTransferCallback,
|
||||
dumpBeginTransferCallback,
|
||||
dumpDataTransferCallback,
|
||||
dumpEndTransferCallback,
|
||||
dumpPostTransferCallback
|
||||
};
|
||||
|
||||
void
|
||||
setRunMode (char *argv[])
|
||||
{
|
||||
char *exeName = strrchr (argv[0], '\\') + 1;
|
||||
|
||||
LogMessage ("Executable name: %s\n", exeName);
|
||||
|
||||
if (!_stricmp (exeName, DUMP_NAME))
|
||||
twain_run_mode = RUN_DUMP;
|
||||
|
||||
if (!_stricmp (exeName, READDUMP_NAME))
|
||||
twain_run_mode = RUN_READDUMP;
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
|
||||
|
||||
int
|
||||
scanImage (void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (twain_run_mode == RUN_READDUMP)
|
||||
{
|
||||
readDumpedImage (twSession);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
#endif /* _DEBUG */
|
||||
return getImage (twSession);
|
||||
}
|
||||
|
||||
/*
|
||||
* initTwainAppIdentity
|
||||
*
|
||||
* Initialize and return our application's identity for
|
||||
* the TWAIN runtime.
|
||||
*/
|
||||
static pTW_IDENTITY
|
||||
getAppIdentity (void)
|
||||
{
|
||||
pTW_IDENTITY appIdentity = g_new (TW_IDENTITY, 1);
|
||||
|
||||
/* Set up the application identity */
|
||||
appIdentity->Id = 0;
|
||||
appIdentity->Version.MajorNum = 0;
|
||||
appIdentity->Version.MinorNum = 1;
|
||||
appIdentity->Version.Language = TWLG_USA;
|
||||
appIdentity->Version.Country = TWCY_USA;
|
||||
strcpy(appIdentity->Version.Info, "PIKA TWAIN 0.6");
|
||||
appIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
|
||||
appIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
|
||||
appIdentity->SupportedGroups = DG_IMAGE;
|
||||
strcpy(appIdentity->Manufacturer, "Craig Setera");
|
||||
strcpy(appIdentity->ProductFamily, "PIKA");
|
||||
strcpy(appIdentity->ProductName, "PIKA");
|
||||
|
||||
return appIdentity;
|
||||
}
|
||||
|
||||
/*
|
||||
* initializeTwain
|
||||
*
|
||||
* Do the necessary TWAIN initialization. This sets up
|
||||
* our TWAIN session information. The session stuff is
|
||||
* something built by me on top of the standard TWAIN
|
||||
* datasource manager calls.
|
||||
*/
|
||||
pTW_SESSION
|
||||
initializeTwain (void)
|
||||
{
|
||||
pTW_IDENTITY appIdentity;
|
||||
|
||||
/* Get our application's identity */
|
||||
appIdentity = getAppIdentity ();
|
||||
|
||||
/* Create a new session object */
|
||||
twSession = newSession (appIdentity);
|
||||
|
||||
/* Register our image transfer callback functions */
|
||||
#ifdef _DEBUG
|
||||
if (twain_run_mode == RUN_DUMP)
|
||||
registerTransferCallbacks (twSession, &dumperCbFuncs, NULL);
|
||||
else
|
||||
#endif /* _DEBUG */
|
||||
registerTransferCallbacks (twSession, &standardCbFuncs, NULL);
|
||||
|
||||
return twSession;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* PIKA Plug-in entry points
|
||||
******************************************************************/
|
||||
|
||||
/* Return values storage */
|
||||
static GList *image_list = NULL;
|
||||
static gint image_count = 0;
|
||||
|
||||
/*
|
||||
* run
|
||||
*
|
||||
* The plug-in is being requested to run.
|
||||
* Capture an image from a TWAIN datasource
|
||||
*/
|
||||
static PikaValueArray *
|
||||
twain_run (PikaProcedure *procedure,
|
||||
PikaRunMode run_mode,
|
||||
PikaImage *image,
|
||||
gint n_drawables,
|
||||
PikaDrawable **drawables,
|
||||
const PikaValueArray *args,
|
||||
gpointer run_data)
|
||||
{
|
||||
/* Initialize the return values
|
||||
* Always return at least the status to the caller.
|
||||
*/
|
||||
PikaPDBStatusType status = PIKA_PDB_SUCCESS;
|
||||
PikaValueArray *return_vals = NULL;
|
||||
PikaImage **images;
|
||||
GList *list;
|
||||
gint num_images;
|
||||
gint i;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
/* Before we get any further, verify that we have
|
||||
* TWAIN and that there is actually a datasource
|
||||
* to be used in doing the acquire.
|
||||
*/
|
||||
if (! twainIsAvailable ())
|
||||
{
|
||||
return pika_procedure_new_return_values (procedure, PIKA_PDB_EXECUTION_ERROR,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* How are we running today? */
|
||||
switch (run_mode)
|
||||
{
|
||||
case PIKA_RUN_INTERACTIVE:
|
||||
/* Retrieve values from the last run...
|
||||
* Currently ignored
|
||||
*/
|
||||
pika_get_data (PLUG_IN_NAME, &twainvals);
|
||||
break;
|
||||
|
||||
case PIKA_RUN_NONINTERACTIVE:
|
||||
/* Currently, we don't do non-interactive calls.
|
||||
* Bail if someone tries to call us non-interactively
|
||||
*/
|
||||
return pika_procedure_new_return_values (procedure, PIKA_PDB_CALLING_ERROR,
|
||||
NULL);
|
||||
|
||||
case PIKA_RUN_WITH_LAST_VALS:
|
||||
/* Retrieve values from the last run...
|
||||
* Currently ignored
|
||||
*/
|
||||
pika_get_data (PLUG_IN_NAME, &twainvals);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Have we succeeded so far? */
|
||||
if (status == PIKA_PDB_SUCCESS)
|
||||
twainMain ();
|
||||
|
||||
/* Check to make sure we got at least one valid
|
||||
* image.
|
||||
*/
|
||||
if (image_count > 0)
|
||||
{
|
||||
/* An image was captured from the TWAIN
|
||||
* datasource. Do final Interactive
|
||||
* steps.
|
||||
*/
|
||||
if (run_mode == PIKA_RUN_INTERACTIVE)
|
||||
{
|
||||
/* Store variable states for next run */
|
||||
pika_set_data (PLUG_IN_NAME, &twainvals, sizeof (TwainValues));
|
||||
}
|
||||
|
||||
num_images = g_list_length (image_list);
|
||||
images = g_new (PikaImage *, num_images);
|
||||
|
||||
for (list = image_list, i = 0;
|
||||
list;
|
||||
list = g_list_next (list), i++)
|
||||
{
|
||||
images[i] = g_object_ref (list->data);
|
||||
}
|
||||
|
||||
g_list_free (image_list);
|
||||
|
||||
/* Set return values */
|
||||
return_vals = pika_procedure_new_return_values (procedure, status,
|
||||
NULL);
|
||||
PIKA_VALUES_SET_INT (return_vals, 1, num_images);
|
||||
PIKA_VALUES_TAKE_OBJECT_ARRAY (return_vals, 2, PIKA_TYPE_IMAGE, images, num_images);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pika_procedure_new_return_values (procedure, PIKA_PDB_EXECUTION_ERROR,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Image transfer callback functions
|
||||
***********************************************************************/
|
||||
|
||||
/* Data used to carry data between each of
|
||||
* the callback function calls.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PikaImage *image;
|
||||
PikaLayer *layer;
|
||||
GeglBuffer *buffer;
|
||||
const Babl *format;
|
||||
pTW_PALETTE8 paletteData;
|
||||
int totalPixels;
|
||||
int completedPixels;
|
||||
} ClientDataStruct, *pClientDataStruct;
|
||||
|
||||
/*
|
||||
* preTransferCallback
|
||||
*
|
||||
* This callback function is called before any images
|
||||
* are transferred. Set up the one time only stuff.
|
||||
*/
|
||||
void
|
||||
preTransferCallback (void *clientData)
|
||||
{
|
||||
/* Initialize our progress dialog */
|
||||
pika_progress_init (_("Transferring data from scanner/camera"));
|
||||
}
|
||||
|
||||
/*
|
||||
* beginTransferCallback
|
||||
*
|
||||
* The following function is called at the beginning
|
||||
* of each image transfer.
|
||||
*/
|
||||
int
|
||||
beginTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
void *clientData)
|
||||
{
|
||||
pClientDataStruct theClientData = g_new (ClientDataStruct, 1);
|
||||
|
||||
const Babl *format;
|
||||
PikaImageBaseType imageType;
|
||||
PikaImageType layerType;
|
||||
PikaPrecision precision;
|
||||
|
||||
gint bpc = imageInfo->BitsPerPixel /
|
||||
imageInfo->SamplesPerPixel;
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
logBegin (imageInfo, clientData);
|
||||
#endif
|
||||
|
||||
/* Decide on the image type */
|
||||
switch (imageInfo->PixelType)
|
||||
{
|
||||
case TWPT_BW:
|
||||
/* Set up the image and layer types */
|
||||
imageType = PIKA_GRAY;
|
||||
layerType = PIKA_GRAY_IMAGE;
|
||||
precision = PIKA_PRECISION_U8_NON_LINEAR;
|
||||
format = babl_format ("Y' u8");
|
||||
break;
|
||||
|
||||
case TWPT_GRAY:
|
||||
/* Set up the image and layer types */
|
||||
imageType = PIKA_GRAY;
|
||||
layerType = PIKA_GRAY_IMAGE;
|
||||
|
||||
switch (bpc)
|
||||
{
|
||||
case 8:
|
||||
precision = PIKA_PRECISION_U8_NON_LINEAR;
|
||||
format = babl_format ("Y' u8");
|
||||
break;
|
||||
|
||||
case 16:
|
||||
precision = PIKA_PRECISION_U16_NON_LINEAR;
|
||||
format = babl_format ("Y' u16");
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TWPT_RGB:
|
||||
/* Set up the image and layer types */
|
||||
imageType = PIKA_RGB;
|
||||
layerType = PIKA_RGB_IMAGE;
|
||||
|
||||
switch (bpc)
|
||||
{
|
||||
case 8:
|
||||
precision = PIKA_PRECISION_U8_NON_LINEAR;
|
||||
format = babl_format ("R'G'B' u8");
|
||||
break;
|
||||
|
||||
case 16:
|
||||
precision = PIKA_PRECISION_U16_NON_LINEAR;
|
||||
format = babl_format ("R'G'B' u16");
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TWPT_PALETTE:
|
||||
/* Get the palette data */
|
||||
theClientData->paletteData = g_new (TW_PALETTE8, 1);
|
||||
twSession->twRC = callDSM (APP_IDENTITY (twSession),
|
||||
DS_IDENTITY (twSession),
|
||||
DG_IMAGE, DAT_PALETTE8, MSG_GET,
|
||||
(TW_MEMREF) theClientData->paletteData);
|
||||
if (twSession->twRC != TWRC_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
switch (theClientData->paletteData->PaletteType)
|
||||
{
|
||||
case TWPA_RGB:
|
||||
/* Set up the image and layer types */
|
||||
imageType = PIKA_RGB;
|
||||
layerType = PIKA_RGB_IMAGE;
|
||||
precision = PIKA_PRECISION_U8_NON_LINEAR;
|
||||
|
||||
format = babl_format ("R'G'B' u8");
|
||||
break;
|
||||
|
||||
case TWPA_GRAY:
|
||||
/* Set up the image and layer types */
|
||||
imageType = PIKA_GRAY;
|
||||
layerType = PIKA_GRAY_IMAGE;
|
||||
precision = PIKA_PRECISION_U8_NON_LINEAR;
|
||||
|
||||
format = babl_format ("Y' u8");
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* We don't know how to deal with anything other than
|
||||
* the types listed above. Bail for any other image
|
||||
* type.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create the PIKA image */
|
||||
theClientData->image = pika_image_new_with_precision (imageInfo->ImageWidth,
|
||||
imageInfo->ImageLength,
|
||||
imageType,
|
||||
precision);
|
||||
|
||||
/* Set the actual resolution */
|
||||
pika_image_set_resolution (theClientData->image,
|
||||
FIX32ToFloat (imageInfo->XResolution),
|
||||
FIX32ToFloat (imageInfo->YResolution));
|
||||
pika_image_set_unit (theClientData->image, PIKA_UNIT_INCH);
|
||||
|
||||
/* Create a layer */
|
||||
theClientData->layer = pika_layer_new (theClientData->image,
|
||||
_("Background"),
|
||||
imageInfo->ImageWidth,
|
||||
imageInfo->ImageLength,
|
||||
layerType, 100,
|
||||
PIKA_LAYER_MODE_NORMAL);
|
||||
|
||||
/* Add the layer to the image */
|
||||
pika_image_insert_layer (theClientData->image,
|
||||
theClientData->layer, NULL, 0);
|
||||
|
||||
/* Update the progress dialog */
|
||||
theClientData->totalPixels = imageInfo->ImageWidth * imageInfo->ImageLength;
|
||||
theClientData->completedPixels = 0;
|
||||
|
||||
pika_progress_update (0.0);
|
||||
|
||||
theClientData->buffer = pika_drawable_get_buffer (PIKA_DRAWABLE (theClientData->layer));
|
||||
theClientData->format = format;
|
||||
|
||||
/* Store our client data for the data transfer callbacks */
|
||||
if (clientData)
|
||||
g_free (clientData);
|
||||
|
||||
setClientData (twSession, (void *) theClientData);
|
||||
|
||||
/* Make sure to return TRUE to continue the image
|
||||
* transfer
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* bitTransferCallback
|
||||
*
|
||||
* The following function is called for each memory
|
||||
* block that is transferred from the data source if
|
||||
* the image type is Black/White.
|
||||
*
|
||||
* Black and white data is unpacked from bit data
|
||||
* into byte data and written into a gray scale PIKA
|
||||
* image.
|
||||
*/
|
||||
static char bitMasks[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||
static int
|
||||
bitTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData)
|
||||
{
|
||||
int row, col, offset;
|
||||
char *srcBuf;
|
||||
char *destBuf;
|
||||
int rows = imageMemXfer->Rows;
|
||||
int cols = imageMemXfer->Columns;
|
||||
pClientDataStruct theClientData = (pClientDataStruct) clientData;
|
||||
|
||||
/* Allocate a buffer as necessary */
|
||||
destBuf = gegl_scratch_new (char, rows * cols);
|
||||
|
||||
/* Unpack the image data from bits into bytes */
|
||||
srcBuf = (char *) imageMemXfer->Memory.TheMem;
|
||||
offset = 0;
|
||||
for (row = 0; row < rows; row++)
|
||||
{
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
char byte = srcBuf[(row * imageMemXfer->BytesPerRow) + (col / 8)];
|
||||
destBuf[offset++] = ((byte & bitMasks[col % 8]) != 0) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the complete chunk */
|
||||
gegl_buffer_set (theClientData->buffer,
|
||||
GEGL_RECTANGLE (imageMemXfer->XOffset, imageMemXfer->YOffset,
|
||||
cols, rows), 0,
|
||||
theClientData->format, destBuf,
|
||||
GEGL_AUTO_ROWSTRIDE);
|
||||
|
||||
/* Free the buffer */
|
||||
gegl_scratch_free (destBuf);
|
||||
|
||||
/* Update the user on our progress */
|
||||
theClientData->completedPixels += (cols * rows);
|
||||
pika_progress_update ((double) theClientData->completedPixels /
|
||||
(double) theClientData->totalPixels);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* directTransferCallback
|
||||
*
|
||||
* The following function is called for each memory
|
||||
* block that is transferred from the data source if
|
||||
* the image type is Grayscale or RGB.
|
||||
*/
|
||||
static int
|
||||
directTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData)
|
||||
{
|
||||
int rows = imageMemXfer->Rows;
|
||||
int cols = imageMemXfer->Columns;
|
||||
pClientDataStruct theClientData = (pClientDataStruct) clientData;
|
||||
|
||||
/* Update the complete chunk */
|
||||
gegl_buffer_set (theClientData->buffer,
|
||||
GEGL_RECTANGLE (imageMemXfer->XOffset, imageMemXfer->YOffset,
|
||||
cols, rows), 0,
|
||||
theClientData->format, imageMemXfer->Memory.TheMem,
|
||||
imageMemXfer->BytesPerRow);
|
||||
|
||||
/* Update the user on our progress */
|
||||
theClientData->completedPixels += (cols * rows);
|
||||
pika_progress_update ((double) theClientData->completedPixels /
|
||||
(double) theClientData->totalPixels);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* palettedTransferCallback
|
||||
*
|
||||
* The following function is called for each memory
|
||||
* block that is transferred from the data source if
|
||||
* the image type is paletted. This does not create
|
||||
* an indexed image type in PIKA because for some
|
||||
* reason it does not allow creation of a specific
|
||||
* palette. This function will create an RGB or Gray
|
||||
* image and use the palette to set the details of
|
||||
* the pixels.
|
||||
*/
|
||||
static int
|
||||
palettedTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData)
|
||||
{
|
||||
int channelsPerEntry;
|
||||
int row, col;
|
||||
int rows = imageMemXfer->Rows;
|
||||
int cols = imageMemXfer->Columns;
|
||||
char *destBuf;
|
||||
char *destPtr = NULL;
|
||||
char *srcPtr = NULL;
|
||||
|
||||
/* Get the client data */
|
||||
pClientDataStruct theClientData = (pClientDataStruct) clientData;
|
||||
|
||||
/* Look up the palette entry size */
|
||||
channelsPerEntry =
|
||||
(theClientData->paletteData->PaletteType == TWPA_RGB) ? 3 : 1;
|
||||
|
||||
/* Allocate a buffer as necessary */
|
||||
destBuf = gegl_scratch_new (char, rows * cols * channelsPerEntry);
|
||||
|
||||
/* Work through the rows */
|
||||
destPtr = destBuf;
|
||||
for (row = 0; row < rows; row++)
|
||||
{
|
||||
srcPtr = (char *) ((char *) imageMemXfer->Memory.TheMem +
|
||||
(row * imageMemXfer->BytesPerRow));
|
||||
|
||||
/* Work through the columns */
|
||||
for (col = 0; col < cols; col++)
|
||||
{
|
||||
/* Get the palette index */
|
||||
int index = (unsigned char) *srcPtr;
|
||||
|
||||
srcPtr++;
|
||||
|
||||
switch (theClientData->paletteData->PaletteType)
|
||||
{
|
||||
case TWPA_GRAY:
|
||||
*destPtr = theClientData->paletteData->Colors[index].Channel1;
|
||||
destPtr++;
|
||||
break;
|
||||
|
||||
case TWPA_RGB:
|
||||
*destPtr = theClientData->paletteData->Colors[index].Channel1;
|
||||
destPtr++;
|
||||
*destPtr = theClientData->paletteData->Colors[index].Channel2;
|
||||
destPtr++;
|
||||
*destPtr = theClientData->paletteData->Colors[index].Channel3;
|
||||
destPtr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the complete chunk */
|
||||
gegl_buffer_set (theClientData->buffer,
|
||||
GEGL_RECTANGLE (imageMemXfer->XOffset, imageMemXfer->YOffset,
|
||||
cols, rows), 0,
|
||||
theClientData->format, destBuf,
|
||||
GEGL_AUTO_ROWSTRIDE);
|
||||
|
||||
/* Free the buffer */
|
||||
gegl_scratch_free (destBuf);
|
||||
|
||||
/* Update the user on our progress */
|
||||
theClientData->completedPixels += (cols * rows);
|
||||
pika_progress_update ((double) theClientData->completedPixels /
|
||||
(double) theClientData->totalPixels);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dataTransferCallback
|
||||
*
|
||||
* The following function is called for each memory
|
||||
* block that is transferred from the data source.
|
||||
*/
|
||||
int
|
||||
dataTransferCallback (pTW_IMAGEINFO imageInfo,
|
||||
pTW_IMAGEMEMXFER imageMemXfer,
|
||||
void *clientData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
logData (imageInfo, imageMemXfer, clientData);
|
||||
#endif
|
||||
|
||||
/* Choose the appropriate transfer handler */
|
||||
switch (imageInfo->PixelType)
|
||||
{
|
||||
case TWPT_PALETTE:
|
||||
return palettedTransferCallback (imageInfo, imageMemXfer, clientData);
|
||||
|
||||
case TWPT_BW:
|
||||
return bitTransferCallback (imageInfo, imageMemXfer, clientData);
|
||||
|
||||
case TWPT_GRAY:
|
||||
case TWPT_RGB:
|
||||
return directTransferCallback (imageInfo, imageMemXfer, clientData);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endTransferCallback
|
||||
*
|
||||
* The following function is called at the end of the
|
||||
* image transfer. The caller will be handed
|
||||
* the image transfer completion state. The
|
||||
* following values (defined in twain.h) are
|
||||
* possible:
|
||||
*
|
||||
* TWRC_XFERDONE
|
||||
* The transfer completed successfully
|
||||
* TWRC_CANCEL
|
||||
* The transfer was completed by the user
|
||||
* TWRC_FAILURE
|
||||
* The transfer failed.
|
||||
*/
|
||||
int
|
||||
endTransferCallback (int completionState,
|
||||
int pendingCount,
|
||||
void *clientData)
|
||||
{
|
||||
pClientDataStruct theClientData = (pClientDataStruct) clientData;
|
||||
|
||||
LogMessage ("endTransferCallback: CompState = %d, pending = %d\n",
|
||||
completionState, pendingCount);
|
||||
|
||||
/* Clean up and detach from the drawable */
|
||||
g_object_unref (theClientData->buffer);
|
||||
|
||||
/* Make sure to check our return code */
|
||||
if (completionState == TWRC_XFERDONE)
|
||||
{
|
||||
/* We have a completed image transfer */
|
||||
image_list = g_list_append (image_list, theClientData->image);
|
||||
image_count++;
|
||||
|
||||
/* Display the image */
|
||||
LogMessage ("Displaying image %d\n",
|
||||
pika_image_get_id (theClientData->image));
|
||||
pika_display_new (theClientData->image);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The transfer did not complete successfully */
|
||||
LogMessage ("Deleting image\n");
|
||||
pika_image_delete (theClientData->image);
|
||||
}
|
||||
|
||||
/* Shut down if we have received all of the possible images */
|
||||
return (image_count < MAX_IMAGES);
|
||||
}
|
||||
|
||||
/*
|
||||
* postTransferCallback
|
||||
*
|
||||
* This callback function will be called
|
||||
* after all possible images have been
|
||||
* transferred.
|
||||
*/
|
||||
void
|
||||
postTransferCallback (int pendingCount,
|
||||
void *clientData)
|
||||
{
|
||||
/* Shut things down. */
|
||||
if (pendingCount != 0)
|
||||
cancelPendingTransfers(twSession);
|
||||
|
||||
/* This will close the datasource and datasource
|
||||
* manager. Then the message queue will be shut
|
||||
* down and the run() procedure will finally be
|
||||
* able to finish.
|
||||
*/
|
||||
disableDS (twSession);
|
||||
closeDS (twSession);
|
||||
closeDSM (twSession);
|
||||
|
||||
/* Post a message to close up the application */
|
||||
twainQuitApplication ();
|
||||
}
|
1819
plug-ins/twain/twain.h
Normal file
1819
plug-ins/twain/twain.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user