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
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(twain);
34 /* DG_IMAGE/DAT_CIECOLOR/MSG_GET */
35 TW_UINT16 SANE_CIEColorGet (pTW_IDENTITY pOrigin,
43 /* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */
44 TW_UINT16 SANE_ExtImageInfoGet (pTW_IDENTITY pOrigin,
52 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */
53 TW_UINT16 SANE_GrayResponseReset (pTW_IDENTITY pOrigin,
61 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */
62 TW_UINT16 SANE_GrayResponseSet (pTW_IDENTITY pOrigin,
70 /* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */
71 TW_UINT16 SANE_ImageFileXferGet (pTW_IDENTITY pOrigin,
79 /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
80 TW_UINT16 SANE_ImageInfoGet (pTW_IDENTITY pOrigin,
83 #ifndef SONAME_LIBSANE
86 TW_UINT16 twRC = TWRC_SUCCESS;
87 pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData;
90 TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
92 if (activeDS.currentState != 6 && activeDS.currentState != 7)
95 activeDS.twCC = TWCC_SEQERROR;
99 if (activeDS.currentState == 6)
101 /* return general image description information about the image about to be transferred */
102 status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
103 TRACE("Getting parameters\n");
104 if (status != SANE_STATUS_GOOD)
106 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
107 psane_cancel (activeDS.deviceHandle);
108 activeDS.twCC = TWCC_OPERATIONERROR;
111 activeDS.sane_param_valid = TRUE;
114 pImageInfo->XResolution.Whole = -1;
115 pImageInfo->XResolution.Frac = 0;
116 pImageInfo->YResolution.Whole = -1;
117 pImageInfo->YResolution.Frac = 0;
118 pImageInfo->ImageWidth = activeDS.sane_param.pixels_per_line;
119 pImageInfo->ImageLength = activeDS.sane_param.lines;
121 TRACE("Bits per Sample %i\n",activeDS.sane_param.depth);
122 TRACE("Frame Format %i\n",activeDS.sane_param.format);
124 if (activeDS.sane_param.format == SANE_FRAME_RGB )
126 pImageInfo->BitsPerPixel = activeDS.sane_param.depth * 3;
127 pImageInfo->Compression = TWCP_NONE;
128 pImageInfo->Planar = TRUE;
129 pImageInfo->SamplesPerPixel = 3;
130 pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth;
131 pImageInfo->BitsPerSample[1] = activeDS.sane_param.depth;
132 pImageInfo->BitsPerSample[2] = activeDS.sane_param.depth;
133 pImageInfo->PixelType = TWPT_RGB;
135 else if (activeDS.sane_param.format == SANE_FRAME_GRAY)
137 pImageInfo->BitsPerPixel = activeDS.sane_param.depth;
138 pImageInfo->Compression = TWCP_NONE;
139 pImageInfo->Planar = TRUE;
140 pImageInfo->SamplesPerPixel = 1;
141 pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth;
142 pImageInfo->PixelType = TWPT_GRAY;
146 ERR("Unhandled source frame type %i\n",activeDS.sane_param.format);
148 activeDS.twCC = TWCC_SEQERROR;
156 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
157 TW_UINT16 SANE_ImageLayoutGet (pTW_IDENTITY pOrigin,
165 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
166 TW_UINT16 SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin,
174 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
175 TW_UINT16 SANE_ImageLayoutReset (pTW_IDENTITY pOrigin,
183 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
184 TW_UINT16 SANE_ImageLayoutSet (pTW_IDENTITY pOrigin,
192 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
193 TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin,
196 #ifndef SONAME_LIBSANE
199 TW_UINT16 twRC = TWRC_SUCCESS;
200 pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
201 SANE_Status status = SANE_STATUS_GOOD;
203 TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
205 if (activeDS.currentState < 6 || activeDS.currentState > 7)
208 activeDS.twCC = TWCC_SEQERROR;
214 int consumed_len = 0;
218 /* Transfer an image from the source to the application */
219 if (activeDS.currentState == 6)
222 /* trigger scanning dialog */
223 activeDS.progressWnd = ScanningDialogBox(NULL,0);
225 ScanningDialogBox(activeDS.progressWnd,0);
227 status = psane_start (activeDS.deviceHandle);
228 if (status != SANE_STATUS_GOOD)
230 WARN("psane_start: %s\n", psane_strstatus (status));
231 psane_cancel (activeDS.deviceHandle);
232 activeDS.twCC = TWCC_OPERATIONERROR;
236 status = psane_get_parameters (activeDS.deviceHandle,
237 &activeDS.sane_param);
238 activeDS.sane_param_valid = TRUE;
240 if (status != SANE_STATUS_GOOD)
242 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
243 psane_cancel (activeDS.deviceHandle);
244 activeDS.twCC = TWCC_OPERATIONERROR;
248 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
249 , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
250 activeDS.sane_param.depth, activeDS.sane_param.format,
251 activeDS.sane_param.last_frame);
253 activeDS.currentState = 7;
256 /* access memory buffer */
257 if (pImageMemXfer->Memory.Length < activeDS.sane_param.bytes_per_line)
259 psane_cancel (activeDS.deviceHandle);
260 activeDS.twCC = TWCC_BADVALUE;
264 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
266 FIXME("Memory Handle, may not be locked correctly\n");
267 buffer = LocalLock(pImageMemXfer->Memory.TheMem);
270 buffer = pImageMemXfer->Memory.TheMem;
272 memset(buffer,0,pImageMemXfer->Memory.Length);
276 rows = pImageMemXfer->Memory.Length / activeDS.sane_param.bytes_per_line;
278 /* must fill full lines */
279 while (consumed_len < (activeDS.sane_param.bytes_per_line*rows) &&
280 status == SANE_STATUS_GOOD)
282 status = psane_read (activeDS.deviceHandle, ptr,
283 (activeDS.sane_param.bytes_per_line*rows) - consumed_len ,
285 consumed_len += buff_len;
289 if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF)
291 pImageMemXfer->Compression = TWCP_NONE;
292 pImageMemXfer->BytesPerRow = activeDS.sane_param.bytes_per_line;
293 pImageMemXfer->Columns = activeDS.sane_param.pixels_per_line;
294 pImageMemXfer->Rows = rows;
295 pImageMemXfer->XOffset = 0;
296 pImageMemXfer->YOffset = 0;
297 pImageMemXfer->BytesWritten = consumed_len;
299 ScanningDialogBox(activeDS.progressWnd, consumed_len);
301 if (status == SANE_STATUS_EOF)
303 ScanningDialogBox(activeDS.progressWnd, -1);
304 TRACE("psane_read: %s\n", psane_strstatus (status));
305 psane_cancel (activeDS.deviceHandle);
306 twRC = TWRC_XFERDONE;
308 activeDS.twCC = TWRC_SUCCESS;
310 else if (status != SANE_STATUS_EOF)
312 ScanningDialogBox(activeDS.progressWnd, -1);
313 WARN("psane_read: %s\n", psane_strstatus (status));
314 psane_cancel (activeDS.deviceHandle);
315 activeDS.twCC = TWCC_OPERATIONERROR;
320 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
321 LocalUnlock(pImageMemXfer->Memory.TheMem);
327 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
328 TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin,
331 #ifndef SONAME_LIBSANE
334 TW_UINT16 twRC = TWRC_SUCCESS;
335 pTW_UINT32 pHandle = (pTW_UINT32) pData;
337 SANE_Byte buffer[32*1024];
344 TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
346 if (activeDS.currentState != 6)
349 activeDS.twCC = TWCC_SEQERROR;
353 /* Transfer an image from the source to the application */
354 status = psane_start (activeDS.deviceHandle);
355 if (status != SANE_STATUS_GOOD)
357 WARN("psane_start: %s\n", psane_strstatus (status));
358 psane_cancel (activeDS.deviceHandle);
359 activeDS.twCC = TWCC_OPERATIONERROR;
363 status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
364 activeDS.sane_param_valid = TRUE;
365 if (status != SANE_STATUS_GOOD)
367 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
368 psane_cancel (activeDS.deviceHandle);
369 activeDS.twCC = TWCC_OPERATIONERROR;
373 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
374 , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
375 activeDS.sane_param.depth, activeDS.sane_param.format,
376 activeDS.sane_param.last_frame);
378 ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
379 bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
380 bmpInfo.bmiHeader.biWidth = activeDS.sane_param.pixels_per_line;
381 bmpInfo.bmiHeader.biHeight = activeDS.sane_param.lines;
382 bmpInfo.bmiHeader.biPlanes = 1;
383 bmpInfo.bmiHeader.biBitCount = activeDS.sane_param.depth;
384 bmpInfo.bmiHeader.biCompression = BI_RGB;
385 bmpInfo.bmiHeader.biSizeImage = 0;
386 bmpInfo.bmiHeader.biXPelsPerMeter = 0;
387 bmpInfo.bmiHeader.biYPelsPerMeter = 0;
388 bmpInfo.bmiHeader.biClrUsed = 1;
389 bmpInfo.bmiHeader.biClrImportant = 0;
390 bmpInfo.bmiColors[0].rgbBlue = 128;
391 bmpInfo.bmiColors[0].rgbGreen = 128;
392 bmpInfo.bmiColors[0].rgbRed = 128;
393 hDIB = CreateDIBSection ((dc = GetDC(activeDS.hwndOwner)), &bmpInfo,
394 DIB_RGB_COLORS, &pBits, 0, 0);
397 psane_cancel (activeDS.deviceHandle);
398 activeDS.twCC = TWCC_LOWMEMORY;
404 status = psane_read (activeDS.deviceHandle, buffer,
405 sizeof (buffer), &buff_len);
406 if (status == SANE_STATUS_GOOD)
408 /* FIXME: put code for converting the image data into DIB here */
411 else if (status != SANE_STATUS_EOF)
413 WARN("psane_read: %s\n", psane_strstatus (status));
414 psane_cancel (activeDS.deviceHandle);
415 activeDS.twCC = TWCC_OPERATIONERROR;
418 } while (status == SANE_STATUS_GOOD);
420 psane_cancel (activeDS.deviceHandle);
421 ReleaseDC (activeDS.hwndOwner, dc);
422 *pHandle = (TW_UINT32)hDIB;
423 twRC = TWRC_XFERDONE;
424 activeDS.twCC = TWCC_SUCCESS;
425 activeDS.currentState = 7;
431 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
432 TW_UINT16 SANE_JPEGCompressionGet (pTW_IDENTITY pOrigin,
440 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
441 TW_UINT16 SANE_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
450 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
451 TW_UINT16 SANE_JPEGCompressionReset (pTW_IDENTITY pOrigin,
459 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
460 TW_UINT16 SANE_JPEGCompressionSet (pTW_IDENTITY pOrigin,
468 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
469 TW_UINT16 SANE_Palette8Get (pTW_IDENTITY pOrigin,
477 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
478 TW_UINT16 SANE_Palette8GetDefault (pTW_IDENTITY pOrigin,
486 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
487 TW_UINT16 SANE_Palette8Reset (pTW_IDENTITY pOrigin,
495 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
496 TW_UINT16 SANE_Palette8Set (pTW_IDENTITY pOrigin,
504 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
505 TW_UINT16 SANE_RGBResponseReset (pTW_IDENTITY pOrigin,
513 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
514 TW_UINT16 SANE_RGBResponseSet (pTW_IDENTITY pOrigin,