gdiplus: Add some tests for pathiterator, fix leaks.
[wine] / dlls / sane.ds / ds_image.c
1 /*
2  * Copyright 2000 Corel Corporation
3  * Copyright 2006 CodeWeavers, Aric Stewart
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include "config.h"
21
22 #include <stdarg.h>
23
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"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(twain);
33
34 /* DG_IMAGE/DAT_CIECOLOR/MSG_GET */
35 TW_UINT16 SANE_CIEColorGet (pTW_IDENTITY pOrigin, 
36                              TW_MEMREF pData)
37 {
38     FIXME ("stub!\n");
39
40     return TWRC_FAILURE;
41 }
42
43 /* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */
44 TW_UINT16 SANE_ExtImageInfoGet (pTW_IDENTITY pOrigin, 
45                                  TW_MEMREF pData)
46 {
47     FIXME ("stub!\n");
48
49     return TWRC_FAILURE;
50 }
51
52 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */
53 TW_UINT16 SANE_GrayResponseReset (pTW_IDENTITY pOrigin, 
54                                    TW_MEMREF pData)
55 {
56     FIXME ("stub!\n");
57
58     return TWRC_FAILURE;
59 }
60
61 /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */
62 TW_UINT16 SANE_GrayResponseSet (pTW_IDENTITY pOrigin, 
63                                  TW_MEMREF pData)
64 {
65     FIXME ("stub!\n");
66
67     return TWRC_FAILURE;
68 }
69
70 /* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */
71 TW_UINT16 SANE_ImageFileXferGet (pTW_IDENTITY pOrigin, 
72                                   TW_MEMREF pData)
73 {
74     FIXME ("stub!\n");
75
76     return TWRC_FAILURE;
77 }
78
79 /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */
80 TW_UINT16 SANE_ImageInfoGet (pTW_IDENTITY pOrigin, 
81                               TW_MEMREF pData)
82 {
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
90     TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
91
92     if (activeDS.currentState != 6 && activeDS.currentState != 7)
93     {
94         twRC = TWRC_FAILURE;
95         activeDS.twCC = TWCC_SEQERROR;
96     }
97     else
98     {
99         if (activeDS.currentState == 6)
100         {
101             /* return general image description information about the image about to be transferred */
102             status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
103             activeDS.sane_param_valid = TRUE;
104             TRACE("Getting parameters\n");
105         }
106
107         pImageInfo->XResolution.Whole = -1;
108         pImageInfo->XResolution.Frac = 0;
109         pImageInfo->YResolution.Whole = -1;
110         pImageInfo->YResolution.Frac = 0;
111         pImageInfo->ImageWidth = activeDS.sane_param.pixels_per_line;
112         pImageInfo->ImageLength = activeDS.sane_param.lines;
113
114         TRACE("Bits per Sample %i\n",activeDS.sane_param.depth);
115         TRACE("Frame Format %i\n",activeDS.sane_param.format);
116
117         if (activeDS.sane_param.format == SANE_FRAME_RGB )
118         {
119             pImageInfo->BitsPerPixel = activeDS.sane_param.depth * 3;
120             pImageInfo->Compression = TWCP_NONE;
121             pImageInfo->Planar = TRUE;
122             pImageInfo->SamplesPerPixel = 3;
123             pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth;
124             pImageInfo->BitsPerSample[1] = activeDS.sane_param.depth;
125             pImageInfo->BitsPerSample[2] = activeDS.sane_param.depth;
126             pImageInfo->PixelType = TWPT_RGB;
127         }
128         else if (activeDS.sane_param.format == SANE_FRAME_GRAY)
129         {
130             pImageInfo->BitsPerPixel = activeDS.sane_param.depth;
131             pImageInfo->Compression = TWCP_NONE;
132             pImageInfo->Planar = TRUE;
133             pImageInfo->SamplesPerPixel = 1;
134             pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth;
135             pImageInfo->PixelType = TWPT_GRAY;
136         }
137         else
138         {
139             ERR("Unhandled source frame type %i\n",activeDS.sane_param.format);
140             twRC = TWRC_FAILURE;
141             activeDS.twCC = TWCC_SEQERROR;
142         }
143     }
144
145     return twRC;
146 #endif
147 }
148
149 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
150 TW_UINT16 SANE_ImageLayoutGet (pTW_IDENTITY pOrigin, 
151                                 TW_MEMREF pData)
152 {
153     FIXME ("stub!\n");
154
155     return TWRC_FAILURE;
156 }
157
158 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
159 TW_UINT16 SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin, 
160                                        TW_MEMREF pData)
161 {
162     FIXME ("stub!\n");
163
164     return TWRC_FAILURE;
165 }
166
167 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
168 TW_UINT16 SANE_ImageLayoutReset (pTW_IDENTITY pOrigin, 
169                                   TW_MEMREF pData)
170 {
171     FIXME ("stub!\n");
172
173     return TWRC_FAILURE;
174 }
175
176 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
177 TW_UINT16 SANE_ImageLayoutSet (pTW_IDENTITY pOrigin, 
178                                 TW_MEMREF pData)
179 {
180     FIXME ("stub!\n");
181
182     return TWRC_FAILURE;
183 }
184
185 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
186 TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin, 
187                                  TW_MEMREF pData)
188 {
189 #ifndef SONAME_LIBSANE
190     return TWRC_FAILURE;
191 #else
192     TW_UINT16 twRC = TWRC_SUCCESS;
193     pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
194     SANE_Status status = SANE_STATUS_GOOD;
195
196     TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
197
198     if (activeDS.currentState < 6 || activeDS.currentState > 7)
199     {
200         twRC = TWRC_FAILURE;
201         activeDS.twCC = TWCC_SEQERROR;
202     }
203     else
204     {
205         LPBYTE buffer;
206         int buff_len = 0;
207         int consumed_len = 0;
208         LPBYTE ptr;
209         int rows;
210
211         /* Transfer an image from the source to the application */
212         if (activeDS.currentState == 6)
213         {
214
215             /* trigger scanning dialog */
216             activeDS.progressWnd = ScanningDialogBox(NULL,0);
217
218             ScanningDialogBox(activeDS.progressWnd,0);
219
220             status = psane_start (activeDS.deviceHandle);
221             if (status != SANE_STATUS_GOOD)
222             {
223                 WARN("psane_start: %s\n", psane_strstatus (status));
224                 psane_cancel (activeDS.deviceHandle);
225                 activeDS.twCC = TWCC_OPERATIONERROR;
226                 return TWRC_FAILURE;
227             }
228
229             status = psane_get_parameters (activeDS.deviceHandle,
230                     &activeDS.sane_param);
231             activeDS.sane_param_valid = TRUE;
232
233             if (status != SANE_STATUS_GOOD)
234             {
235                 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
236                 psane_cancel (activeDS.deviceHandle);
237                 activeDS.twCC = TWCC_OPERATIONERROR;
238                 return TWRC_FAILURE;
239             }
240
241             TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
242               , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
243               activeDS.sane_param.depth, activeDS.sane_param.format,
244               activeDS.sane_param.last_frame);
245
246             activeDS.currentState = 7;
247         }
248
249         /* access memory buffer */
250         if (pImageMemXfer->Memory.Length < activeDS.sane_param.bytes_per_line)
251         {
252             psane_cancel (activeDS.deviceHandle);
253             activeDS.twCC = TWCC_BADVALUE;
254             return TWRC_FAILURE;
255         }
256
257         if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
258         {
259             FIXME("Memory Handle, may not be locked correctly\n");
260             buffer = LocalLock(pImageMemXfer->Memory.TheMem);
261         }
262         else
263             buffer = pImageMemXfer->Memory.TheMem;
264        
265         memset(buffer,0,pImageMemXfer->Memory.Length);
266
267         ptr = buffer;
268         consumed_len = 0;
269         rows = pImageMemXfer->Memory.Length / activeDS.sane_param.bytes_per_line;
270
271         /* must fill full lines */
272         while (consumed_len < (activeDS.sane_param.bytes_per_line*rows) && 
273                 status == SANE_STATUS_GOOD)
274         {
275             status = psane_read (activeDS.deviceHandle, ptr,
276                     (activeDS.sane_param.bytes_per_line*rows) - consumed_len ,
277                     &buff_len);
278             consumed_len += buff_len;
279             ptr += buff_len;
280         }
281
282         if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF)
283         {
284             pImageMemXfer->Compression = TWCP_NONE;
285             pImageMemXfer->BytesPerRow = activeDS.sane_param.bytes_per_line;
286             pImageMemXfer->Columns = activeDS.sane_param.pixels_per_line;
287             pImageMemXfer->Rows = rows;
288             pImageMemXfer->XOffset = 0;
289             pImageMemXfer->YOffset = 0;
290             pImageMemXfer->BytesWritten = consumed_len;
291
292             ScanningDialogBox(activeDS.progressWnd, consumed_len);
293
294             if (status == SANE_STATUS_EOF)
295             {
296                 ScanningDialogBox(activeDS.progressWnd, -1);
297                 TRACE("psane_read: %s\n", psane_strstatus (status));
298                 psane_cancel (activeDS.deviceHandle);
299                 twRC = TWRC_XFERDONE;
300             }
301             activeDS.twCC = TWRC_SUCCESS;
302         }
303         else if (status != SANE_STATUS_EOF)
304         {
305             ScanningDialogBox(activeDS.progressWnd, -1);
306             WARN("psane_read: %s\n", psane_strstatus (status));
307             psane_cancel (activeDS.deviceHandle);
308             activeDS.twCC = TWCC_OPERATIONERROR;
309             twRC = TWRC_FAILURE;
310         }
311     }
312
313     if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
314         LocalUnlock(pImageMemXfer->Memory.TheMem);
315     
316     return twRC;
317 #endif
318 }
319
320 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
321 TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, 
322                                     TW_MEMREF pData)
323 {
324 #ifndef SONAME_LIBSANE
325     return TWRC_FAILURE;
326 #else
327     TW_UINT16 twRC = TWRC_SUCCESS;
328     pTW_UINT32 pHandle = (pTW_UINT32) pData;
329     SANE_Status status;
330     SANE_Byte buffer[32*1024];
331     int buff_len;
332     HBITMAP hDIB;
333     BITMAPINFO bmpInfo;
334     VOID *pBits;
335     HDC dc;
336
337     TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
338
339     if (activeDS.currentState != 6)
340     {
341         twRC = TWRC_FAILURE;
342         activeDS.twCC = TWCC_SEQERROR;
343     }
344     else
345     {
346         /* Transfer an image from the source to the application */
347         status = psane_start (activeDS.deviceHandle);
348         if (status != SANE_STATUS_GOOD)
349         {
350             WARN("psane_start: %s\n", psane_strstatus (status));
351             psane_cancel (activeDS.deviceHandle);
352             activeDS.twCC = TWCC_OPERATIONERROR;
353             return TWRC_FAILURE;
354         }
355
356         status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
357         activeDS.sane_param_valid = TRUE;
358         if (status != SANE_STATUS_GOOD)
359         {
360             WARN("psane_get_parameters: %s\n", psane_strstatus (status));
361             psane_cancel (activeDS.deviceHandle);
362             activeDS.twCC = TWCC_OPERATIONERROR;
363             return TWRC_FAILURE;
364         }
365
366         TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
367               , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
368               activeDS.sane_param.depth, activeDS.sane_param.format,
369               activeDS.sane_param.last_frame);
370
371         ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
372         bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
373         bmpInfo.bmiHeader.biWidth = activeDS.sane_param.pixels_per_line;
374         bmpInfo.bmiHeader.biHeight = activeDS.sane_param.lines;
375         bmpInfo.bmiHeader.biPlanes = 1;
376         bmpInfo.bmiHeader.biBitCount = activeDS.sane_param.depth;
377         bmpInfo.bmiHeader.biCompression = BI_RGB;
378         bmpInfo.bmiHeader.biSizeImage = 0;
379         bmpInfo.bmiHeader.biXPelsPerMeter = 0;
380         bmpInfo.bmiHeader.biYPelsPerMeter = 0;
381         bmpInfo.bmiHeader.biClrUsed = 1;
382         bmpInfo.bmiHeader.biClrImportant = 0;
383         bmpInfo.bmiColors[0].rgbBlue = 128;
384         bmpInfo.bmiColors[0].rgbGreen = 128;
385         bmpInfo.bmiColors[0].rgbRed = 128;
386         hDIB = CreateDIBSection ((dc = GetDC(activeDS.hwndOwner)), &bmpInfo,
387                                  DIB_RGB_COLORS, &pBits, 0, 0);
388         if (!hDIB)
389         {
390             psane_cancel (activeDS.deviceHandle);
391             activeDS.twCC = TWCC_LOWMEMORY;
392             return TWRC_FAILURE;
393         }
394
395         do
396         {
397             status = psane_read (activeDS.deviceHandle, buffer,
398                                 sizeof (buffer),  &buff_len);
399             if (status == SANE_STATUS_GOOD)
400             {
401                 /* FIXME: put code for converting the image data into DIB here */
402
403             }
404             else if (status != SANE_STATUS_EOF)
405             {
406                 WARN("psane_read: %s\n", psane_strstatus (status));
407                 psane_cancel (activeDS.deviceHandle);
408                 activeDS.twCC = TWCC_OPERATIONERROR;
409                 return TWRC_FAILURE;
410             }
411         } while (status == SANE_STATUS_GOOD);
412
413         psane_cancel (activeDS.deviceHandle);
414         ReleaseDC (activeDS.hwndOwner, dc);
415         *pHandle = (TW_UINT32)hDIB;
416         twRC = TWRC_XFERDONE;
417         activeDS.twCC = TWCC_SUCCESS;
418         activeDS.currentState = 7;
419     }
420     return twRC;
421 #endif
422 }
423
424 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
425 TW_UINT16 SANE_JPEGCompressionGet (pTW_IDENTITY pOrigin, 
426                                     TW_MEMREF pData)
427 {
428     FIXME ("stub!\n");
429
430     return TWRC_FAILURE;
431 }
432
433 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
434 TW_UINT16 SANE_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
435                                            
436                                            TW_MEMREF pData)
437 {
438     FIXME ("stub!\n");
439
440     return TWRC_FAILURE;
441 }
442
443 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
444 TW_UINT16 SANE_JPEGCompressionReset (pTW_IDENTITY pOrigin, 
445                                       TW_MEMREF pData)
446 {
447     FIXME ("stub!\n");
448
449     return TWRC_FAILURE;
450 }
451
452 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
453 TW_UINT16 SANE_JPEGCompressionSet (pTW_IDENTITY pOrigin, 
454                                     TW_MEMREF pData)
455 {
456     FIXME ("stub!\n");
457
458     return TWRC_FAILURE;
459 }
460
461 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
462 TW_UINT16 SANE_Palette8Get (pTW_IDENTITY pOrigin, 
463                              TW_MEMREF pData)
464 {
465     FIXME ("stub!\n");
466
467     return TWRC_FAILURE;
468 }
469
470 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
471 TW_UINT16 SANE_Palette8GetDefault (pTW_IDENTITY pOrigin, 
472                                     TW_MEMREF pData)
473 {
474     FIXME ("stub!\n");
475
476     return TWRC_FAILURE;
477 }
478
479 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
480 TW_UINT16 SANE_Palette8Reset (pTW_IDENTITY pOrigin, 
481                                TW_MEMREF pData)
482 {
483     FIXME ("stub!\n");
484
485     return TWRC_FAILURE;
486 }
487
488 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
489 TW_UINT16 SANE_Palette8Set (pTW_IDENTITY pOrigin, 
490                              TW_MEMREF pData)
491 {
492     FIXME ("stub!\n");
493
494     return TWRC_FAILURE;
495 }
496
497 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
498 TW_UINT16 SANE_RGBResponseReset (pTW_IDENTITY pOrigin, 
499                                   TW_MEMREF pData)
500 {
501     FIXME ("stub!\n");
502
503     return TWRC_FAILURE;
504 }
505
506 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
507 TW_UINT16 SANE_RGBResponseSet (pTW_IDENTITY pOrigin, 
508                                 TW_MEMREF pData)
509 {
510     FIXME ("stub!\n");
511
512     return TWRC_FAILURE;
513 }