ntdll: Use a separate memory allocation for the kernel stack.
[wine.git] / dlls / sane.ds / ds_image.c
blobb2fad94c8480ee8c0103e054fbfeb5307678d56e
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 <stdarg.h>
22 #include "sane_i.h"
23 #include "wingdi.h"
24 #include "winuser.h"
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,
31 TW_MEMREF pData)
33 TW_UINT16 twRC = TWRC_SUCCESS;
34 pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData;
35 int resolution;
37 TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n");
39 if (activeDS.currentState != 6 && activeDS.currentState != 7)
41 twRC = TWRC_FAILURE;
42 activeDS.twCC = TWCC_SEQERROR;
44 else
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;
55 return TWRC_FAILURE;
59 if (sane_option_get_int("resolution", &resolution) == TWCC_SUCCESS)
60 pImageInfo->XResolution.Whole = pImageInfo->YResolution.Whole = resolution;
61 else
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)
73 case FMT_RGB:
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;
82 break;
83 case FMT_GRAY:
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;
91 else
92 pImageInfo->PixelType = TWPT_GRAY;
93 break;
94 case FMT_OTHER:
95 twRC = TWRC_FAILURE;
96 activeDS.twCC = TWCC_SEQERROR;
97 break;
101 return twRC;
104 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */
105 TW_UINT16 SANE_ImageLayoutGet (pTW_IDENTITY pOrigin,
106 TW_MEMREF pData)
108 TW_IMAGELAYOUT *img = (TW_IMAGELAYOUT *) pData;
109 int tlx, tly, brx, bry;
110 TW_UINT16 rc;
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)
117 activeDS.twCC = rc;
118 return TWRC_FAILURE;
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;
126 img->PageNumber = 1;
127 img->FrameNumber = 1;
129 activeDS.twCC = TWCC_SUCCESS;
130 return TWRC_SUCCESS;
133 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */
134 TW_UINT16 SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin,
135 TW_MEMREF pData)
137 FIXME ("stub!\n");
139 return TWRC_FAILURE;
142 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */
143 TW_UINT16 SANE_ImageLayoutReset (pTW_IDENTITY pOrigin,
144 TW_MEMREF pData)
146 FIXME ("stub!\n");
148 return TWRC_FAILURE;
151 /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */
152 TW_UINT16 SANE_ImageLayoutSet (pTW_IDENTITY pOrigin,
153 TW_MEMREF pData)
155 TW_IMAGELAYOUT *img = (TW_IMAGELAYOUT *) pData;
156 BOOL changed = FALSE;
157 TW_UINT16 twrc;
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 = img->Frame.Left.Whole * 65536 + img->Frame.Left.Frac;
168 tly = img->Frame.Top.Whole * 65536 + img->Frame.Top.Frac;
169 brx = img->Frame.Right.Whole * 65536 + img->Frame.Right.Frac;
170 bry = img->Frame.Bottom.Whole * 65536 + img->Frame.Bottom.Frac;
172 twrc = sane_option_set_scan_area( tlx, tly, brx, bry, &changed );
173 if (twrc != TWRC_SUCCESS)
174 return (twrc);
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,
182 TW_MEMREF pData)
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)
191 twRC = TWRC_FAILURE;
192 activeDS.twCC = TWCC_SEQERROR;
194 else
196 struct read_data_params params;
197 LPBYTE buffer;
198 int retlen;
199 int rows;
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;
213 return TWRC_FAILURE;
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;
221 return TWRC_FAILURE;
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;
237 return TWRC_FAILURE;
240 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
242 FIXME("Memory Handle, may not be locked correctly\n");
243 buffer = LocalLock(pImageMemXfer->Memory.TheMem);
245 else
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, &params );
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;
278 else
280 ScanningDialogBox(activeDS.progressWnd, -1);
281 WARN("sane_read: %u\n", twRC);
282 SANE_CALL( cancel_device, NULL );
283 activeDS.twCC = TWCC_OPERATIONERROR;
284 twRC = TWRC_FAILURE;
288 if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
289 LocalUnlock(pImageMemXfer->Memory.TheMem);
291 return twRC;
294 /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
295 TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin,
296 TW_MEMREF pData)
298 TW_UINT16 twRC = TWRC_SUCCESS;
299 pTW_UINT32 pHandle = (pTW_UINT32) pData;
300 HANDLE hDIB;
301 BITMAPINFOHEADER *header = NULL;
302 int dib_bytes;
303 int dib_bytes_per_line;
304 BYTE *line;
305 RGBQUAD *colors;
306 int color_size = 0;
307 int i;
308 BYTE *p;
310 TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");
312 if (activeDS.currentState != 6)
314 twRC = TWRC_FAILURE;
315 activeDS.twCC = TWCC_SEQERROR;
317 else
319 /* Transfer an image from the source to the application */
320 if (SANE_CALL( start_device, NULL ))
322 activeDS.twCC = TWCC_OPERATIONERROR;
323 return TWRC_FAILURE;
326 if (SANE_CALL( get_params, &activeDS.frame_params ))
328 WARN("sane_get_parameters failed\n");
329 SANE_CALL( cancel_device, NULL );
330 activeDS.twCC = TWCC_OPERATIONERROR;
331 return TWRC_FAILURE;
334 switch (activeDS.frame_params.format)
336 case FMT_GRAY:
337 if (activeDS.frame_params.depth == 8)
338 color_size = (1 << 8) * sizeof(*colors);
339 else if (activeDS.frame_params.depth == 1)
341 else
343 FIXME("For NATIVE, we support only 1 bit monochrome and 8 bit Grayscale, not %d\n", activeDS.frame_params.depth);
344 SANE_CALL( cancel_device, NULL );
345 activeDS.twCC = TWCC_OPERATIONERROR;
346 return TWRC_FAILURE;
348 break;
349 case FMT_RGB:
350 break;
351 case FMT_OTHER:
352 FIXME("For NATIVE, we support only GRAY and RGB\n");
353 SANE_CALL( cancel_device, NULL );
354 activeDS.twCC = TWCC_OPERATIONERROR;
355 return TWRC_FAILURE;
358 TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d bpl=%d) from sane...\n"
359 , activeDS.frame_params.pixels_per_line, activeDS.frame_params.lines,
360 activeDS.frame_params.depth, activeDS.frame_params.format,
361 activeDS.frame_params.last_frame, activeDS.frame_params.bytes_per_line);
363 dib_bytes_per_line = ((activeDS.frame_params.bytes_per_line + 3) / 4) * 4;
364 dib_bytes = activeDS.frame_params.lines * dib_bytes_per_line;
366 hDIB = GlobalAlloc(GMEM_ZEROINIT, dib_bytes + sizeof(*header) + color_size);
367 if (hDIB)
368 header = GlobalLock(hDIB);
370 if (!header)
372 SANE_CALL( cancel_device, NULL );
373 activeDS.twCC = TWCC_LOWMEMORY;
374 if (hDIB)
375 GlobalFree(hDIB);
376 return TWRC_FAILURE;
379 header->biSize = sizeof (*header);
380 header->biWidth = activeDS.frame_params.pixels_per_line;
381 header->biHeight = activeDS.frame_params.lines;
382 header->biPlanes = 1;
383 header->biCompression = BI_RGB;
384 switch (activeDS.frame_params.format)
386 case FMT_RGB:
387 header->biBitCount = activeDS.frame_params.depth * 3;
388 break;
389 case FMT_GRAY:
390 header->biBitCount = activeDS.frame_params.depth;
391 break;
392 case FMT_OTHER:
393 break;
395 header->biSizeImage = dib_bytes;
396 header->biXPelsPerMeter = 0;
397 header->biYPelsPerMeter = 0;
398 header->biClrUsed = 0;
399 header->biClrImportant = 0;
401 p = (BYTE *)(header + 1);
403 if (color_size > 0)
405 colors = (RGBQUAD *) p;
406 p += color_size;
407 for (i = 0; i < (color_size / sizeof(*colors)); i++)
408 colors[i].rgbBlue = colors[i].rgbRed = colors[i].rgbGreen = i;
412 /* Sane returns data in top down order. Acrobat does best with
413 a bottom up DIB being returned. */
414 line = p + (activeDS.frame_params.lines - 1) * dib_bytes_per_line;
415 for (i = activeDS.frame_params.lines - 1; i >= 0; i--)
417 int retlen;
418 struct read_data_params params = { line, activeDS.frame_params.bytes_per_line, &retlen };
420 activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd,
421 ((activeDS.frame_params.lines - 1 - i) * 100)
423 (activeDS.frame_params.lines - 1));
425 twRC = SANE_CALL( read_data, &params );
426 if (twRC != TWCC_SUCCESS) break;
427 if (retlen < activeDS.frame_params.bytes_per_line) break;
428 line -= dib_bytes_per_line;
430 activeDS.progressWnd = ScanningDialogBox(activeDS.progressWnd, -1);
432 GlobalUnlock(hDIB);
434 if (twRC != TWCC_SUCCESS)
436 WARN("sane_read: %u, reading line %d\n", twRC, i);
437 SANE_CALL( cancel_device, NULL );
438 activeDS.twCC = TWCC_OPERATIONERROR;
439 GlobalFree(hDIB);
440 return TWRC_FAILURE;
443 SANE_CALL( cancel_device, NULL );
444 *pHandle = (UINT_PTR)hDIB;
445 twRC = TWRC_XFERDONE;
446 activeDS.twCC = TWCC_SUCCESS;
447 activeDS.currentState = 7;
449 return twRC;