diff options
| author | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
|---|---|---|
| committer | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
| commit | 96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch) | |
| tree | ad5f3ede5cbcd6b598677ce41bcf8318471bdd92 /wia/ProdScan/FileConv.cpp | |
| parent | 687b274aa38fd05c8c26e3068932121876d7f745 (diff) | |
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'wia/ProdScan/FileConv.cpp')
| -rw-r--r-- | wia/ProdScan/FileConv.cpp | 730 |
1 files changed, 730 insertions, 0 deletions
diff --git a/wia/ProdScan/FileConv.cpp b/wia/ProdScan/FileConv.cpp new file mode 100644 index 00000000..5e3091d2 --- /dev/null +++ b/wia/ProdScan/FileConv.cpp @@ -0,0 +1,730 @@ +/************************************************************************** +* +* Copyright � Microsoft Corporation +* +* Title: FileConv.cpp +* +* Description: This file contains implementation of utility functions for +* image file format conversions used by the sample driver. +* +***************************************************************************/ + +#include "stdafx.h" + +// +// The GDI+ codec name used for the DIB file format: +// +#define GDIPLUS_BMP_ENCODER L"image/bmp" + +/**************************************************************************\ +* +* Inline function to convert a GDI+ result code to a COM HRESULT, +* similar to the HRESULT_FOM_WIN32 macro. +* +* Parameters: +* +* status - GDI+ return code value +* +* Return Value: +* +* HRESULT describing the GDI+ status, E_FAIL if conversion is possible +* +\**************************************************************************/ + +inline HRESULT +GDISTATUS_TO_HRESULT( + Gdiplus::Status status) +{ + HRESULT hr = E_FAIL; + DWORD dwErr = NO_ERROR; + + switch (status) + { + case Gdiplus::Ok: + hr = S_OK; + break; + + case Gdiplus::InvalidParameter: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::InvalidParameter")); + hr = E_INVALIDARG; + break; + + case Gdiplus::OutOfMemory: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::OutOfMemory")); + hr = E_OUTOFMEMORY; + break; + + case Gdiplus::InsufficientBuffer: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::InsufficientBuffer")); + hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + break; + + case Gdiplus::Aborted: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::Aborted")); + hr = E_ABORT; + break; + + case Gdiplus::ObjectBusy: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::ObjectBusy")); + hr = E_PENDING; + break; + + case Gdiplus::FileNotFound: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::FileNotFound")); + hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); + break; + + case Gdiplus::AccessDenied: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::AccessDenied")); + hr = E_ACCESSDENIED; + break; + + case Gdiplus::UnknownImageFormat: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::UnknownImageFormat")); + hr = HRESULT_FROM_WIN32(ERROR_INVALID_PIXEL_FORMAT); + break; + + case Gdiplus::NotImplemented: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::NotImplemented")); + hr = E_NOTIMPL; + break; + + case Gdiplus::Win32Error: + dwErr = GetLastError(); + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::Win32Error, last error: 0x%08X", dwErr)); + hr = HRESULT_FROM_WIN32(dwErr); + break; + + case Gdiplus::ValueOverflow: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::ValueOverflow")); + hr = E_FAIL; + break; + + case Gdiplus::FontFamilyNotFound: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::FontFamilyNotFound")); + hr = E_FAIL; + break; + + case Gdiplus::FontStyleNotFound: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::FontFamilyNotFound")); + hr = E_FAIL; + break; + + case Gdiplus::NotTrueTypeFont: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::NotTrueTypeFont")); + hr = E_FAIL; + break; + + case Gdiplus::UnsupportedGdiplusVersion: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::UnsupportedGdiplusVersion")); + hr = E_FAIL; + break; + + case Gdiplus::GdiplusNotInitialized: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::GdiplusNotInitialized")); + hr = E_FAIL; + break; + + case Gdiplus::WrongState: + WIAEX_ERROR((g_hInst, "GDI+: Gdiplus::WrongState")); + hr = E_FAIL; + break; + + default: + WIAEX_ERROR((g_hInst, "GDI+: unknown Gdiplus status code (%u)", (ULONG)status)); + hr = E_FAIL; + } + + return hr; +} + +/**************************************************************************\ +* +* Executes GdiplusStartup to initialize the GDI+ engine. Must be called +* before calling ConvertImageToDIB. A matching ShutdownGDIPlus call +* must be always made to stop the GDI+ engine started by this function. +* +* Parameters: +* +* ppToken - token returned by GDI+, must be used when calling ShutdownGDIPlus +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT +InitializeGDIPlus( + _Out_ ULONG_PTR *ppToken) +{ + HRESULT hr = S_OK; + GdiplusStartupInput gdiplusStartupInput; + + if (!ppToken) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr)); + } + + // + // Start the GDI+ engine: + // + if (SUCCEEDED(hr)) + { + hr = GDISTATUS_TO_HRESULT(GdiplusStartup(ppToken, &gdiplusStartupInput, NULL)); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Gdiplus::GdiplusStartup failed, hr = 0x%08X", hr)); + } + } + + return hr; +} + +/**************************************************************************\ +* +* Executes GdiplusShutdown to shutdown the GDI+ engine. +* +* Parameters: +* +* pToken - token obtained from a previous InitializeGDIPlus call +* +* Return Value: +* +* E_INVALIDARG if called with a NULL pToken parameter or S_OK +* (GDI+ does not return a result code for GdiplusShutdown) +* +\**************************************************************************/ + +HRESULT +ShutdownGDIPlus( + _In_ ULONG_PTR pToken) +{ + HRESULT hr = S_OK; + + if (!pToken) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr)); + } + + // + // Shutdown the GDI+ engine: + // + if (SUCCEEDED(hr)) + { + GdiplusShutdown(pToken); + } + + return hr; +} + +/**************************************************************************\ +* +* Internal helper for ConvertImageToDIB. Enumerates available GDI+ image +* format encoders and returns the CLSID of the specified encoder, if available. +* +* Parameters: +* +* wszFormat - GDI+ format name, e.g. "image/bmp" for DIB +* pClisid - returns the CLSID of the GDI+ encoder +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT +_GetEncoderCLSID( + _In_ LPCWSTR wszFormat, + _Out_ CLSID *pClsid) +{ + HRESULT hr = S_OK; + UINT nNumEncoders = 0; + UINT cbEncoderSize = 0; + ImageCodecInfo *pImageCodecInfo = NULL; + + if ((!wszFormat) || (!pClsid)) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr)); + } + + if (SUCCEEDED(hr)) + { + hr = GDISTATUS_TO_HRESULT(GetImageEncodersSize(&nNumEncoders, &cbEncoderSize)); + if (SUCCEEDED(hr) && (!cbEncoderSize)) + { + hr = E_FAIL; + } + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Gdiplus::GetImageEncodersSize(%ws) failed, hr = 0x%08X", wszFormat, hr)); + } + } + + if (SUCCEEDED(hr)) + { + pImageCodecInfo = (ImageCodecInfo*)new BYTE[cbEncoderSize]; + if (!pImageCodecInfo) + { + hr = E_OUTOFMEMORY; + WIAEX_ERROR((g_hInst, "Failed to allocate memory for the encoder info, hr = 0x%08X", hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = GDISTATUS_TO_HRESULT(GetImageEncoders(nNumEncoders, cbEncoderSize, pImageCodecInfo)); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Gdiplus::GetImageEncoders(%u encoders) failed, hr = 0x%08X", nNumEncoders, hr)); + } + } + + if (SUCCEEDED(hr)) + { + hr = E_FAIL; + + for (UINT j = 0; j < nNumEncoders; ++j) + { + _Analysis_assume_(cbEncoderSize >= nNumEncoders * sizeof(ImageCodecInfo)); + _Analysis_assume_(wcslen(wszFormat) < (cbEncoderSize / sizeof(WCHAR))); + + if (!wcscmp(pImageCodecInfo[j].MimeType, wszFormat)) + { + *pClsid = pImageCodecInfo[j].Clsid; + hr = S_OK; + break; + } + } + + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "No %ws encoder found in %u available GDI+ encoders, hr = 0x%08X", wszFormat, nNumEncoders, hr)); + } + } + + if (pImageCodecInfo) + { + delete[] pImageCodecInfo; + } + + return hr; +} + +/**************************************************************************\ +* +* Converts a GDI+ compatible image to a Windows DIB. +* +* Parameters: +* +* pInputImage - GDI+ Image object containing the image to be converted +* ppOutputStream - returns a new global memory IStream containing the +* converted DIB image file (must be released by caller) +* plImageWidth - (optional) returns the width of the image, in pixels +* plImageHeight - (optional) returns the height of the image, in pixels +* plOutputImageBPL - (optional) returns the estimated number of bytes +* per line for the converted DIB image +* +* Remarks: +* +* The caller is responsible to release the returned IStream object to +* free the memory after successful execution of this function. +* +* The caller must execute InitializeGDIPlus before calling this function. +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT +ConvertImageToDIB( + _In_ Image *pInputImage, + _Outptr_ IStream **ppOutputStream, + _Out_opt_ LONG *plImageWidth, + _Out_opt_ LONG *plImageHeight, + _Out_opt_ LONG *plOutputImageBPL) +{ + HRESULT hr = S_OK; + CLSID clsidBmpEncoder = {}; + LONG lImageWidth = 0; + LONG lImageHeight = 0; + LONG lOutputBPL = 0; + LONG lBitDepth = 0; + + WIAEX_TRACE_BEGIN; + + if ((!pInputImage) || (!ppOutputStream)) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08X", hr)); + } + + // + // Read the dimensions of the input image: + // + if (SUCCEEDED(hr)) + { + *ppOutputStream = NULL; + + lImageWidth = pInputImage->GetWidth(); + lImageHeight = pInputImage->GetHeight(); + lBitDepth = GetPixelFormatSize(pInputImage->GetPixelFormat()); + + if ((lImageWidth > 0) && (lImageHeight > 0) && (lBitDepth > 0)) + { + lOutputBPL = BytesPerLine(lImageWidth, lBitDepth); + + WIAS_TRACE((g_hInst, "Input image is %u x %u pixels, %u bpp, %u BPL (estimated) on output", + lImageWidth, lImageHeight, lBitDepth, lOutputBPL)); + } + else + { + hr = E_FAIL; + WIAEX_ERROR((g_hInst, "Incorrect image dimensions reported by GDI+ (%d x %d pixels, %d bpp), hr = 0x%08X", + lImageWidth, lImageHeight, lBitDepth, hr)); + } + } + + // + // Retrieve the GDI+ encoder necessary to convert the input image to a DIB: + // + if (SUCCEEDED(hr)) + { + hr = _GetEncoderCLSID(GDIPLUS_BMP_ENCODER, &clsidBmpEncoder); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "The GDI+ %ws encoder appears to be missing or improperly installed, hr = 0x%08X", + GDIPLUS_BMP_ENCODER, hr)); + } + } + + // + // Create the output stream in global memory: + // + if (SUCCEEDED(hr)) + { + hr = CreateStreamOnHGlobal(NULL, TRUE, ppOutputStream); + if (SUCCEEDED(hr) && (!(*ppOutputStream))) + { + hr = E_FAIL; + } + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "CreateStreamOnHGlobal failed, hr = 0x%08X", hr)); + } + } + + // + // Convert and save the image stored in the Image object to the output stream as a DIB: + // + if (SUCCEEDED(hr)) + { + hr = GDISTATUS_TO_HRESULT(pInputImage->Save(*ppOutputStream, &clsidBmpEncoder)); + if (FAILED(hr)) + { + WIAEX_ERROR((g_hInst, "Image::Save(%ws) failed, hr = 0x%08X", GDIPLUS_BMP_ENCODER, hr)); + } + } + + if (FAILED(hr)) + { + if (ppOutputStream && *ppOutputStream) + { + (*ppOutputStream)->Release(); + *ppOutputStream = NULL; + } + } + + if (SUCCEEDED(hr)) + { + if (plImageWidth) + { + *plImageWidth = lImageWidth; + } + if (plImageHeight) + { + *plImageHeight = lImageHeight; + } + if (plOutputImageBPL) + { + *plOutputImageBPL = lOutputBPL; + } + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} + +/**************************************************************************\ +* +* Converts a 8-bpp grayscale or 24-bpp RGB color DIB to a WIA Raw image. +* +* Parameters: +* +* ppInputStream - input stream containing the DIB to be converted +* ppOutputStream - returns a new global memory IStream containing the +* converted Raw image file (must be released by caller) +* +* Remarks: +* +* The current form of this function for simplicty supports only 8-bpp +* Grayscale and 24-bpp RGB color images. Palettes are not supported. +* +* The caller is responsible to release the returned IStream object to +* free the memory after successful execution of this function. +* +* Return Value: +* +* S_OK if successful, an error HRESULT otherwise +* +\**************************************************************************/ + +HRESULT +ConvertDibToRaw( + _In_ IStream *pInputStream, + _Out_ IStream **ppOutputStream) +{ + HRESULT hr = S_OK; + LARGE_INTEGER liOffset = {}; + WIA_RAW_HEADER wiaRawHeader = {}; + BYTE bGrayPalette[256] = {}; + BITMAPINFOHEADER bih = {}; + ULONG ulDataSize = 0; + ULONG ulDataWritten = 0; + ULONG ulPaletteSize = 0; + + WIAEX_TRACE_BEGIN; + + if ((!pInputStream) || (!ppOutputStream)) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Invalid parameter, hr = 0x%08.8X", hr)); + } + else + { + *ppOutputStream = NULL; + } + + liOffset.LowPart = sizeof(BITMAPFILEHEADER); + hr = pInputStream->Seek(liOffset, STREAM_SEEK_SET, NULL); + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "IStream::Seek(%u, STREAM_SEEK_SET, NULL) failed, hr = 0x%08X", liOffset.LowPart, hr)); + } + + if (S_OK == hr) + { + // + // Extract the DIB header from the input stream: + // + hr = pInputStream->Read((void *)&bih, sizeof(bih), &ulDataSize); + if ((S_OK == hr) && (ulDataSize != sizeof(bih))) + { + hr = E_FAIL; + WIAEX_ERROR((g_hInst, "Expected to read %u bytes for the DIB header, got %u bytes, hr = 0x%08X", + sizeof(bih), ulDataSize, hr)); + } + + // + // Validate the input DIB and fill in the output Raw header: + // + if (S_OK == hr) + { + if ((bih.biBitCount != 24) && (bih.biBitCount != 8)) + { + hr = E_INVALIDARG; + WIAEX_ERROR((g_hInst, "Test image must be either 8-bpp Grayscale or 24-bpp RGB Color, hr = 0x%08X", + sizeof(bih), ulDataSize, hr)); + } + else + { + const char szRawSignature[] = "WRAW"; + memcpy(&wiaRawHeader.Tag, szRawSignature, sizeof(DWORD)); + + wiaRawHeader.Version = 0x00010000; + wiaRawHeader.HeaderSize = sizeof(wiaRawHeader); + + wiaRawHeader.XExtent = bih.biWidth; + wiaRawHeader.YExtent = bih.biHeight; + wiaRawHeader.LineOrder = (bih.biHeight < 0) ? WIA_LINE_ORDER_TOP_TO_BOTTOM : WIA_LINE_ORDER_BOTTOM_TO_TOP; + wiaRawHeader.BitsPerPixel = bih.biBitCount; + wiaRawHeader.BytesPerLine = BytesPerLine(bih.biWidth, bih.biBitCount); + wiaRawHeader.ChannelsPerPixel = (8 == bih.biBitCount) ? 1 : 3; + wiaRawHeader.DataType = (8 == bih.biBitCount) ? WIA_DATA_GRAYSCALE : WIA_DATA_RAW_BGR; + wiaRawHeader.BitsPerChannel[0] = 8; + wiaRawHeader.BitsPerChannel[1] = (8 == bih.biBitCount) ? 0 : 8; + wiaRawHeader.BitsPerChannel[2] = (8 == bih.biBitCount) ? 0 : 8; + wiaRawHeader.Compression = WIA_COMPRESSION_NONE; + wiaRawHeader.PhotometricInterp = WIA_PHOTO_WHITE_1; + + // + // The scan resolution is fixed for this sample driver: + // + wiaRawHeader.XRes = OPTICAL_RESOLUTION; + wiaRawHeader.YRes = OPTICAL_RESOLUTION; + + ulDataSize = wiaRawHeader.BytesPerLine * wiaRawHeader.YExtent; + ulPaletteSize = (8 == bih.biBitCount) ? (256 * sizeof(BYTE)) : 0; + + wiaRawHeader.RawDataSize = ulDataSize; + wiaRawHeader.RawDataOffset = ulPaletteSize; + wiaRawHeader.PaletteOffset = 0; + wiaRawHeader.PaletteSize = ulPaletteSize; + + // + // For 8-bpp Grayscale data prepare a standard grayscale palette with entries sorted + // in increasing or decreasing order depending on the photometric interpretation: + // + if (8 == bih.biBitCount) + { + for (UINT i = 0; i < 256; i++) + { + bGrayPalette[i] = (WIA_PHOTO_WHITE_1 == wiaRawHeader.PhotometricInterp) ? (BYTE)i : (255 - (BYTE)i); + } + } + + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.Version = 0x%08X", wiaRawHeader.Version)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.HeaderSize = %u bytes", wiaRawHeader.HeaderSize)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.XExtent = %u pixels", wiaRawHeader.XExtent)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.YExtent = %u pixels", wiaRawHeader.YExtent)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.LineOrder = %u", wiaRawHeader.LineOrder)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.BitsPerPixel = %u bpp", wiaRawHeader.BitsPerPixel)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.BytesPerLine = %u BPL", wiaRawHeader.BytesPerLine)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.ChannelsPerPixel = %u", wiaRawHeader.ChannelsPerPixel)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.DataType = %u", wiaRawHeader.DataType)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.BitsPerChannel[0] = %u bps", wiaRawHeader.BitsPerChannel[0])); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.BitsPerChannel[1] = %u bps", wiaRawHeader.BitsPerChannel[1])); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.BitsPerChannel[2] = %u bps", wiaRawHeader.BitsPerChannel[2])); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.Compression = %u", wiaRawHeader.Compression)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.PhotometricInterp = %u", wiaRawHeader.PhotometricInterp)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.XRes = %u DPI", wiaRawHeader.XRes)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.YRes = %u DPI", wiaRawHeader.YRes)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.RawDataOffset = %u bytes", wiaRawHeader.RawDataOffset)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.RawDataSize = %u bytes", wiaRawHeader.RawDataSize)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.PaletteOffset = %u bytes", wiaRawHeader.PaletteOffset)); + WIAS_TRACE((g_hInst, "WIA_RAW_HEADER.PaletteSize = %u bytes", wiaRawHeader.PaletteSize)); + } + } + else + { + WIAEX_ERROR((g_hInst, "Failed to read the DIB header for the test image, hr = 0x%08X", hr)); + } + + // + // If there is a grayscale palette, jump the input stream pointer past it: + // + if ((S_OK == hr) && (8 == bih.biBitCount)) + { + liOffset.LowPart = 256 * sizeof(RGBQUAD); + hr = pInputStream->Seek(liOffset, STREAM_SEEK_CUR, NULL); + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "IStream::Seek(%u, STREAM_SEEK_SET, NULL) failed, hr = 0x%08X", liOffset.LowPart, hr)); + } + } + + // + // Create the output stream in memory: + // + if (S_OK == hr) + { + hr = CreateStreamOnHGlobal(NULL, TRUE, ppOutputStream); + if (SUCCEEDED(hr) && (!(*ppOutputStream))) + { + hr = E_FAIL; + } + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "CreateStreamOnHGlobal failed, hr = 0x%08X", hr)); + } + } + + // + // Write the Raw header to the output stream: + // + if (S_OK == hr) + { + hr = (*ppOutputStream)->Write(&wiaRawHeader, sizeof(wiaRawHeader), &ulDataWritten); + if (SUCCEEDED(hr) && (sizeof(wiaRawHeader) != ulDataWritten)) + { + hr = E_FAIL; + WIAEX_ERROR((g_hInst, "Expected to write %u bytes for the raw header, wrote %u bytes, hr = 0x%08X", + sizeof(wiaRawHeader), ulDataWritten, hr)); + } + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "IStream::Write(%u bytes) failed, hr = 0x%08X", sizeof(wiaRawHeader), hr)); + } + } + + // + // Write the palette (if one) to the output stream: + // + if ((S_OK == hr) && (8 == bih.biBitCount)) + { + hr = (*ppOutputStream)->Write(&bGrayPalette[0], ulPaletteSize, &ulDataWritten); + if (SUCCEEDED(hr) && (ulPaletteSize != ulDataWritten)) + { + hr = E_FAIL; + WIAEX_ERROR((g_hInst, "Expected to write %u bytes for the raw palette, wrote %u bytes, hr = 0x%08X", + ulPaletteSize, ulDataWritten, hr)); + } + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "IStream::Write(%u bytes) failed, hr = 0x%08X", ulPaletteSize, hr)); + } + } + + // + // Write the Raw image data to the output stream: + // + if (S_OK == hr) + { + ULARGE_INTEGER uliDataSize = {}, uliRead = {}, uliWritten = {}; + + uliDataSize.LowPart = ulDataSize; + + hr = pInputStream->CopyTo(*ppOutputStream, uliDataSize, &uliRead, &uliWritten); + if ((S_OK == hr) && ((ulDataSize != uliRead.LowPart) || (ulDataSize != uliWritten.LowPart))) + { + hr = E_FAIL; + WIAEX_ERROR((g_hInst, "Expected to stream copy %u bytes for the raw image data, copied %u bytes, hr = 0x%08X", + ulDataSize, uliWritten.LowPart, hr)); + } + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "IStream::CopyTo(%u bytes) failed, hr = 0x%08X", ulDataSize, hr)); + } + } + + // + // Reset the output stream seek pointer at the beginning of the stream: + // + if (S_OK == hr) + { + liOffset.LowPart = 0; + hr = (*ppOutputStream)->Seek(liOffset, STREAM_SEEK_SET, NULL); + if (S_OK != hr) + { + WIAEX_ERROR((g_hInst, "IStream::Seek(0, STREAM_SEEK_SET, NULL) failed, hr = 0x%08X", hr)); + } + } + } + + if ((S_OK != hr) && ppOutputStream && *ppOutputStream) + { + (*ppOutputStream)->Release(); + *ppOutputStream = NULL; + } + + WIAEX_TRACE_FUNC_HR; + + return hr; +} |
