include: Add IShellItem to headers.
[wine.git] / dlls / sane.ds / ds_image.c
blob38689da13f8db1198cb586f5e7c35e03cc72c0af
1 /*
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
20 #include "config.h"
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "twain.h"
29 #include "sane_i.h"
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,
36 TW_MEMREF pData)
38 FIXME ("stub!\n");
40 return TWRC_FAILURE;
43 /* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */
44 TW_UINT16 SANE_ExtImageInfoGet (pTW_IDENTITY pOrigin,
45 TW_MEMREF pData)
47 FIXME ("stub!\n");
49 return TWRC_FAILURE;
52 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */
53 TW_UINT16 SANE_GrayResponseReset (pTW_IDENTITY pOrigin,
54 TW_MEMREF pData)
56 FIXME ("stub!\n");
58 return TWRC_FAILURE;
61 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */
62 TW_UINT16 SANE_GrayResponseSet (pTW_IDENTITY pOrigin,
63 TW_MEMREF pData)
65 FIXME ("stub!\n");
67 return TWRC_FAILURE;
70 /* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */
71 TW_UINT16 SANE_ImageFileXferGet (pTW_IDENTITY pOrigin,
72 TW_MEMREF pData)
74 FIXME ("stub!\n");
76 return TWRC_FAILURE;
79 /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
80 TW_UINT16 SANE_ImageInfoGet (pTW_IDENTITY pOrigin,
81 TW_MEMREF pData)
83 #ifndef SONAME_LIBSANE
84 return TWRC_FAILURE;
85 #else
86 TW_UINT16 twRC = TWRC_SUCCESS;
87 pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData;
88 SANE_Status status;
89 SANE_Int resolution;
91 TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
93 if (activeDS.currentState != 6 && activeDS.currentState != 7)
95 twRC = TWRC_FAILURE;
96 activeDS.twCC = TWCC_SEQERROR;
98 else
100 if (activeDS.currentState == 6)
102 /* return general image description information about the image about to be transferred */
103 status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
104 TRACE("Getting parameters\n");
105 if (status != SANE_STATUS_GOOD)
107 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
108 psane_cancel (activeDS.deviceHandle);
109 activeDS.twCC = TWCC_OPERATIONERROR;
110 return TWRC_FAILURE;
112 activeDS.sane_param_valid = TRUE;
115 if (sane_option_get_int(activeDS.deviceHandle, "resolution", &resolution) == SANE_STATUS_GOOD)
116 pImageInfo->XResolution.Whole = pImageInfo->YResolution.Whole = resolution;
117 else
118 pImageInfo->XResolution.Whole = pImageInfo->YResolution.Whole = -1;
119 pImageInfo->XResolution.Frac = 0;
120 pImageInfo->YResolution.Frac = 0;
121 pImageInfo->ImageWidth = activeDS.sane_param.pixels_per_line;
122 pImageInfo->ImageLength = activeDS.sane_param.lines;
124 TRACE("Bits per Sample %i\n",activeDS.sane_param.depth);
125 TRACE("Frame Format %i\n",activeDS.sane_param.format);
127 if (activeDS.sane_param.format == SANE_FRAME_RGB )
129 pImageInfo->BitsPerPixel = activeDS.sane_param.depth * 3;
130 pImageInfo->Compression = TWCP_NONE;
131 pImageInfo->Planar = TRUE;
132 pImageInfo->SamplesPerPixel = 3;
133 pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth;
134 pImageInfo->BitsPerSample[1] = activeDS.sane_param.depth;
135 pImageInfo->BitsPerSample[2] = activeDS.sane_param.depth;
136 pImageInfo->PixelType = TWPT_RGB;
138 else if (activeDS.sane_param.format == SANE_FRAME_GRAY)
140 pImageInfo->BitsPerPixel = activeDS.sane_param.depth;
141 pImageInfo->Compression = TWCP_NONE;
142 pImageInfo->Planar = TRUE;
143 pImageInfo->SamplesPerPixel = 1;
144 pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth;
145 pImageInfo->PixelType = TWPT_GRAY;
147 else
149 ERR("Unhandled source frame type %i\n",activeDS.sane_param.format);
150 twRC = TWRC_FAILURE;
151 activeDS.twCC = TWCC_SEQERROR;
155 return twRC;
156 #endif
159 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
160 TW_UINT16 SANE_ImageLayoutGet (pTW_IDENTITY pOrigin,
161 TW_MEMREF pData)
163 FIXME ("stub!\n");
165 return TWRC_FAILURE;
168 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
169 TW_UINT16 SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin,
170 TW_MEMREF pData)
172 FIXME ("stub!\n");
174 return TWRC_FAILURE;
177 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
178 TW_UINT16 SANE_ImageLayoutReset (pTW_IDENTITY pOrigin,
179 TW_MEMREF pData)
181 FIXME ("stub!\n");
183 return TWRC_FAILURE;
186 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
187 TW_UINT16 SANE_ImageLayoutSet (pTW_IDENTITY pOrigin,
188 TW_MEMREF pData)
190 FIXME ("stub!\n");
192 return TWRC_FAILURE;
195 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
196 TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin,
197 TW_MEMREF pData)
199 #ifndef SONAME_LIBSANE
200 return TWRC_FAILURE;
201 #else
202 TW_UINT16 twRC = TWRC_SUCCESS;
203 pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
204 SANE_Status status = SANE_STATUS_GOOD;
206 TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
208 if (activeDS.currentState < 6 || activeDS.currentState > 7)
210 twRC = TWRC_FAILURE;
211 activeDS.twCC = TWCC_SEQERROR;
213 else
215 LPBYTE buffer;
216 int buff_len = 0;
217 int consumed_len = 0;
218 LPBYTE ptr;
219 int rows;
221 /* Transfer an image from the source to the application */
222 if (activeDS.currentState == 6)
225 /* trigger scanning dialog */
226 activeDS.progressWnd = ScanningDialogBox(NULL,0);
228 ScanningDialogBox(activeDS.progressWnd,0);
230 status = psane_start (activeDS.deviceHandle);
231 if (status != SANE_STATUS_GOOD)
233 WARN("psane_start: %s\n", psane_strstatus (status));
234 psane_cancel (activeDS.deviceHandle);
235 activeDS.twCC = TWCC_OPERATIONERROR;
236 return TWRC_FAILURE;
239 status = psane_get_parameters (activeDS.deviceHandle,
240 &activeDS.sane_param);
241 activeDS.sane_param_valid = TRUE;
243 if (status != SANE_STATUS_GOOD)
245 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
246 psane_cancel (activeDS.deviceHandle);
247 activeDS.twCC = TWCC_OPERATIONERROR;
248 return TWRC_FAILURE;
251 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
252 , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
253 activeDS.sane_param.depth, activeDS.sane_param.format,
254 activeDS.sane_param.last_frame);
256 activeDS.currentState = 7;
259 /* access memory buffer */
260 if (pImageMemXfer->Memory.Length < activeDS.sane_param.bytes_per_line)
262 psane_cancel (activeDS.deviceHandle);
263 activeDS.twCC = TWCC_BADVALUE;
264 return TWRC_FAILURE;
267 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
269 FIXME("Memory Handle, may not be locked correctly\n");
270 buffer = LocalLock(pImageMemXfer->Memory.TheMem);
272 else
273 buffer = pImageMemXfer->Memory.TheMem;
275 memset(buffer,0,pImageMemXfer->Memory.Length);
277 ptr = buffer;
278 consumed_len = 0;
279 rows = pImageMemXfer->Memory.Length / activeDS.sane_param.bytes_per_line;
281 /* must fill full lines */
282 while (consumed_len < (activeDS.sane_param.bytes_per_line*rows) &&
283 status == SANE_STATUS_GOOD)
285 status = psane_read (activeDS.deviceHandle, ptr,
286 (activeDS.sane_param.bytes_per_line*rows) - consumed_len ,
287 &buff_len);
288 consumed_len += buff_len;
289 ptr += buff_len;
292 if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF)
294 pImageMemXfer->Compression = TWCP_NONE;
295 pImageMemXfer->BytesPerRow = activeDS.sane_param.bytes_per_line;
296 pImageMemXfer->Columns = activeDS.sane_param.pixels_per_line;
297 pImageMemXfer->Rows = rows;
298 pImageMemXfer->XOffset = 0;
299 pImageMemXfer->YOffset = 0;
300 pImageMemXfer->BytesWritten = consumed_len;
302 ScanningDialogBox(activeDS.progressWnd, consumed_len);
304 if (status == SANE_STATUS_EOF)
306 ScanningDialogBox(activeDS.progressWnd, -1);
307 TRACE("psane_read: %s\n", psane_strstatus (status));
308 psane_cancel (activeDS.deviceHandle);
309 twRC = TWRC_XFERDONE;
311 activeDS.twCC = TWRC_SUCCESS;
313 else if (status != SANE_STATUS_EOF)
315 ScanningDialogBox(activeDS.progressWnd, -1);
316 WARN("psane_read: %s\n", psane_strstatus (status));
317 psane_cancel (activeDS.deviceHandle);
318 activeDS.twCC = TWCC_OPERATIONERROR;
319 twRC = TWRC_FAILURE;
323 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
324 LocalUnlock(pImageMemXfer->Memory.TheMem);
326 return twRC;
327 #endif
330 #ifdef SONAME_LIBSANE
331 static SANE_Status read_one_line(SANE_Handle h, BYTE *line, int len)
333 int read_len;
334 SANE_Status status;
336 for (;;)
338 read_len = 0;
339 status = psane_read (activeDS.deviceHandle, line, len, &read_len);
340 if (status != SANE_STATUS_GOOD)
341 break;
343 if (read_len == len)
344 break;
346 line += read_len;
347 len -= read_len;
350 return status;
352 #endif
354 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
355 TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin,
356 TW_MEMREF pData)
358 #ifndef SONAME_LIBSANE
359 return TWRC_FAILURE;
360 #else
361 TW_UINT16 twRC = TWRC_SUCCESS;
362 pTW_UINT32 pHandle = (pTW_UINT32) pData;
363 SANE_Status status;
364 HANDLE hDIB;
365 BITMAPINFOHEADER *header = NULL;
366 int dib_bytes;
367 int dib_bytes_per_line;
368 BYTE *line;
369 int i;
371 TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
373 if (activeDS.currentState != 6)
375 twRC = TWRC_FAILURE;
376 activeDS.twCC = TWCC_SEQERROR;
378 else
380 /* Transfer an image from the source to the application */
381 status = psane_start (activeDS.deviceHandle);
382 if (status != SANE_STATUS_GOOD)
384 WARN("psane_start: %s\n", psane_strstatus (status));
385 psane_cancel (activeDS.deviceHandle);
386 activeDS.twCC = TWCC_OPERATIONERROR;
387 return TWRC_FAILURE;
390 status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
391 activeDS.sane_param_valid = TRUE;
392 if (status != SANE_STATUS_GOOD)
394 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
395 psane_cancel (activeDS.deviceHandle);
396 activeDS.twCC = TWCC_OPERATIONERROR;
397 return TWRC_FAILURE;
400 if (activeDS.sane_param.format != SANE_FRAME_RGB)
402 FIXME("For NATIVE, we support only RGB, not %d\n", activeDS.sane_param.format);
403 psane_cancel (activeDS.deviceHandle);
404 activeDS.twCC = TWCC_OPERATIONERROR;
405 return TWRC_FAILURE;
408 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d bpl=%d) from sane...\n"
409 , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
410 activeDS.sane_param.depth, activeDS.sane_param.format,
411 activeDS.sane_param.last_frame, activeDS.sane_param.bytes_per_line);
413 dib_bytes_per_line = ((activeDS.sane_param.bytes_per_line + 3) / 4) * 4;
414 dib_bytes = activeDS.sane_param.lines * dib_bytes_per_line;
416 hDIB = GlobalAlloc(GMEM_ZEROINIT, dib_bytes + sizeof(*header));
417 if (hDIB)
418 header = GlobalLock(hDIB);
420 if (!header)
422 psane_cancel (activeDS.deviceHandle);
423 activeDS.twCC = TWCC_LOWMEMORY;
424 if (hDIB)
425 GlobalFree(hDIB);
426 return TWRC_FAILURE;
429 header->biSize = sizeof (*header);
430 header->biWidth = activeDS.sane_param.pixels_per_line;
431 header->biHeight = activeDS.sane_param.lines;
432 header->biPlanes = 1;
433 header->biBitCount = activeDS.sane_param.depth * 3;
434 header->biCompression = BI_RGB;
435 header->biSizeImage = dib_bytes;
436 header->biXPelsPerMeter = 0;
437 header->biYPelsPerMeter = 0;
438 header->biClrUsed = 0;
439 header->biClrImportant = 0;
441 /* Sane returns data in top down order. Acrobat does best with
442 a bottom up DIB being returned. */
443 line = (BYTE *)(header + 1) +
444 (activeDS.sane_param.lines - 1) * dib_bytes_per_line;
445 for (i = activeDS.sane_param.lines - 1; i >= 0; i--)
447 activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd,
448 ((activeDS.sane_param.lines - 1 - i) * 100)
450 (activeDS.sane_param.lines - 1));
452 status = read_one_line(activeDS.deviceHandle, line,
453 activeDS.sane_param.bytes_per_line);
454 if (status != SANE_STATUS_GOOD)
455 break;
457 line -= dib_bytes_per_line;
459 activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1);
461 GlobalUnlock(hDIB);
463 if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF)
465 WARN("psane_read: %s, reading line %d\n", psane_strstatus(status), i);
466 psane_cancel (activeDS.deviceHandle);
467 activeDS.twCC = TWCC_OPERATIONERROR;
468 GlobalFree(hDIB);
469 return TWRC_FAILURE;
472 psane_cancel (activeDS.deviceHandle);
473 *pHandle = (TW_UINT32)hDIB;
474 twRC = TWRC_XFERDONE;
475 activeDS.twCC = TWCC_SUCCESS;
476 activeDS.currentState = 7;
478 return twRC;
479 #endif
482 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
483 TW_UINT16 SANE_JPEGCompressionGet (pTW_IDENTITY pOrigin,
484 TW_MEMREF pData)
486 FIXME ("stub!\n");
488 return TWRC_FAILURE;
491 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
492 TW_UINT16 SANE_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
494 TW_MEMREF pData)
496 FIXME ("stub!\n");
498 return TWRC_FAILURE;
501 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
502 TW_UINT16 SANE_JPEGCompressionReset (pTW_IDENTITY pOrigin,
503 TW_MEMREF pData)
505 FIXME ("stub!\n");
507 return TWRC_FAILURE;
510 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
511 TW_UINT16 SANE_JPEGCompressionSet (pTW_IDENTITY pOrigin,
512 TW_MEMREF pData)
514 FIXME ("stub!\n");
516 return TWRC_FAILURE;
519 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
520 TW_UINT16 SANE_Palette8Get (pTW_IDENTITY pOrigin,
521 TW_MEMREF pData)
523 FIXME ("stub!\n");
525 return TWRC_FAILURE;
528 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
529 TW_UINT16 SANE_Palette8GetDefault (pTW_IDENTITY pOrigin,
530 TW_MEMREF pData)
532 FIXME ("stub!\n");
534 return TWRC_FAILURE;
537 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
538 TW_UINT16 SANE_Palette8Reset (pTW_IDENTITY pOrigin,
539 TW_MEMREF pData)
541 FIXME ("stub!\n");
543 return TWRC_FAILURE;
546 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
547 TW_UINT16 SANE_Palette8Set (pTW_IDENTITY pOrigin,
548 TW_MEMREF pData)
550 FIXME ("stub!\n");
552 return TWRC_FAILURE;
555 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
556 TW_UINT16 SANE_RGBResponseReset (pTW_IDENTITY pOrigin,
557 TW_MEMREF pData)
559 FIXME ("stub!\n");
561 return TWRC_FAILURE;
564 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
565 TW_UINT16 SANE_RGBResponseSet (pTW_IDENTITY pOrigin,
566 TW_MEMREF pData)
568 FIXME ("stub!\n");
570 return TWRC_FAILURE;