From: Bernd Herd codeberg@herdsoft.com
Twain ICAP_BITDEPTH is defined in bits per pixel, whereas in sane depth is defined per color channel. Fix it.
Also allows setting ICAP_BITDEPTH for those sane backends that allow it --- dlls/sane.ds/capability.c | 78 ++++++++++++++++++++++++++++++++++----- dlls/sane.ds/options.c | 2 +- dlls/sane.ds/sane_i.h | 1 + 3 files changed, 71 insertions(+), 10 deletions(-)
diff --git a/dlls/sane.ds/capability.c b/dlls/sane.ds/capability.c index 33b586b0824..52633931007 100644 --- a/dlls/sane.ds/capability.c +++ b/dlls/sane.ds/capability.c @@ -85,10 +85,10 @@ static TW_UINT16 msg_get_enum(pTW_CAPABILITY pCapability, const TW_UINT32 *value pCapability->hContainer = 0;
if (type == TWTY_INT16 || type == TWTY_UINT16) - pCapability->hContainer = GlobalAlloc (0, FIELD_OFFSET( TW_ENUMERATION, ItemList[value_count * sizeof(TW_UINT16)])); + pCapability->hContainer = GlobalAlloc (GMEM_ZEROINIT, FIELD_OFFSET( TW_ENUMERATION, ItemList[value_count * sizeof(TW_UINT16)]));
if (type == TWTY_INT32 || type == TWTY_UINT32) - pCapability->hContainer = GlobalAlloc (0, FIELD_OFFSET( TW_ENUMERATION, ItemList[value_count * sizeof(TW_UINT32)])); + pCapability->hContainer = GlobalAlloc (GMEM_ZEROINIT, FIELD_OFFSET( TW_ENUMERATION, ItemList[value_count * sizeof(TW_UINT32)]));
if (pCapability->hContainer) enumv = GlobalLock(pCapability->hContainer); @@ -476,30 +476,90 @@ static TW_UINT16 SANE_ICAPUnits (pTW_CAPABILITY pCapability, TW_UINT16 action) static TW_UINT16 SANE_ICAPBitDepth(pTW_CAPABILITY pCapability, TW_UINT16 action) { TW_UINT16 twCC = TWCC_BADCAP; - TW_UINT32 possible_values[1]; + TW_UINT32 val; + TW_UINT32 sane_depth, twain_depth; + BOOL have_option_depth; + int samples_per_pixel; + struct option_descriptor opt;
TRACE("ICAP_BITDEPTH\n");
- possible_values[0] = activeDS.frame_params.depth; + get_sane_params(&activeDS.frame_params); // Updates activeDS.frame_params.format + samples_per_pixel=(activeDS.frame_params.format == FMT_RGB) ? 3 : 1; + + sane_depth=activeDS.frame_params.depth; + have_option_depth = + sane_find_option( "depth", TYPE_INT, &opt ) == TWCC_SUCCESS + && (opt.size==sizeof(TW_UINT32)); + if (have_option_depth) + { + twCC = sane_option_get_value(opt.optno, &sane_depth); + } + twain_depth = sane_depth*samples_per_pixel;
switch (action) { case MSG_QUERYSUPPORT: twCC = set_onevalue(pCapability, TWTY_INT32, - TWQC_GET | TWQC_GETDEFAULT | TWQC_GETCURRENT ); + TWQC_GET | TWQC_GETDEFAULT | TWQC_GETCURRENT | (have_option_depth ? TWQC_SET : 0) ); break;
case MSG_GET: - twCC = msg_get_enum(pCapability, possible_values, ARRAY_SIZE(possible_values), - TWTY_UINT16, activeDS.frame_params.depth, activeDS.frame_params.depth); + if (have_option_depth && + opt.constraint_type == CONSTRAINT_WORD_LIST && + opt.constraint.word_list[0]<=32) + { + /* The constraint word ist is in bits per color channel, for TWAIN we need bits per pixel */ + TW_UINT32 enum_bitdepths[32]; + int i; + for (i=0; i<opt.constraint.word_list[0]; i++) + enum_bitdepths[i] = opt.constraint.word_list[i+1] * samples_per_pixel; + twCC = msg_get_enum(pCapability, enum_bitdepths, opt.constraint.word_list[0], + TWTY_UINT16, twain_depth, twain_depth); + } + else + { + twCC = msg_get_enum(pCapability, &twain_depth, 1, + TWTY_UINT16, twain_depth, twain_depth); + } + break; + + case MSG_SET: + if (have_option_depth) + { + twCC = msg_set(pCapability, &val); + if (twCC == TWCC_SUCCESS) + { + BOOL reload = FALSE; + TW_UINT16 val16 = (TW_UINT16) val; + + /* TWAIN Spec 2.4 says unambiguous that the depth is defined per pixel, + * not per color channel. However it also warns that there have been + * misunderstandings. So interpret it... */ + if (val16==8 && samples_per_pixel==3) + { + val16=24; + } else if (val16==16 && samples_per_pixel==3) + { + val16=48; + } + sane_depth = val16/samples_per_pixel; + twCC = sane_option_set_value(opt.optno, &sane_depth, &reload); + if (reload) twCC = TWCC_CHECKSTATUS; + } + } + else + { + twCC = TWCC_BADCAP; + } break;
case MSG_GETDEFAULT: /* .. Fall through intentional .. */
case MSG_GETCURRENT: - TRACE("Returning current bitdepth of %d\n", activeDS.frame_params.depth); - twCC = set_onevalue(pCapability, TWTY_UINT16, activeDS.frame_params.depth); + TRACE("Returning current bitdepth of %ld\n", twain_depth); + twCC = set_onevalue(pCapability, TWTY_UINT16, twain_depth); break; } return twCC; diff --git a/dlls/sane.ds/options.c b/dlls/sane.ds/options.c index 335e0306f38..f46ba0f8fc7 100644 --- a/dlls/sane.ds/options.c +++ b/dlls/sane.ds/options.c @@ -40,7 +40,7 @@ TW_UINT16 sane_option_set_value( int optno, void *val, BOOL *reload ) return SANE_CALL( option_set_value, ¶ms ); }
-static TW_UINT16 sane_find_option( const char *name, int type, struct option_descriptor *descr ) +TW_UINT16 sane_find_option( const char *name, int type, struct option_descriptor *descr ) { struct option_find_descriptor_params params = { name, type, descr }; return SANE_CALL( option_find_descriptor, ¶ms ) ? TWCC_CAPUNSUPPORTED : TWCC_SUCCESS; diff --git a/dlls/sane.ds/sane_i.h b/dlls/sane.ds/sane_i.h index 0691f02e22d..4ce7f42e1b1 100644 --- a/dlls/sane.ds/sane_i.h +++ b/dlls/sane.ds/sane_i.h @@ -207,6 +207,7 @@ BOOL DoScannerUI(void); HWND ScanningDialogBox(HWND dialog, LONG progress);
/* Option functions */ +TW_UINT16 sane_find_option( const char *name, int type, struct option_descriptor *descr ); TW_UINT16 sane_option_get_value( int optno, void *val ); TW_UINT16 sane_option_set_value( int optno, void *val, BOOL *reload ); TW_UINT16 sane_option_get_int( const char *option_name, int *val );