2 * Copyright 2000 Corel Corporation
3 * Copyright 2006 CodeWeavers, Aric Stewart
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
29 /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
30 TW_UINT16
SANE_ImageInfoGet (pTW_IDENTITY pOrigin
,
33 TW_UINT16 twRC
= TWRC_SUCCESS
;
34 pTW_IMAGEINFO pImageInfo
= (pTW_IMAGEINFO
) pData
;
37 TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
39 if (activeDS
.currentState
!= 6 && activeDS
.currentState
!= 7)
42 activeDS
.twCC
= TWCC_SEQERROR
;
46 if (activeDS
.currentState
== 6)
48 /* return general image description information about the image about to be transferred */
49 TRACE("Getting parameters\n");
50 if (SANE_CALL( get_params
, &activeDS
.frame_params
))
52 WARN("sane_get_parameters failed\n");
53 SANE_CALL( cancel_device
, NULL
);
54 activeDS
.twCC
= TWCC_OPERATIONERROR
;
59 if (sane_option_get_int("resolution", &resolution
) == TWCC_SUCCESS
)
60 pImageInfo
->XResolution
.Whole
= pImageInfo
->YResolution
.Whole
= resolution
;
62 pImageInfo
->XResolution
.Whole
= pImageInfo
->YResolution
.Whole
= -1;
63 pImageInfo
->XResolution
.Frac
= 0;
64 pImageInfo
->YResolution
.Frac
= 0;
65 pImageInfo
->ImageWidth
= activeDS
.frame_params
.pixels_per_line
;
66 pImageInfo
->ImageLength
= activeDS
.frame_params
.lines
;
68 TRACE("Bits per Sample %i\n",activeDS
.frame_params
.depth
);
69 TRACE("Frame Format %i\n",activeDS
.frame_params
.format
);
71 switch (activeDS
.frame_params
.format
)
74 pImageInfo
->BitsPerPixel
= activeDS
.frame_params
.depth
* 3;
75 pImageInfo
->Compression
= TWCP_NONE
;
76 pImageInfo
->Planar
= TRUE
;
77 pImageInfo
->SamplesPerPixel
= 3;
78 pImageInfo
->BitsPerSample
[0] = activeDS
.frame_params
.depth
;
79 pImageInfo
->BitsPerSample
[1] = activeDS
.frame_params
.depth
;
80 pImageInfo
->BitsPerSample
[2] = activeDS
.frame_params
.depth
;
81 pImageInfo
->PixelType
= TWPT_RGB
;
84 pImageInfo
->BitsPerPixel
= activeDS
.frame_params
.depth
;
85 pImageInfo
->Compression
= TWCP_NONE
;
86 pImageInfo
->Planar
= TRUE
;
87 pImageInfo
->SamplesPerPixel
= 1;
88 pImageInfo
->BitsPerSample
[0] = activeDS
.frame_params
.depth
;
89 if (activeDS
.frame_params
.depth
== 1)
90 pImageInfo
->PixelType
= TWPT_BW
;
92 pImageInfo
->PixelType
= TWPT_GRAY
;
96 activeDS
.twCC
= TWCC_SEQERROR
;
104 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
105 TW_UINT16
SANE_ImageLayoutGet (pTW_IDENTITY pOrigin
,
108 TW_IMAGELAYOUT
*img
= (TW_IMAGELAYOUT
*) pData
;
109 int tlx
, tly
, brx
, bry
;
112 TRACE("DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET\n");
114 rc
= sane_option_get_scan_area( &tlx
, &tly
, &brx
, &bry
);
115 if (rc
!= TWCC_SUCCESS
)
121 img
->Frame
.Left
= convert_sane_res_to_twain( tlx
);
122 img
->Frame
.Top
= convert_sane_res_to_twain( tly
);
123 img
->Frame
.Right
= convert_sane_res_to_twain( brx
);
124 img
->Frame
.Bottom
= convert_sane_res_to_twain( bry
);
125 img
->DocumentNumber
= 1;
127 img
->FrameNumber
= 1;
129 activeDS
.twCC
= TWCC_SUCCESS
;
133 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
134 TW_UINT16
SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin
,
142 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
143 TW_UINT16
SANE_ImageLayoutReset (pTW_IDENTITY pOrigin
,
151 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
152 TW_UINT16
SANE_ImageLayoutSet (pTW_IDENTITY pOrigin
,
155 TW_IMAGELAYOUT
*img
= (TW_IMAGELAYOUT
*) pData
;
156 BOOL changed
= FALSE
;
158 int tlx
, tly
, brx
, bry
;
160 TRACE("DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET\n");
161 TRACE("Frame: [Left %x.%x|Top %x.%x|Right %x.%x|Bottom %x.%x]\n",
162 img
->Frame
.Left
.Whole
, img
->Frame
.Left
.Frac
,
163 img
->Frame
.Top
.Whole
, img
->Frame
.Top
.Frac
,
164 img
->Frame
.Right
.Whole
, img
->Frame
.Right
.Frac
,
165 img
->Frame
.Bottom
.Whole
, img
->Frame
.Bottom
.Frac
);
167 tlx
= img
->Frame
.Left
.Whole
* 65536 + img
->Frame
.Left
.Frac
;
168 tly
= img
->Frame
.Top
.Whole
* 65536 + img
->Frame
.Top
.Frac
;
169 brx
= img
->Frame
.Right
.Whole
* 65536 + img
->Frame
.Right
.Frac
;
170 bry
= img
->Frame
.Bottom
.Whole
* 65536 + img
->Frame
.Bottom
.Frac
;
172 twrc
= sane_option_set_scan_area( tlx
, tly
, brx
, bry
, &changed
);
173 if (twrc
!= TWRC_SUCCESS
)
176 activeDS
.twCC
= TWCC_SUCCESS
;
177 return changed
? TWRC_CHECKSTATUS
: TWRC_SUCCESS
;
180 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
181 TW_UINT16
SANE_ImageMemXferGet (pTW_IDENTITY pOrigin
,
184 TW_UINT16 twRC
= TWRC_SUCCESS
;
185 pTW_IMAGEMEMXFER pImageMemXfer
= (pTW_IMAGEMEMXFER
) pData
;
187 TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
189 if (activeDS
.currentState
< 6 || activeDS
.currentState
> 7)
192 activeDS
.twCC
= TWCC_SEQERROR
;
196 struct read_data_params params
;
201 /* Transfer an image from the source to the application */
202 if (activeDS
.currentState
== 6)
205 /* trigger scanning dialog */
206 activeDS
.progressWnd
= ScanningDialogBox(NULL
,0);
208 ScanningDialogBox(activeDS
.progressWnd
,0);
210 if (SANE_CALL( start_device
, NULL
))
212 activeDS
.twCC
= TWCC_OPERATIONERROR
;
216 if (get_sane_params( &activeDS
.frame_params
))
218 WARN("sane_get_parameters failed\n");
219 SANE_CALL( cancel_device
, NULL
);
220 activeDS
.twCC
= TWCC_OPERATIONERROR
;
224 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
225 , activeDS
.frame_params
.pixels_per_line
, activeDS
.frame_params
.lines
,
226 activeDS
.frame_params
.depth
, activeDS
.frame_params
.format
,
227 activeDS
.frame_params
.last_frame
);
229 activeDS
.currentState
= 7;
232 /* access memory buffer */
233 if (pImageMemXfer
->Memory
.Length
< activeDS
.frame_params
.bytes_per_line
)
235 SANE_CALL( cancel_device
, NULL
);
236 activeDS
.twCC
= TWCC_BADVALUE
;
240 if (pImageMemXfer
->Memory
.Flags
& TWMF_HANDLE
)
242 FIXME("Memory Handle, may not be locked correctly\n");
243 buffer
= LocalLock(pImageMemXfer
->Memory
.TheMem
);
246 buffer
= pImageMemXfer
->Memory
.TheMem
;
248 memset(buffer
,0,pImageMemXfer
->Memory
.Length
);
250 /* must fill full lines */
251 rows
= pImageMemXfer
->Memory
.Length
/ activeDS
.frame_params
.bytes_per_line
;
252 params
.buffer
= buffer
;
253 params
.len
= activeDS
.frame_params
.bytes_per_line
* rows
;
254 params
.retlen
= &retlen
;
256 twRC
= SANE_CALL( read_data
, ¶ms
);
257 if (twRC
== TWCC_SUCCESS
)
259 pImageMemXfer
->Compression
= TWCP_NONE
;
260 pImageMemXfer
->BytesPerRow
= activeDS
.frame_params
.bytes_per_line
;
261 pImageMemXfer
->Columns
= activeDS
.frame_params
.pixels_per_line
;
262 pImageMemXfer
->Rows
= rows
;
263 pImageMemXfer
->XOffset
= 0;
264 pImageMemXfer
->YOffset
= 0;
265 pImageMemXfer
->BytesWritten
= retlen
;
267 ScanningDialogBox(activeDS
.progressWnd
, retlen
);
269 if (retlen
< activeDS
.frame_params
.bytes_per_line
* rows
)
271 ScanningDialogBox(activeDS
.progressWnd
, -1);
272 TRACE("sane_read: %u / %u\n", retlen
, activeDS
.frame_params
.bytes_per_line
* rows
);
273 SANE_CALL( cancel_device
, NULL
);
274 twRC
= TWRC_XFERDONE
;
276 activeDS
.twCC
= TWRC_SUCCESS
;
280 ScanningDialogBox(activeDS
.progressWnd
, -1);
281 WARN("sane_read: %u\n", twRC
);
282 SANE_CALL( cancel_device
, NULL
);
283 activeDS
.twCC
= TWCC_OPERATIONERROR
;
288 if (pImageMemXfer
->Memory
.Flags
& TWMF_HANDLE
)
289 LocalUnlock(pImageMemXfer
->Memory
.TheMem
);
294 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
295 TW_UINT16
SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin
,
298 TW_UINT16 twRC
= TWRC_SUCCESS
;
299 pTW_UINT32 pHandle
= (pTW_UINT32
) pData
;
301 BITMAPINFOHEADER
*header
= NULL
;
303 int dib_bytes_per_line
;
310 TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
312 if (activeDS
.currentState
!= 6)
315 activeDS
.twCC
= TWCC_SEQERROR
;
319 /* Transfer an image from the source to the application */
320 if (SANE_CALL( start_device
, NULL
))
322 activeDS
.twCC
= TWCC_OPERATIONERROR
;
326 if (SANE_CALL( get_params
, &activeDS
.frame_params
))
328 WARN("sane_get_parameters failed\n");
329 SANE_CALL( cancel_device
, NULL
);
330 activeDS
.twCC
= TWCC_OPERATIONERROR
;
334 switch (activeDS
.frame_params
.format
)
337 if (activeDS
.frame_params
.depth
== 8)
338 color_size
= (1 << 8) * sizeof(*colors
);
339 else if (activeDS
.frame_params
.depth
== 1)
343 FIXME("For NATIVE, we support only 1 bit monochrome and 8 bit Grayscale, not %d\n", activeDS
.frame_params
.depth
);
344 SANE_CALL( cancel_device
, NULL
);
345 activeDS
.twCC
= TWCC_OPERATIONERROR
;
352 FIXME("For NATIVE, we support only GRAY and RGB\n");
353 SANE_CALL( cancel_device
, NULL
);
354 activeDS
.twCC
= TWCC_OPERATIONERROR
;
358 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d bpl=%d) from sane...\n"
359 , activeDS
.frame_params
.pixels_per_line
, activeDS
.frame_params
.lines
,
360 activeDS
.frame_params
.depth
, activeDS
.frame_params
.format
,
361 activeDS
.frame_params
.last_frame
, activeDS
.frame_params
.bytes_per_line
);
363 dib_bytes_per_line
= ((activeDS
.frame_params
.bytes_per_line
+ 3) / 4) * 4;
364 dib_bytes
= activeDS
.frame_params
.lines
* dib_bytes_per_line
;
366 hDIB
= GlobalAlloc(GMEM_ZEROINIT
, dib_bytes
+ sizeof(*header
) + color_size
);
368 header
= GlobalLock(hDIB
);
372 SANE_CALL( cancel_device
, NULL
);
373 activeDS
.twCC
= TWCC_LOWMEMORY
;
379 header
->biSize
= sizeof (*header
);
380 header
->biWidth
= activeDS
.frame_params
.pixels_per_line
;
381 header
->biHeight
= activeDS
.frame_params
.lines
;
382 header
->biPlanes
= 1;
383 header
->biCompression
= BI_RGB
;
384 switch (activeDS
.frame_params
.format
)
387 header
->biBitCount
= activeDS
.frame_params
.depth
* 3;
390 header
->biBitCount
= activeDS
.frame_params
.depth
;
395 header
->biSizeImage
= dib_bytes
;
396 header
->biXPelsPerMeter
= 0;
397 header
->biYPelsPerMeter
= 0;
398 header
->biClrUsed
= 0;
399 header
->biClrImportant
= 0;
401 p
= (BYTE
*)(header
+ 1);
405 colors
= (RGBQUAD
*) p
;
407 for (i
= 0; i
< (color_size
/ sizeof(*colors
)); i
++)
408 colors
[i
].rgbBlue
= colors
[i
].rgbRed
= colors
[i
].rgbGreen
= i
;
412 /* Sane returns data in top down order. Acrobat does best with
413 a bottom up DIB being returned. */
414 line
= p
+ (activeDS
.frame_params
.lines
- 1) * dib_bytes_per_line
;
415 for (i
= activeDS
.frame_params
.lines
- 1; i
>= 0; i
--)
418 struct read_data_params params
= { line
, activeDS
.frame_params
.bytes_per_line
, &retlen
};
420 activeDS
.progressWnd
= ScanningDialogBox(activeDS
.progressWnd
,
421 ((activeDS
.frame_params
.lines
- 1 - i
) * 100)
423 (activeDS
.frame_params
.lines
- 1));
425 twRC
= SANE_CALL( read_data
, ¶ms
);
426 if (twRC
!= TWCC_SUCCESS
) break;
427 if (retlen
< activeDS
.frame_params
.bytes_per_line
) break;
428 line
-= dib_bytes_per_line
;
430 activeDS
.progressWnd
= ScanningDialogBox(activeDS
.progressWnd
, -1);
434 if (twRC
!= TWCC_SUCCESS
)
436 WARN("sane_read: %u, reading line %d\n", twRC
, i
);
437 SANE_CALL( cancel_device
, NULL
);
438 activeDS
.twCC
= TWCC_OPERATIONERROR
;
443 SANE_CALL( cancel_device
, NULL
);
444 *pHandle
= (UINT_PTR
)hDIB
;
445 twRC
= TWRC_XFERDONE
;
446 activeDS
.twCC
= TWCC_SUCCESS
;
447 activeDS
.currentState
= 7;