winejoystick.drv: Use CP_UNIXCP instead of CP_ACP when converting a string that comes...
[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     SANE_Int resolution;
90
91     TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
92
93     if (activeDS.currentState != 6 && activeDS.currentState != 7)
94     {
95         twRC = TWRC_FAILURE;
96         activeDS.twCC = TWCC_SEQERROR;
97     }
98     else
99     {
100         if (activeDS.currentState == 6)
101         {
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)
106             {
107                 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
108                 psane_cancel (activeDS.deviceHandle);
109                 activeDS.twCC = TWCC_OPERATIONERROR;
110                 return TWRC_FAILURE;
111             }
112             activeDS.sane_param_valid = TRUE;
113         }
114
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;
123
124         TRACE("Bits per Sample %i\n",activeDS.sane_param.depth);
125         TRACE("Frame Format %i\n",activeDS.sane_param.format);
126
127         if (activeDS.sane_param.format == SANE_FRAME_RGB )
128         {
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;
137         }
138         else if (activeDS.sane_param.format == SANE_FRAME_GRAY)
139         {
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;
146         }
147         else
148         {
149             ERR("Unhandled source frame type %i\n",activeDS.sane_param.format);
150             twRC = TWRC_FAILURE;
151             activeDS.twCC = TWCC_SEQERROR;
152         }
153     }
154
155     return twRC;
156 #endif
157 }
158
159 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
160 TW_UINT16 SANE_ImageLayoutGet (pTW_IDENTITY pOrigin, 
161                                 TW_MEMREF pData)
162 {
163     FIXME ("stub!\n");
164
165     return TWRC_FAILURE;
166 }
167
168 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
169 TW_UINT16 SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin, 
170                                        TW_MEMREF pData)
171 {
172     FIXME ("stub!\n");
173
174     return TWRC_FAILURE;
175 }
176
177 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
178 TW_UINT16 SANE_ImageLayoutReset (pTW_IDENTITY pOrigin, 
179                                   TW_MEMREF pData)
180 {
181     FIXME ("stub!\n");
182
183     return TWRC_FAILURE;
184 }
185
186 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
187 TW_UINT16 SANE_ImageLayoutSet (pTW_IDENTITY pOrigin, 
188                                 TW_MEMREF pData)
189 {
190     FIXME ("stub!\n");
191
192     return TWRC_FAILURE;
193 }
194
195 /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
196 TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin, 
197                                  TW_MEMREF pData)
198 {
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;
205
206     TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");
207
208     if (activeDS.currentState < 6 || activeDS.currentState > 7)
209     {
210         twRC = TWRC_FAILURE;
211         activeDS.twCC = TWCC_SEQERROR;
212     }
213     else
214     {
215         LPBYTE buffer;
216         int buff_len = 0;
217         int consumed_len = 0;
218         LPBYTE ptr;
219         int rows;
220
221         /* Transfer an image from the source to the application */
222         if (activeDS.currentState == 6)
223         {
224
225             /* trigger scanning dialog */
226             activeDS.progressWnd = ScanningDialogBox(NULL,0);
227
228             ScanningDialogBox(activeDS.progressWnd,0);
229
230             status = psane_start (activeDS.deviceHandle);
231             if (status != SANE_STATUS_GOOD)
232             {
233                 WARN("psane_start: %s\n", psane_strstatus (status));
234                 psane_cancel (activeDS.deviceHandle);
235                 activeDS.twCC = TWCC_OPERATIONERROR;
236                 return TWRC_FAILURE;
237             }
238
239             status = psane_get_parameters (activeDS.deviceHandle,
240                     &activeDS.sane_param);
241             activeDS.sane_param_valid = TRUE;
242
243             if (status != SANE_STATUS_GOOD)
244             {
245                 WARN("psane_get_parameters: %s\n", psane_strstatus (status));
246                 psane_cancel (activeDS.deviceHandle);
247                 activeDS.twCC = TWCC_OPERATIONERROR;
248                 return TWRC_FAILURE;
249             }
250
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);
255
256             activeDS.currentState = 7;
257         }
258
259         /* access memory buffer */
260         if (pImageMemXfer->Memory.Length < activeDS.sane_param.bytes_per_line)
261         {
262             psane_cancel (activeDS.deviceHandle);
263             activeDS.twCC = TWCC_BADVALUE;
264             return TWRC_FAILURE;
265         }
266
267         if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
268         {
269             FIXME("Memory Handle, may not be locked correctly\n");
270             buffer = LocalLock(pImageMemXfer->Memory.TheMem);
271         }
272         else
273             buffer = pImageMemXfer->Memory.TheMem;
274        
275         memset(buffer,0,pImageMemXfer->Memory.Length);
276
277         ptr = buffer;
278         consumed_len = 0;
279         rows = pImageMemXfer->Memory.Length / activeDS.sane_param.bytes_per_line;
280
281         /* must fill full lines */
282         while (consumed_len < (activeDS.sane_param.bytes_per_line*rows) && 
283                 status == SANE_STATUS_GOOD)
284         {
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;
290         }
291
292         if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF)
293         {
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;
301
302             ScanningDialogBox(activeDS.progressWnd, consumed_len);
303
304             if (status == SANE_STATUS_EOF)
305             {
306                 ScanningDialogBox(activeDS.progressWnd, -1);
307                 TRACE("psane_read: %s\n", psane_strstatus (status));
308                 psane_cancel (activeDS.deviceHandle);
309                 twRC = TWRC_XFERDONE;
310             }
311             activeDS.twCC = TWRC_SUCCESS;
312         }
313         else if (status != SANE_STATUS_EOF)
314         {
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;
320         }
321     }
322
323     if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
324         LocalUnlock(pImageMemXfer->Memory.TheMem);
325     
326     return twRC;
327 #endif
328 }
329
330 #ifdef SONAME_LIBSANE
331 static SANE_Status read_one_line(SANE_Handle h, BYTE *line, int len)
332 {
333     int read_len;
334     SANE_Status status;
335
336     for (;;)
337     {
338         read_len = 0;
339         status = psane_read (activeDS.deviceHandle, line, len, &read_len);
340         if (status != SANE_STATUS_GOOD)
341             break;
342
343         if (read_len == len)
344             break;
345
346         line += read_len;
347         len -= read_len;
348     }
349
350     return status;
351 }
352 #endif
353
354 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
355 TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, 
356                                     TW_MEMREF pData)
357 {
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;
370
371     TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
372
373     if (activeDS.currentState != 6)
374     {
375         twRC = TWRC_FAILURE;
376         activeDS.twCC = TWCC_SEQERROR;
377     }
378     else
379     {
380         /* Transfer an image from the source to the application */
381         status = psane_start (activeDS.deviceHandle);
382         if (status != SANE_STATUS_GOOD)
383         {
384             WARN("psane_start: %s\n", psane_strstatus (status));
385             psane_cancel (activeDS.deviceHandle);
386             activeDS.twCC = TWCC_OPERATIONERROR;
387             return TWRC_FAILURE;
388         }
389
390         status = psane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
391         activeDS.sane_param_valid = TRUE;
392         if (status != SANE_STATUS_GOOD)
393         {
394             WARN("psane_get_parameters: %s\n", psane_strstatus (status));
395             psane_cancel (activeDS.deviceHandle);
396             activeDS.twCC = TWCC_OPERATIONERROR;
397             return TWRC_FAILURE;
398         }
399
400         if (activeDS.sane_param.format != SANE_FRAME_RGB)
401         {
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;
406         }
407
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);
412
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;
415
416         hDIB = GlobalAlloc(GMEM_ZEROINIT, dib_bytes + sizeof(*header));
417         if (hDIB)
418            header = GlobalLock(hDIB);
419
420         if (!header)
421         {
422             psane_cancel (activeDS.deviceHandle);
423             activeDS.twCC = TWCC_LOWMEMORY;
424             if (hDIB)
425                 GlobalFree(hDIB);
426             return TWRC_FAILURE;
427         }
428
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;
440
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--)
446         {
447             activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd,
448                     ((activeDS.sane_param.lines - 1 - i) * 100)
449                             /
450                     (activeDS.sane_param.lines - 1));
451
452             status = read_one_line(activeDS.deviceHandle, line,
453                             activeDS.sane_param.bytes_per_line);
454             if (status != SANE_STATUS_GOOD)
455                 break;
456
457             line -= dib_bytes_per_line;
458         }
459         activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1);
460
461         GlobalUnlock(hDIB);
462
463         if (status != SANE_STATUS_GOOD && status != SANE_STATUS_EOF)
464         {
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;
470         }
471
472         psane_cancel (activeDS.deviceHandle);
473         *pHandle = (TW_UINT32)hDIB;
474         twRC = TWRC_XFERDONE;
475         activeDS.twCC = TWCC_SUCCESS;
476         activeDS.currentState = 7;
477     }
478     return twRC;
479 #endif
480 }
481
482 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */
483 TW_UINT16 SANE_JPEGCompressionGet (pTW_IDENTITY pOrigin, 
484                                     TW_MEMREF pData)
485 {
486     FIXME ("stub!\n");
487
488     return TWRC_FAILURE;
489 }
490
491 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */
492 TW_UINT16 SANE_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin,
493                                            
494                                            TW_MEMREF pData)
495 {
496     FIXME ("stub!\n");
497
498     return TWRC_FAILURE;
499 }
500
501 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */
502 TW_UINT16 SANE_JPEGCompressionReset (pTW_IDENTITY pOrigin, 
503                                       TW_MEMREF pData)
504 {
505     FIXME ("stub!\n");
506
507     return TWRC_FAILURE;
508 }
509
510 /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */
511 TW_UINT16 SANE_JPEGCompressionSet (pTW_IDENTITY pOrigin, 
512                                     TW_MEMREF pData)
513 {
514     FIXME ("stub!\n");
515
516     return TWRC_FAILURE;
517 }
518
519 /* DG_IMAGE/DAT_PALETTE8/MSG_GET */
520 TW_UINT16 SANE_Palette8Get (pTW_IDENTITY pOrigin, 
521                              TW_MEMREF pData)
522 {
523     FIXME ("stub!\n");
524
525     return TWRC_FAILURE;
526 }
527
528 /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */
529 TW_UINT16 SANE_Palette8GetDefault (pTW_IDENTITY pOrigin, 
530                                     TW_MEMREF pData)
531 {
532     FIXME ("stub!\n");
533
534     return TWRC_FAILURE;
535 }
536
537 /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */
538 TW_UINT16 SANE_Palette8Reset (pTW_IDENTITY pOrigin, 
539                                TW_MEMREF pData)
540 {
541     FIXME ("stub!\n");
542
543     return TWRC_FAILURE;
544 }
545
546 /* DG_IMAGE/DAT_PALETTE8/MSG_SET */
547 TW_UINT16 SANE_Palette8Set (pTW_IDENTITY pOrigin, 
548                              TW_MEMREF pData)
549 {
550     FIXME ("stub!\n");
551
552     return TWRC_FAILURE;
553 }
554
555 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */
556 TW_UINT16 SANE_RGBResponseReset (pTW_IDENTITY pOrigin, 
557                                   TW_MEMREF pData)
558 {
559     FIXME ("stub!\n");
560
561     return TWRC_FAILURE;
562 }
563
564 /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */
565 TW_UINT16 SANE_RGBResponseSet (pTW_IDENTITY pOrigin, 
566                                 TW_MEMREF pData)
567 {
568     FIXME ("stub!\n");
569
570     return TWRC_FAILURE;
571 }