twain.c: Implment DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET

Aric Stewart aric at codeweavers.com
Tue Feb 21 08:41:07 CST 2006


Subject: [PATCH] Implement the  DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET code 
path. Along with a number of corrections and improvements to allow the 
actual aquiring of images tosucceed.

twain/sane can now aquire images from a scanner using this method.

-------------- next part --------------
Subject: [PATCH] Implement the  DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET code path. Along with a number
of corrections and improvements to allow the actual aquiring of images to
succeed.

twain/sane can now aquire images from a scanner using this method.

---

 dlls/twain/ds_ctrl.c  |   28 ++++++++-
 dlls/twain/ds_image.c |  154 ++++++++++++++++++++++++++++++++++++++++++++++---
 dlls/twain/dsm_ctrl.c |    1 
 dlls/twain/twain_i.h  |    1 
 4 files changed, 169 insertions(+), 15 deletions(-)

applies-to: a51b355800f98646ae91ae9c95b2c82655ab91d9
69f29d2079c231c41af61d679f2ebf2059331f93
diff --git a/dlls/twain/ds_ctrl.c b/dlls/twain/ds_ctrl.c
index bc6841a..ff49c28 100644
--- a/dlls/twain/ds_ctrl.c
+++ b/dlls/twain/ds_ctrl.c
@@ -332,7 +332,7 @@ TW_UINT16 TWAIN_ProcessEvent (pTW_IDENTI
         {
             pEvent->TWMessage = pSource->pendingEvent.TWMessage;
             pSource->pendingEvent.TWMessage = MSG_NULL;
-            twRC = TWRC_DSEVENT;
+            twRC = TWRC_NOTDSEVENT;
         }
         else
         {
@@ -360,7 +360,7 @@ TW_UINT16 TWAIN_PendingXfersEndXfer (pTW
 {
     TW_UINT16 twRC = TWRC_SUCCESS;
     pTW_PENDINGXFERS pPendingXfers = (pTW_PENDINGXFERS) pData;
-    activeDS *pSource = TWAIN_LookupSource (pData);
+    activeDS *pSource = TWAIN_LookupSource (pDest);
 
     TRACE("DG_CONTROL/DAT_PENDINGXFERS/MSG_ENDXFER\n");
 
@@ -542,9 +542,29 @@ TW_UINT16 TWAIN_SetupFileXfer2Set (pTW_I
 TW_UINT16 TWAIN_SetupMemXferGet (pTW_IDENTITY pOrigin, pTW_IDENTITY pDest,
                                   TW_MEMREF pData)
 {
-    FIXME ("stub!\n");
-
+#ifndef HAVE_SANE
     return TWRC_FAILURE;
+#else
+    activeDS *pSource = TWAIN_LookupSource (pDest);
+    pTW_SETUPMEMXFER  pSetupMemXfer = (pTW_SETUPMEMXFER)pData;
+
+    TRACE("DG_CONTROL/DAT_SETUPMEMXFER/MSG_GET\n");
+    if (pSource->sane_param_valid)
+    {
+        pSetupMemXfer->MinBufSize = pSource->sane_param.bytes_per_line;
+        pSetupMemXfer->MaxBufSize = pSource->sane_param.bytes_per_line * 8;
+        pSetupMemXfer->Preferred = pSource->sane_param.bytes_per_line * 2;
+    }
+    else
+    {
+        /* Guessing */
+        pSetupMemXfer->MinBufSize = 2000;
+        pSetupMemXfer->MaxBufSize = 8000;
+        pSetupMemXfer->Preferred = 4000;
+    }
+
+    return TWRC_SUCCESS;
+#endif
 }
 
 /* DG_CONTROL/DAT_STATUS/MSG_GET */
diff --git a/dlls/twain/ds_image.c b/dlls/twain/ds_image.c
index c9fc1b0..07ebad8 100644
--- a/dlls/twain/ds_image.c
+++ b/dlls/twain/ds_image.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2000 Corel Corporation
+ * Copyright 2006 CodeWeavers, Aric Stewart
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -105,6 +106,8 @@ TW_UINT16 TWAIN_ImageInfoGet (pTW_IDENTI
         {
             /* return general image description information about the image about to be transferred */
             status = sane_get_parameters (pSource->deviceHandle, &pSource->sane_param);
+            pSource->sane_param_valid = TRUE;
+            TRACE("Getting parameters\n");
         }
 
         pImageInfo->XResolution.Whole = -1;
@@ -113,20 +116,26 @@ TW_UINT16 TWAIN_ImageInfoGet (pTW_IDENTI
         pImageInfo->YResolution.Frac = 0;
         pImageInfo->ImageWidth = pSource->sane_param.pixels_per_line;
         pImageInfo->ImageLength = pSource->sane_param.lines;
-        if (pSource->sane_param.depth == 24)
+
+        TRACE("Bits per Sample %i\n",pSource->sane_param.depth);
+        TRACE("Frame Format %i\n",pSource->sane_param.format);
+
+        if (pSource->sane_param.format == 1 /*RGB*/ )
         {
-            pImageInfo->SamplesPerPixel = 3;
-            pImageInfo->BitsPerSample[0] = 8;
-            pImageInfo->BitsPerSample[1] = 8;
-            pImageInfo->BitsPerSample[2] = 8;
-            pImageInfo->BitsPerPixel = 24;
+            pImageInfo->BitsPerPixel = pSource->sane_param.depth * 3;
+            pImageInfo->Compression = TWCP_NONE;
             pImageInfo->Planar = TRUE;
+            pImageInfo->SamplesPerPixel = 3;
+            pImageInfo->BitsPerSample[0] = pSource->sane_param.depth;
+            pImageInfo->BitsPerSample[1] = pSource->sane_param.depth;
+            pImageInfo->BitsPerSample[2] = pSource->sane_param.depth;
             pImageInfo->PixelType = TWPT_RGB;
-            pImageInfo->Compression = TWCP_NONE;
         }
-        else if (pSource->sane_param.depth == 8)
+        else
         {
-            /* FIXME: fill the image info structure for 8-bit image */
+            ERR("Unhandled source frame type\n");
+            twRC = TWRC_FAILURE;
+            pSource->twCC = TWCC_SEQERROR;
         }
     }
 
@@ -174,9 +183,131 @@ TW_UINT16 TWAIN_ImageLayoutSet (pTW_IDEN
 TW_UINT16 TWAIN_ImageMemXferGet (pTW_IDENTITY pOrigin, pTW_IDENTITY pDest,
                                  TW_MEMREF pData)
 {
-    FIXME ("stub!\n");
-
+#ifndef HAVE_SANE
     return TWRC_FAILURE;
+#else
+    TW_UINT16 twRC = TWRC_SUCCESS;
+    pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
+    activeDS *pSource = TWAIN_LookupSource (pDest);
+    SANE_Status status = SANE_STATUS_GOOD;
+
+    TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
+
+    if (!pSource)
+    {
+        twRC = TWRC_FAILURE;
+        DSM_twCC = TWCC_NODS;
+    }
+    else if (pSource->currentState < 6 || pSource->currentState > 7)
+    {
+        twRC = TWRC_FAILURE;
+        pSource->twCC = TWCC_SEQERROR;
+    }
+    else
+    {
+        LPBYTE buffer;
+        int buff_len = 0;
+        int consumed_len = 0;
+        LPBYTE ptr;
+        int rows;
+
+        /* Transfer an image from the source to the application */
+        if (pSource->currentState == 6)
+        {
+            status = sane_start (pSource->deviceHandle);
+            if (status != SANE_STATUS_GOOD)
+            {
+                WARN("sane_start: %s\n", sane_strstatus (status));
+                sane_cancel (pSource->deviceHandle);
+                pSource->twCC = TWCC_OPERATIONERROR;
+                return TWRC_FAILURE;
+            }
+
+            status = sane_get_parameters (pSource->deviceHandle,
+                    &pSource->sane_param);
+            pSource->sane_param_valid = TRUE;
+
+            if (status != SANE_STATUS_GOOD)
+            {
+                WARN("sane_get_parameters: %s\n", sane_strstatus (status));
+                sane_cancel (pSource->deviceHandle);
+                pSource->twCC = TWCC_OPERATIONERROR;
+                return TWRC_FAILURE;
+            }
+
+            TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
+              , pSource->sane_param.pixels_per_line, pSource->sane_param.lines,
+              pSource->sane_param.depth, pSource->sane_param.format,
+              pSource->sane_param.last_frame);
+
+            pSource->currentState = 7;
+        }
+
+        /* access memory buffer */
+        if (pImageMemXfer->Memory.Length < pSource->sane_param.bytes_per_line)
+        {
+            sane_cancel (pSource->deviceHandle);
+            pSource->twCC = TWCC_BADVALUE;
+            return TWRC_FAILURE;
+        }
+
+        if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
+        {
+            FIXME("Memory Handle, may not be locked correctly\n");
+            buffer = LocalLock(pImageMemXfer->Memory.TheMem);
+        }
+        else
+            buffer = pImageMemXfer->Memory.TheMem;
+       
+        memset(buffer,0,pImageMemXfer->Memory.Length);
+
+        ptr = buffer;
+        consumed_len = 0;
+        rows = pImageMemXfer->Memory.Length / pSource->sane_param.bytes_per_line;
+
+        /* must fill full lines */
+        while (consumed_len < (pSource->sane_param.bytes_per_line*rows) && 
+                status == SANE_STATUS_GOOD)
+        {
+            status = sane_read (pSource->deviceHandle, ptr, 
+                    (pSource->sane_param.bytes_per_line*rows) - consumed_len ,
+                    &buff_len);
+            consumed_len += buff_len;
+            ptr += buff_len;
+        }
+
+        if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF)
+        {
+            pImageMemXfer->Compression = TWCP_NONE;
+            pImageMemXfer->BytesPerRow = pSource->sane_param.bytes_per_line;
+            pImageMemXfer->Columns = pSource->sane_param.pixels_per_line;
+            pImageMemXfer->Rows = rows;
+            pImageMemXfer->XOffset = 0;
+            pImageMemXfer->YOffset = 0;
+            pImageMemXfer->BytesWritten = consumed_len;
+
+            if (status == SANE_STATUS_EOF)
+            {
+                TRACE("sane_read: %s\n", sane_strstatus (status));
+                sane_cancel (pSource->deviceHandle);
+                twRC = TWRC_XFERDONE;
+            }
+            pSource->twCC = TWRC_SUCCESS;
+        }
+        else if (status != SANE_STATUS_EOF)
+        {
+            WARN("sane_read: %s\n", sane_strstatus (status));
+            sane_cancel (pSource->deviceHandle);
+            pSource->twCC = TWCC_OPERATIONERROR;
+            twRC = TWRC_FAILURE;
+        }
+    }
+
+    if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
+        LocalUnlock(pImageMemXfer->Memory.TheMem);
+    
+    return twRC;
+#endif
 }
 
 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
@@ -222,6 +353,7 @@ TW_UINT16 TWAIN_ImageNativeXferGet (pTW_
         }
 
         status = sane_get_parameters (pSource->deviceHandle, &pSource->sane_param);
+        pSource->sane_param_valid = TRUE;
         if (status != SANE_STATUS_GOOD)
         {
             WARN("sane_get_parameters: %s\n", sane_strstatus (status));
diff --git a/dlls/twain/dsm_ctrl.c b/dlls/twain/dsm_ctrl.c
index 6ebff41..002a3bf 100644
--- a/dlls/twain/dsm_ctrl.c
+++ b/dlls/twain/dsm_ctrl.c
@@ -178,6 +178,7 @@ TW_UINT16 TWAIN_IdentityGetFirst (pTW_ID
 
     TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
 
+    device_list = NULL;
     status = sane_get_devices (&device_list, SANE_FALSE);
     if (status == SANE_STATUS_GOOD)
     {
diff --git a/dlls/twain/twain_i.h b/dlls/twain/twain_i.h
index bc8f664..6d98763 100644
--- a/dlls/twain/twain_i.h
+++ b/dlls/twain/twain_i.h
@@ -46,6 +46,7 @@ typedef struct tagActiveDS
     SANE_Handle		deviceHandle;		/* device handle */
     SANE_Parameters     sane_param;             /* parameters about the image
                                                    transferred */
+    BOOL                sane_param_valid;  /* true if valid sane_param*/
 #endif
     /* Capabiblities */
     TW_UINT16		capXferMech;		/* ICAP_XFERMECH */
---
0.99.9i


More information about the wine-patches mailing list