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
= convert_twain_res_to_sane( img
->Frame
.Left
);
168 tly
= convert_twain_res_to_sane( img
->Frame
.Top
);
169 brx
= convert_twain_res_to_sane( img
->Frame
.Right
);
170 bry
= convert_twain_res_to_sane( img
->Frame
.Bottom
);
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
;
304 BYTE
*line
, color_buffer
;
311 TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
313 if (activeDS
.currentState
!= 6)
316 activeDS
.twCC
= TWCC_SEQERROR
;
320 /* Transfer an image from the source to the application */
321 if (SANE_CALL( start_device
, NULL
))
323 activeDS
.twCC
= TWCC_OPERATIONERROR
;
327 if (SANE_CALL( get_params
, &activeDS
.frame_params
))
329 WARN("sane_get_parameters failed\n");
330 SANE_CALL( cancel_device
, NULL
);
331 activeDS
.twCC
= TWCC_OPERATIONERROR
;
335 switch (activeDS
.frame_params
.format
)
338 if (activeDS
.frame_params
.depth
== 8 || activeDS
.frame_params
.depth
== 1)
339 color_size
= (1 << activeDS
.frame_params
.depth
) * sizeof(*colors
);
342 FIXME("For NATIVE, we support only 1 bit monochrome and 8 bit Grayscale, not %d\n", activeDS
.frame_params
.depth
);
343 SANE_CALL( cancel_device
, NULL
);
344 activeDS
.twCC
= TWCC_OPERATIONERROR
;
351 FIXME("For NATIVE, we support only GRAY and RGB\n");
352 SANE_CALL( cancel_device
, NULL
);
353 activeDS
.twCC
= TWCC_OPERATIONERROR
;
357 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d bpl=%d) from sane...\n"
358 , activeDS
.frame_params
.pixels_per_line
, activeDS
.frame_params
.lines
,
359 activeDS
.frame_params
.depth
, activeDS
.frame_params
.format
,
360 activeDS
.frame_params
.last_frame
, activeDS
.frame_params
.bytes_per_line
);
362 dib_bytes_per_line
= ((activeDS
.frame_params
.bytes_per_line
+ 3) / 4) * 4;
363 dib_bytes
= activeDS
.frame_params
.lines
* dib_bytes_per_line
;
365 hDIB
= GlobalAlloc(GMEM_ZEROINIT
, dib_bytes
+ sizeof(*header
) + color_size
);
367 header
= GlobalLock(hDIB
);
371 SANE_CALL( cancel_device
, NULL
);
372 activeDS
.twCC
= TWCC_LOWMEMORY
;
378 header
->biSize
= sizeof (*header
);
379 header
->biWidth
= activeDS
.frame_params
.pixels_per_line
;
380 header
->biHeight
= activeDS
.frame_params
.lines
;
381 header
->biPlanes
= 1;
382 header
->biCompression
= BI_RGB
;
383 switch (activeDS
.frame_params
.format
)
386 header
->biBitCount
= activeDS
.frame_params
.depth
* 3;
389 header
->biBitCount
= activeDS
.frame_params
.depth
;
394 header
->biSizeImage
= dib_bytes
;
395 header
->biXPelsPerMeter
= 0;
396 header
->biYPelsPerMeter
= 0;
397 header
->biClrUsed
= 0;
398 header
->biClrImportant
= 0;
400 p
= (BYTE
*)(header
+ 1);
404 colors
= (RGBQUAD
*) p
;
406 if (activeDS
.frame_params
.depth
== 1)
408 /* Sane uses 1 to represent minimum intensity (black) and 0 for maximum (white) */
409 colors
[0].rgbBlue
= colors
[0].rgbRed
= colors
[0].rgbGreen
= 255;
410 colors
[1].rgbBlue
= colors
[1].rgbRed
= colors
[1].rgbGreen
= 0;
413 for (i
= 0; i
< (color_size
/ sizeof(*colors
)); i
++)
414 colors
[i
].rgbBlue
= colors
[i
].rgbRed
= colors
[i
].rgbGreen
= i
;
418 /* Sane returns data in top down order. Acrobat does best with
419 a bottom up DIB being returned. */
420 line
= p
+ (activeDS
.frame_params
.lines
- 1) * dib_bytes_per_line
;
421 for (i
= activeDS
.frame_params
.lines
- 1; i
>= 0; i
--)
424 struct read_data_params params
= { line
, activeDS
.frame_params
.bytes_per_line
, &retlen
};
426 activeDS
.progressWnd
= ScanningDialogBox(activeDS
.progressWnd
,
427 ((activeDS
.frame_params
.lines
- 1 - i
) * 100)
429 (activeDS
.frame_params
.lines
- 1));
431 twRC
= SANE_CALL( read_data
, ¶ms
);
432 if (twRC
!= TWCC_SUCCESS
) break;
433 if (retlen
< activeDS
.frame_params
.bytes_per_line
) break;
434 /* TWAIN: for 24 bit color DIBs, the pixels are stored in BGR order */
435 if (activeDS
.frame_params
.format
== FMT_RGB
&& activeDS
.frame_params
.depth
== 8)
437 pixels
= (RGBTRIPLE
*) line
;
438 for (j
= 0; j
< activeDS
.frame_params
.pixels_per_line
; ++j
)
440 color_buffer
= pixels
[j
].rgbtRed
;
441 pixels
[j
].rgbtRed
= pixels
[j
].rgbtBlue
;
442 pixels
[j
].rgbtBlue
= color_buffer
;
445 line
-= dib_bytes_per_line
;
447 activeDS
.progressWnd
= ScanningDialogBox(activeDS
.progressWnd
, -1);
451 if (twRC
!= TWCC_SUCCESS
)
453 WARN("sane_read: %u, reading line %d\n", twRC
, i
);
454 SANE_CALL( cancel_device
, NULL
);
455 activeDS
.twCC
= TWCC_OPERATIONERROR
;
460 SANE_CALL( cancel_device
, NULL
);
461 *pHandle
= (UINT_PTR
)hDIB
;
462 twRC
= TWRC_XFERDONE
;
463 activeDS
.twCC
= TWCC_SUCCESS
;
464 activeDS
.currentState
= 7;