diff --git a/build2/qt/HGBase/HGBase.def b/build2/qt/HGBase/HGBase.def index c8ad0e4d..5b77ac00 100644 --- a/build2/qt/HGBase/HGBase.def +++ b/build2/qt/HGBase/HGBase.def @@ -99,7 +99,11 @@ HGBase_CreateImage HGBase_CreateImageWithData HGBase_CreateImageFromData HGBase_CreateImageFromHBITMAP -HGBase_CreateImageFromDIB +HGBase_CreateDIBFile +HGBase_CreateImageFromFile +HGBase_CreateDIBStream +HGBase_DestroyStream +HGBase_CreateImageFromStream HGBase_CloneImage HGBase_DestroyImage HGBase_GetImageData diff --git a/modules/base/HGImage.cpp b/modules/base/HGImage.cpp index a9814cbb..ef94d80d 100644 --- a/modules/base/HGImage.cpp +++ b/modules/base/HGImage.cpp @@ -2,6 +2,7 @@ #include "HGInc.h" #if defined(HG_CMP_MSC) #include +#include #include #endif @@ -522,12 +523,10 @@ static HGResult LoadGdiImage(Gdiplus::Image* pImage, const HGImageRoi* roi, HGUI return ret; } - if (HGBASE_IMGTYPE_BGR == type || HGBASE_IMGTYPE_BGRA == type) + HBITMAP hBmp = NULL; + HGBase_GetHBITMAPOfImage(*image, &hBmp); + if (NULL != hBmp) { - HBITMAP hBmp = NULL; - HGBase_GetHBITMAPOfImage(*image, &hBmp); - assert(NULL != hBmp); - HDC hMem = CreateCompatibleDC(NULL); HBITMAP hOldBmp = (HBITMAP)SelectObject(hMem, hBmp); Gdiplus::Graphics graphics(hMem); @@ -539,9 +538,11 @@ static HGResult LoadGdiImage(Gdiplus::Image* pImage, const HGImageRoi* roi, HGUI } else { - HGUInt type2 = HGBASE_IMGTYPE_BGR; - if (HGBASE_IMGTYPE_RGBA == type) - type2 = HGBASE_IMGTYPE_BGRA; + HGUInt type2 = type; + if (HGBASE_IMGTYPE_RGB == type) + type2 = HGBASE_IMGTYPE_BGR; + else if (HGBASE_IMGTYPE_RGBA == type) + type2 = HGBASE_IMGTYPE_BGRA; HGImage image2 = NULL; ret = LoadGdiImage(pImage, roi, type2, origin, &image2); @@ -565,62 +566,157 @@ static HGResult LoadGdiImage(Gdiplus::Image* pImage, const HGImageRoi* roi, HGUI return ret; } -HGResult HGAPI HGBase_CreateImageFromDIB(HGLOBAL hMem, const HGImageRoi* roi, +HGResult HGAPI HGBase_CreateDIBFile(HGLOBAL hMem, const HGChar *fileName) +{ + if (NULL == hMem || NULL == fileName) + { + return HGBASE_ERR_INVALIDARG; + } + + HGResult ret = HGBASE_ERR_FAIL; + + ULONG size = (ULONG)GlobalSize(hMem); + void* pMem = GlobalLock(hMem); + if (NULL != pMem) + { + FILE *file = fopen(fileName, "wb"); + if (NULL != file) + { + BITMAPINFOHEADER* infoHeader = (BITMAPINFOHEADER*)pMem; + DWORD bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + if (infoHeader->biBitCount <= 8) + bfOffBits += ((HGUInt)(1 << infoHeader->biBitCount) * sizeof(RGBQUAD)); + + BITMAPFILEHEADER fileHeader = { 0 }; + fileHeader.bfType = 0x4D42; + fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + size; + fileHeader.bfOffBits = bfOffBits; + fwrite(&fileHeader, 1, sizeof(BITMAPFILEHEADER), file); + fwrite(pMem, 1, size, file); + + fclose(file); + ret = HGBASE_ERR_OK; + } + + GlobalUnlock(hMem); + } + + return ret; +} + +HGResult HGAPI HGBase_CreateImageFromFile(const HGChar *fileName, const HGImageRoi* roi, + HGUInt type, HGUInt origin, HGImage* image) +{ + if (NULL == fileName || NULL == image) + { + return HGBASE_ERR_INVALIDARG; + } + + HGResult ret = HGBASE_ERR_FAIL; + + ULONG_PTR nToken = 0; + Gdiplus::GdiplusStartupInput input; + Gdiplus::GdiplusStartupOutput output; + Gdiplus::GdiplusStartup(&nToken, &input, &output); + assert(0 != nToken); + + CStringW fileName2(fileName); + Gdiplus::Image *img = new Gdiplus::Image(fileName2); + Gdiplus::Status status = img->GetLastStatus(); + if (Gdiplus::Ok == status) + { + ret = LoadGdiImage(img, roi, type, origin, image); + } + + delete img; + Gdiplus::GdiplusShutdown(nToken); + nToken = 0; + + return ret; +} + +HGResult HGAPI HGBase_CreateDIBStream(HGLOBAL hMem, HGStream *stream) +{ + if (NULL == hMem || NULL == stream) + { + return HGBASE_ERR_INVALIDARG; + } + + HGResult ret = HGBASE_ERR_FAIL; + + ULONG size = (ULONG)GlobalSize(hMem); + void* pMem = GlobalLock(hMem); + if (NULL != pMem) + { + IStream* pStream = NULL; + HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); + if (SUCCEEDED(hr)) + { + ULONG writeSize = 0; + + BITMAPINFOHEADER* infoHeader = (BITMAPINFOHEADER*)pMem; + DWORD bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); + if (infoHeader->biBitCount <= 8) + bfOffBits += ((HGUInt)(1 << infoHeader->biBitCount) * sizeof(RGBQUAD)); + + BITMAPFILEHEADER fileHeader = { 0 }; + fileHeader.bfType = 0x4D42; + fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + size; + fileHeader.bfOffBits = bfOffBits; + pStream->Write(&fileHeader, sizeof(BITMAPFILEHEADER), &writeSize); + pStream->Write(pMem, size, &writeSize); + + *stream = (HGStream)pStream; + ret = HGBASE_ERR_OK; + } + + GlobalUnlock(hMem); + } + + return ret; +} + +HGResult HGAPI HGBase_DestroyStream(HGStream stream) +{ + if (NULL == stream) + { + return HGBASE_ERR_INVALIDARG; + } + + IStream* pStream = (IStream*)stream; + pStream->Release(); + return HGBASE_ERR_OK; +} + +HGResult HGAPI HGBase_CreateImageFromStream(HGStream stream, const HGImageRoi* roi, HGUInt type, HGUInt origin, HGImage* image) { - if (NULL == hMem || NULL == image) + if (NULL == stream || NULL == image) { return HGBASE_ERR_INVALIDARG; } - HGResult ret = HGBASE_ERR_FAIL; + HGResult ret = HGBASE_ERR_FAIL; - ULONG size = (ULONG)GlobalSize(hMem); - void* pMem = GlobalLock(hMem); - if (NULL != pMem) - { - IStream* pStream = NULL; - HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); - if (SUCCEEDED(hr)) - { - ULONG writeSize = 0; + ULONG_PTR nToken = 0; + Gdiplus::GdiplusStartupInput input; + Gdiplus::GdiplusStartupOutput output; + Gdiplus::GdiplusStartup(&nToken, &input, &output); + assert(0 != nToken); - BITMAPINFOHEADER* infoHeader = (BITMAPINFOHEADER*)pMem; - DWORD bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - if (infoHeader->biBitCount <= 8) - bfOffBits += ((HGUInt)(1 << infoHeader->biBitCount) * sizeof(RGBQUAD)); + IStream* pStream = (IStream*)stream; + Gdiplus::Image *img = new Gdiplus::Image(pStream); + Gdiplus::Status status = img->GetLastStatus(); + if (Gdiplus::Ok == status) + { + ret = LoadGdiImage(img, roi, type, origin, image); + } - BITMAPFILEHEADER fileHeader = { 0 }; - fileHeader.bfType = 0x4D42; - fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + size; - fileHeader.bfOffBits = bfOffBits; - pStream->Write(&fileHeader, sizeof(BITMAPFILEHEADER), &writeSize); - pStream->Write(pMem, size, &writeSize); + delete img; + Gdiplus::GdiplusShutdown(nToken); + nToken = 0; - ULONG_PTR nToken = 0; - Gdiplus::GdiplusStartupInput input; - Gdiplus::GdiplusStartupOutput output; - Gdiplus::GdiplusStartup(&nToken, &input, &output); - assert(0 != nToken); - - Gdiplus::Image *img = new Gdiplus::Image(pStream); - Gdiplus::Status status = img->GetLastStatus(); - if (Gdiplus::Ok == status) - { - ret = LoadGdiImage(img, roi, type, origin, image); - } - - delete img; - Gdiplus::GdiplusShutdown(nToken); - nToken = 0; - - pStream->Release(); - } - - GlobalUnlock(hMem); - } - - return ret; + return ret; } #endif /* HG_CMP_MSC */ diff --git a/modules/base/HGImage.h b/modules/base/HGImage.h index 50e6babe..cb4a2bde 100644 --- a/modules/base/HGImage.h +++ b/modules/base/HGImage.h @@ -8,6 +8,9 @@ #endif HG_DECLARE_HANDLE(HGImage); +#if defined(HG_CMP_MSC) +HG_DECLARE_HANDLE(HGStream); +#endif /* 1位黑白图 */ #define HGBASE_IMGTYPE_BINARY 1L @@ -120,11 +123,28 @@ HGEXPORT HGResult HGAPI HGBase_CreateImageFromData(HGByte* data, const HGImageIn HGEXPORT HGResult HGAPI HGBase_CreateImageFromHBITMAP(HBITMAP hBmp, const HGImageRoi* roi, HGUInt type, HGUInt origin, HGImage* image); -/* 从DIB内存创建新图像 +/* 创建文件 + */ +HGEXPORT HGResult HGAPI HGBase_CreateDIBFile(HGLOBAL hMem, const HGChar *fileName); + +/* 从文件加载图像 + */ +HGEXPORT HGResult HGAPI HGBase_CreateImageFromFile(const HGChar *fileName, const HGImageRoi* roi, + HGUInt type, HGUInt origin, HGImage* image); + +/* 创建DIB流 + */ +HGEXPORT HGResult HGAPI HGBase_CreateDIBStream(HGLOBAL hMem, HGStream *stream); + +/* 销毁流 + */ +HGEXPORT HGResult HGAPI HGBase_DestroyStream(HGStream stream); + +/* 从流创建新图像 * 参数: -* 1) hMem: in, DIB内存句柄 -* 2) roi: DIB内存的感兴趣区域, NULL表示整个图像区域 -* 3) type: in, 新图像的类型, 0表示自动生成和DIB内存最接近的type +* 1) stream: in, 流句柄 +* 2) roi: 流图像的感兴趣区域, NULL表示整个图像区域 +* 3) type: in, 新图像的类型, 0表示自动生成和流图像最接近的type * 4) origin: in, 新图像的数据排列方式, 必须指定 * 5) image: out,新图像句柄 * 说明: @@ -133,9 +153,9 @@ HGEXPORT HGResult HGAPI HGBase_CreateImageFromHBITMAP(HBITMAP hBmp, const HGImag * 2) 新图像的width=roi->right-roi->left; 新图像的height=roi->bottom-roi->top; 新图像的type=type; 新图像的widthStep为4字节对齐; * 新图像的origin=origin * 3) 新图像的roi为{0, 0, width, height} -* 4) 新图像的xdpi=DIB的xDPI, ydpi=DIB的yDPI +* 4) 新图像的xdpi=流图像的xDPI, ydpi=流图像的yDPI */ -HGEXPORT HGResult HGAPI HGBase_CreateImageFromDIB(HGLOBAL hMem, const HGImageRoi* roi, +HGEXPORT HGResult HGAPI HGBase_CreateImageFromStream(HGStream stream, const HGImageRoi* roi, HGUInt type, HGUInt origin, HGImage* image); #endif /* HG_CMP_MSC */ @@ -388,4 +408,4 @@ HGEXPORT HGResult HGAPI HGBase_ReverseImage(HGImage image, HGImage destImage); */ HGEXPORT HGResult HGAPI HGBase_CopyImage(HGImage image, HGImage destImage); -#endif /* __HGIMAGE_H__ */ \ No newline at end of file +#endif /* __HGIMAGE_H__ */ diff --git a/modules/twain_user/HGTwainImpl.cpp b/modules/twain_user/HGTwainImpl.cpp index f258982f..cb3813d2 100644 --- a/modules/twain_user/HGTwainImpl.cpp +++ b/modules/twain_user/HGTwainImpl.cpp @@ -1,6 +1,7 @@ #include "HGTwainImpl.hpp" #include "../base/HGInc.h" #include "../base/HGInfo.h" +#include "../base/HGUtility.h" #include "app_cfg.h" std::map HGTwainDSMImpl::m_mapWnd; @@ -964,8 +965,30 @@ HGResult HGTwainDSImpl::ImageNativeXfer(HGUInt type, HGUInt origin, HGImage* ima return HGTWAIN_ERR_FAIL; } - HGResult ret = HGBase_CreateImageFromDIB(hMem, NULL, type, origin, image); - GlobalFree(hMem); +#ifdef _WIN64 + HGStream stream = NULL; + HGResult ret = HGBase_CreateDIBStream(hMem, &stream); + GlobalFree(hMem); + if (HGBASE_ERR_OK != ret) + { + return ret; + } + + ret = HGBase_CreateImageFromStream(stream, NULL, type, origin, image); + HGBase_DestroyStream(stream); +#else + HGChar tmpFile[260]; + HGBase_GetTmpFileName("bmp", tmpFile, 260); + HGResult ret = HGBase_CreateDIBFile(hMem, tmpFile); + GlobalFree(hMem); + if (HGBASE_ERR_OK != ret) + { + return ret; + } + + ret = HGBase_CreateImageFromFile(tmpFile, NULL, type, origin, image); + HGBase_DeleteFile(tmpFile); +#endif return ret; }