/* * Copyright 2000 Corel Corporation * Copyright 2006 CodeWeavers, Aric Stewart * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "twain.h" #include "sane_i.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(twain); /* DG_IMAGE/DAT_CIECOLOR/MSG_GET */ TW_UINT16 SANE_CIEColorGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_EXTIMAGEINFO/MSG_GET */ TW_UINT16 SANE_ExtImageInfoGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_RESET */ TW_UINT16 SANE_GrayResponseReset (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_GRAYRESPONSE/MSG_SET */ TW_UINT16 SANE_GrayResponseSet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_IMAGEFILEXFER/MSG_GET */ TW_UINT16 SANE_ImageFileXferGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_IMAGEINFO/MSG_GET */ TW_UINT16 SANE_ImageInfoGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { #ifndef HAVE_SANE return TWRC_FAILURE; #else TW_UINT16 twRC = TWRC_SUCCESS; pTW_IMAGEINFO pImageInfo = (pTW_IMAGEINFO) pData; SANE_Status status; TRACE("DG_IMAGE/DAT_IMAGEINFO/MSG_GET\n"); if (activeDS.currentState != 6 && activeDS.currentState != 7) { twRC = TWRC_FAILURE; activeDS.twCC = TWCC_SEQERROR; } else { if (activeDS.currentState == 6) { /* return general image description information about the image about to be transferred */ status = sane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param); activeDS.sane_param_valid = TRUE; TRACE("Getting parameters\n"); } pImageInfo->XResolution.Whole = -1; pImageInfo->XResolution.Frac = 0; pImageInfo->YResolution.Whole = -1; pImageInfo->YResolution.Frac = 0; pImageInfo->ImageWidth = activeDS.sane_param.pixels_per_line; pImageInfo->ImageLength = activeDS.sane_param.lines; TRACE("Bits per Sample %i\n",activeDS.sane_param.depth); TRACE("Frame Format %i\n",activeDS.sane_param.format); if (activeDS.sane_param.format == SANE_FRAME_RGB ) { pImageInfo->BitsPerPixel = activeDS.sane_param.depth * 3; pImageInfo->Compression = TWCP_NONE; pImageInfo->Planar = TRUE; pImageInfo->SamplesPerPixel = 3; pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth; pImageInfo->BitsPerSample[1] = activeDS.sane_param.depth; pImageInfo->BitsPerSample[2] = activeDS.sane_param.depth; pImageInfo->PixelType = TWPT_RGB; } else if (activeDS.sane_param.format == SANE_FRAME_GRAY) { pImageInfo->BitsPerPixel = activeDS.sane_param.depth; pImageInfo->Compression = TWCP_NONE; pImageInfo->Planar = TRUE; pImageInfo->SamplesPerPixel = 1; pImageInfo->BitsPerSample[0] = activeDS.sane_param.depth; pImageInfo->PixelType = TWPT_GRAY; } else { ERR("Unhandled source frame type %i\n",activeDS.sane_param.format); twRC = TWRC_FAILURE; activeDS.twCC = TWCC_SEQERROR; } } return twRC; #endif } /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GET */ TW_UINT16 SANE_ImageLayoutGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_GETDEFAULT */ TW_UINT16 SANE_ImageLayoutGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_RESET */ TW_UINT16 SANE_ImageLayoutReset (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_IMAGELAYOUT/MSG_SET */ TW_UINT16 SANE_ImageLayoutSet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */ TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { #ifndef HAVE_SANE return TWRC_FAILURE; #else TW_UINT16 twRC = TWRC_SUCCESS; pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData; SANE_Status status = SANE_STATUS_GOOD; TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n"); if (activeDS.currentState < 6 || activeDS.currentState > 7) { twRC = TWRC_FAILURE; activeDS.twCC = TWCC_SEQERROR; } else { LPBYTE buffer; int buff_len = 0; int consumed_len = 0; LPBYTE ptr; int rows; /* Transfer an image from the source to the application */ if (activeDS.currentState == 6) { /* trigger scanning dialog */ activeDS.progressWnd = ScanningDialogBox(NULL,0); ScanningDialogBox(activeDS.progressWnd,0); status = sane_start (activeDS.deviceHandle); if (status != SANE_STATUS_GOOD) { WARN("sane_start: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_OPERATIONERROR; return TWRC_FAILURE; } status = sane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param); activeDS.sane_param_valid = TRUE; if (status != SANE_STATUS_GOOD) { WARN("sane_get_parameters: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_OPERATIONERROR; return TWRC_FAILURE; } TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n" , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines, activeDS.sane_param.depth, activeDS.sane_param.format, activeDS.sane_param.last_frame); activeDS.currentState = 7; } /* access memory buffer */ if (pImageMemXfer->Memory.Length < activeDS.sane_param.bytes_per_line) { sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_BADVALUE; return TWRC_FAILURE; } if (pImageMemXfer->Memory.Flags & TWMF_HANDLE) { FIXME("Memory Handle, may not be locked correctly\n"); buffer = LocalLock(pImageMemXfer->Memory.TheMem); } else buffer = pImageMemXfer->Memory.TheMem; memset(buffer,0,pImageMemXfer->Memory.Length); ptr = buffer; consumed_len = 0; rows = pImageMemXfer->Memory.Length / activeDS.sane_param.bytes_per_line; /* must fill full lines */ while (consumed_len < (activeDS.sane_param.bytes_per_line*rows) && status == SANE_STATUS_GOOD) { status = sane_read (activeDS.deviceHandle, ptr, (activeDS.sane_param.bytes_per_line*rows) - consumed_len , &buff_len); consumed_len += buff_len; ptr += buff_len; } if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF) { pImageMemXfer->Compression = TWCP_NONE; pImageMemXfer->BytesPerRow = activeDS.sane_param.bytes_per_line; pImageMemXfer->Columns = activeDS.sane_param.pixels_per_line; pImageMemXfer->Rows = rows; pImageMemXfer->XOffset = 0; pImageMemXfer->YOffset = 0; pImageMemXfer->BytesWritten = consumed_len; ScanningDialogBox(activeDS.progressWnd, consumed_len); if (status == SANE_STATUS_EOF) { ScanningDialogBox(activeDS.progressWnd, -1); TRACE("sane_read: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); twRC = TWRC_XFERDONE; } activeDS.twCC = TWRC_SUCCESS; } else if (status != SANE_STATUS_EOF) { ScanningDialogBox(activeDS.progressWnd, -1); WARN("sane_read: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_OPERATIONERROR; twRC = TWRC_FAILURE; } } if (pImageMemXfer->Memory.Flags & TWMF_HANDLE) LocalUnlock(pImageMemXfer->Memory.TheMem); return twRC; #endif } /* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */ TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { #ifndef HAVE_SANE return TWRC_FAILURE; #else TW_UINT16 twRC = TWRC_SUCCESS; pTW_UINT32 pHandle = (pTW_UINT32) pData; SANE_Status status; SANE_Byte buffer[32*1024]; int buff_len; HBITMAP hDIB; BITMAPINFO bmpInfo; VOID *pBits; HDC dc; TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n"); if (activeDS.currentState != 6) { twRC = TWRC_FAILURE; activeDS.twCC = TWCC_SEQERROR; } else { /* Transfer an image from the source to the application */ status = sane_start (activeDS.deviceHandle); if (status != SANE_STATUS_GOOD) { WARN("sane_start: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_OPERATIONERROR; return TWRC_FAILURE; } status = sane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param); activeDS.sane_param_valid = TRUE; if (status != SANE_STATUS_GOOD) { WARN("sane_get_parameters: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_OPERATIONERROR; return TWRC_FAILURE; } TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n" , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines, activeDS.sane_param.depth, activeDS.sane_param.format, activeDS.sane_param.last_frame); ZeroMemory (&bmpInfo, sizeof (BITMAPINFO)); bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth = activeDS.sane_param.pixels_per_line; bmpInfo.bmiHeader.biHeight = activeDS.sane_param.lines; bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = activeDS.sane_param.depth; bmpInfo.bmiHeader.biCompression = BI_RGB; bmpInfo.bmiHeader.biSizeImage = 0; bmpInfo.bmiHeader.biXPelsPerMeter = 0; bmpInfo.bmiHeader.biYPelsPerMeter = 0; bmpInfo.bmiHeader.biClrUsed = 1; bmpInfo.bmiHeader.biClrImportant = 0; bmpInfo.bmiColors[0].rgbBlue = 128; bmpInfo.bmiColors[0].rgbGreen = 128; bmpInfo.bmiColors[0].rgbRed = 128; hDIB = CreateDIBSection ((dc = GetDC(activeDS.hwndOwner)), &bmpInfo, DIB_RGB_COLORS, &pBits, 0, 0); if (!hDIB) { sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_LOWMEMORY; return TWRC_FAILURE; } do { status = sane_read (activeDS.deviceHandle, buffer, sizeof (buffer), &buff_len); if (status == SANE_STATUS_GOOD) { /* FIXME: put code for converting the image data into DIB here */ } else if (status != SANE_STATUS_EOF) { WARN("sane_read: %s\n", sane_strstatus (status)); sane_cancel (activeDS.deviceHandle); activeDS.twCC = TWCC_OPERATIONERROR; return TWRC_FAILURE; } } while (status == SANE_STATUS_GOOD); sane_cancel (activeDS.deviceHandle); ReleaseDC (activeDS.hwndOwner, dc); *pHandle = (TW_UINT32)hDIB; twRC = TWRC_XFERDONE; activeDS.twCC = TWCC_SUCCESS; activeDS.currentState = 7; } return twRC; #endif } /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GET */ TW_UINT16 SANE_JPEGCompressionGet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_GETDEFAULT */ TW_UINT16 SANE_JPEGCompressionGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_RESET */ TW_UINT16 SANE_JPEGCompressionReset (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_JPEGCOMPRESSION/MSG_SET */ TW_UINT16 SANE_JPEGCompressionSet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_PALETTE8/MSG_GET */ TW_UINT16 SANE_Palette8Get (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_PALETTE8/MSG_GETDEFAULT */ TW_UINT16 SANE_Palette8GetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_PALETTE8/MSG_RESET */ TW_UINT16 SANE_Palette8Reset (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_PALETTE8/MSG_SET */ TW_UINT16 SANE_Palette8Set (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_RGBRESPONSE/MSG_RESET */ TW_UINT16 SANE_RGBResponseReset (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; } /* DG_IMAGE/DAT_RGBRESPONSE/MSG_SET */ TW_UINT16 SANE_RGBResponseSet (pTW_IDENTITY pOrigin, TW_MEMREF pData) { FIXME ("stub!\n"); return TWRC_FAILURE; }