C++ 如何使用Win32 Imaging API(Windows Mobile 6+;)将HBITMAP另存为JPG?

C++ 如何使用Win32 Imaging API(Windows Mobile 6+;)将HBITMAP另存为JPG?,c++,visual-c++,windows-mobile,windows-mobile-6,windows-mobile-6.5,C++,Visual C++,Windows Mobile,Windows Mobile 6,Windows Mobile 6.5,我已经创建了将窗口截图保存到文件的程序。它适用于PNG和BMP,但不适用于JPG(和GIF)。 以下是捕获HBITMAP的代码: HBITMAP Signature::getScreenHBITMAP() { // get screen rectangle RECT windowRect; GetWindowRect(getMainWnd(), &windowRect); // bitmap dimensions int bitmap_dx = windowRect.right

我已经创建了将窗口截图保存到文件的程序。它适用于PNG和BMP,但不适用于JPG(和GIF)。 以下是捕获HBITMAP的代码:

HBITMAP Signature::getScreenHBITMAP() {
// get screen rectangle 
RECT windowRect; 
GetWindowRect(getMainWnd(), &windowRect); 

// bitmap dimensions 
int bitmap_dx = windowRect.right - windowRect.left; 
int bitmap_dy = windowRect.bottom - windowRect.top; 

// create bitmap info header 
BITMAPINFOHEADER infoHeader; 
infoHeader.biSize          = sizeof(infoHeader); 
infoHeader.biWidth         = bitmap_dx; 
infoHeader.biHeight        = bitmap_dy; 
infoHeader.biPlanes        = 1; 
infoHeader.biBitCount      = 24;
infoHeader.biCompression   = BI_RGB; 
infoHeader.biSizeImage     = 0;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed       = 0;
infoHeader.biClrImportant  = 0;

// dibsection information 
BITMAPINFO info; 
info.bmiHeader = infoHeader; 
HDC winDC = GetWindowDC(getMainWnd()); 
HDC memDC = CreateCompatibleDC(winDC); 
BYTE* memory = 0; 
HBITMAP bitmap = CreateDIBSection(winDC, &info, DIB_RGB_COLORS, (void**)&memory, 0, 0); 
SelectObject(memDC, bitmap); 
// Copies screen upside down (as it is already upside down) - if need normal layout, change to BitBlt function call
StretchBlt(memDC, 0, 0, bitmap_dx, bitmap_dy, winDC, 0, bitmap_dy, bitmap_dx, bitmap_dy * -1, SRCCOPY); 
DeleteDC(memDC); 
ReleaseDC(getMainWnd(), winDC); 

return bitmap;
}
下面是图像保存的代码:

HRESULT Imaging_SaveToFile(HBITMAP handle, LPTSTR filename, LPCTSTR format){
HRESULT res;

res = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if ((res == S_OK) || (res == S_FALSE)) {
    IImagingFactory* factory=NULL;
    if (CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void**)&factory) == S_OK) {
        UINT count;
        ImageCodecInfo* imageCodecInfo=NULL;
        if (factory->GetInstalledEncoders(&count, &imageCodecInfo) == S_OK) {
            // Get the particular encoder to use
            LPTSTR formatString;
            if (wcscmp(format, L"png") == 0) {
                formatString = _T("image/png");
            } else if (wcscmp(format, L"jpg") == 0) {
                formatString = _T("image/jpeg");
            } else if (wcscmp(format, L"gif") == 0) {
                formatString = _T("image/gif");
            } else if (wcscmp(format, L"bmp") == 0) {
                formatString = _T("image/bmp");
            } else {
                CoUninitialize();
                return S_FALSE;
            }
            CLSID encoderClassId;
            if (count == 0) {
                CoUninitialize();
                return S_FALSE;
            }
            for(int i=0; i < (int)count; i++) {
                if (wcscmp(imageCodecInfo[i].MimeType, formatString) == 0) {
                    encoderClassId= imageCodecInfo[i].Clsid;
                    free(imageCodecInfo);
                    break;
                } else {
                    continue;
                }
                CoUninitialize();
                return S_FALSE;
            } 
            IImageEncoder* imageEncoder=NULL;
            if (factory->CreateImageEncoderToFile(&encoderClassId, filename, &imageEncoder) == S_OK) {
                IImageSink* imageSink = NULL;
                res = imageEncoder->GetEncodeSink(&imageSink);
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }
                BITMAP bm;
                GetObject (handle, sizeof(BITMAP), &bm);

                ImageInfo* imageInfo = new ImageInfo();
                imageInfo->Width = bm.bmWidth;
                imageInfo->Height = bm.bmHeight;
                imageInfo->RawDataFormat = IMGFMT_MEMORYBMP; //ImageFormatMemoryBMP;
                imageInfo->Flags |= SinkFlagsTopDown | SinkFlagsFullWidth;
                // Get pixel format from hBitmap
                PixelFormatID pixelFormat;
                int numColors = 0;
                switch (bm.bmBitsPixel) {
                    case 1: {
                        pixelFormat = PixelFormat1bppIndexed;
                        numColors = 1;
                        break;
                    }
                    case 4: {
                        pixelFormat = PixelFormat4bppIndexed;
                        numColors = 16;
                        break;
                    }
                    case 8: {
                        pixelFormat = PixelFormat8bppIndexed;
                        numColors = 256;
                        break;
                    }
                    case 24: {
                        pixelFormat = PixelFormat24bppRGB;
                        break;
                    }
                    default: {
                        pixelFormat = PixelFormat32bppARGB;
                        numColors = 3; // according to MSDN 16 and 32 bpp numColors should be 3
                        break;
                    }
                }
                imageInfo->PixelFormat = pixelFormat;
                if (pixelFormat == PixelFormat32bppARGB) imageInfo->Flags |= SinkFlagsHasAlpha;
                res = imageSink->BeginSink(imageInfo, NULL);
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }
                ColorPalette* palette = NULL;
                if (numColors > 0) {
                    palette = (ColorPalette*)malloc(sizeof(ColorPalette) + (numColors - 1) * sizeof(ARGB));
                    palette->Count = numColors;
                    for (int i=0; i<numColors; i++) {
                        int rgb = i*64;
                        int red = rgb & 0x00FF;
                        int green = (rgb >> 8) & 0x00FF;
                        int blue = (rgb >> 16) & 0x00FF;
                        palette->Entries[i] = MAKEARGB(0, red, green, blue);
                    }
                } else {
                    palette = (ColorPalette*)malloc(sizeof(ColorPalette));
                    palette->Count = 0;
                    if (pixelFormat == PixelFormat32bppARGB) palette->Flags = PALFLAG_HASALPHA;
                }
                res = imageSink->SetPalette(palette);
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }

                BitmapData* bmData = new BitmapData();
                bmData->Height = bm.bmHeight;
                bmData->Width = bm.bmWidth;
                bmData->Scan0 = bm.bmBits;
                bmData->PixelFormat = pixelFormat;

                UINT bitsPerLine = imageInfo->Width * bm.bmBitsPixel;
                UINT bitAlignment = sizeof(LONG) * 8;
                UINT bitStride = bitAlignment * (bitsPerLine / bitAlignment);   // The image buffer is always padded to LONG boundaries
                if ((bitsPerLine % bitAlignment) != 0) bitStride += bitAlignment; // Add a bit more for the leftover values
                bmData->Stride = (bitStride / 8);

                RECT rect;
                rect.top = 0;
                rect.bottom = bm.bmHeight;
                rect.left = 0;
                rect.right = bm.bmWidth;

                res = imageSink->PushPixelData(&rect, bmData, TRUE);
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }

                res = imageSink->EndSink(S_OK);
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }
                imageSink->Release();
                res = imageEncoder->TerminateEncoder();
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }
            }
        }
    }
    CoUninitialize();
} else {
    return res;
}

return res;
}
HRESULT成像\u保存文件(HBITMAP句柄,LPTSTR文件名,LPCTSTR格式){
HRESULT res;
res=coinitializex(空,COINIT\u多线程);
if((res==S_OK)| |(res==S_FALSE)){
IImagingFactory*工厂=空;
if(CoCreateInstance(CLSID_ImagingFactory,NULL,CLSCTX_INPROC_服务器,IID_IImagingFactory,(void**)和factory)==S_OK){
单位计数;
ImageCodecInfo*ImageCodecInfo=NULL;
如果(factory->GetInstalledEncoders(&count,&ImageCodeInfo)==S\U OK){
//获取要使用的特定编码器
LPTSTR格式字符串;
如果(wcscmp(格式,L“png”)==0){
formatString=_T(“图像/png”);
}else if(wcscmp(格式,L“jpg”)==0){
formatString=_T(“图像/jpeg”);
}else if(wcscmp(格式,L“gif”)==0){
formatString=_T(“图像/gif”);
}else if(wcscmp(格式,L“bmp”)==0){
formatString=_T(“图像/bmp”);
}否则{
coninitialize();
返回S_FALSE;
}
CLSID编码分类;
如果(计数=0){
coninitialize();
返回S_FALSE;
}
对于(int i=0;i<(int)计数;i++){
if(wcscmp(imageCodecInfo[i].MimeType,formatString)==0){
encoderClassId=imageCodecInfo[i].Clsid;
免费(imageCodecInfo);
打破
}否则{
继续;
}
coninitialize();
返回S_FALSE;
} 
IImageEncoder*imageEncoder=NULL;
如果(工厂->CreateImageEncoderToFile(&encoderClassId、文件名和imageEncoder)==S_OK){
IImageSink*imageSink=NULL;
res=imageEncoder->GetEncodeSink(&imageSink);
如果(res!=S_OK){
coninitialize();
返回res;
}
位图bm;
GetObject(句柄、sizeof(位图)和bm);
ImageInfo*ImageInfo=新的ImageInfo();
imageInfo->Width=bm.bmWidth;
imageInfo->Height=bm.bmHeight;
imageInfo->RawDataFormat=IMGFMT_MEMORYBMP;//ImageFormatMemoryBMP;
imageInfo->Flags |=SinkFlagsStopDown | SinkFlagsFullWidth;
//从hBitmap获取像素格式
像素格式;像素格式;
int numColors=0;
开关(bm.bmBitsPixel){
案例1:{
pixelFormat=PixelFormat1Bppined;
numColors=1;
打破
}
案例4:{
像素格式=像素格式4bppindexed;
numColors=16;
打破
}
案例8:{
pixelFormat=PixelFormat8Bppined;
numColors=256;
打破
}
案例24:{
像素格式=像素格式24bpprgb;
打破
}
默认值:{
像素格式=像素格式32bppargb;
numColors=3;//根据MSDN 16和32 bpp,numColors应为3
打破
}
}
imageInfo->PixelFormat=PixelFormat;
如果(pixelFormat==PixelFormat32bppARGB)imageInfo->Flags |=SinkFlagsHasAlpha;
res=imageSink->BeginSink(imagesinfo,NULL);
如果(res!=S_OK){
coninitialize();
返回res;
}
ColorPalette*palette=NULL;
如果(numColors>0){
调色板=(颜色调色板*)malloc(sizeof(颜色调色板)+(numColors-1)*sizeof(ARGB));
调色板->计数=numColors;
对于(int i=0;i>8)&0x00FF;
蓝色整数=(rgb>>16)和0x00FF;
调色板->条目[i]=MAKEARGB(0,红色,绿色,蓝色);
}
}否则{
调色板=(调色板*)malloc(色板大小);
调色板->计数=0;
如果(pixelFormat==PixelFormat32bppARGB)调色板->标志=PALFLAG\u HASALPHA;
}
res=图像接收器->设置调色板(调色板);
如果(res!=S_OK){
coninitialize();
返回res;
}
BitmapData*bmData=新的BitmapData();
bmData->Height=bm.bmHeight;
bmData->Width=bm.bmWidth;
bmData->Scan0=bm.bmBits;
bmData->PixelFormat=PixelFormat;
UINT bitsPerLine=imageInfo->Width*bm.bmbitspexel;
UINT位对齐=大小(长)*8;
UINT bitStride=bitAlignment*(bitsPerLine/bitAlignment);//图像缓冲区始终填充到长边界
if((bitsPerLine%bitAlignment)!=0)bitStride+=bitAlignment;//为剩余值添加多一点
bmData->Stride=(bitStride/8);
RECT-RECT;
rect.top=0;
rect.bottom=bm.bmHeight;
rect.left=0;
rect.right=bm.bmWidth;
res=imageSink->PushPixelData(&rect,bmData,TRUE);
如果(res!=S_OK){
协商初始化(
HRESULT Imaging_SaveToFile(HBITMAP handle, LPTSTR filename, LPCTSTR format){
HRESULT res;

res = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if ((res == S_OK) || (res == S_FALSE)) {
    IImagingFactory* factory=NULL;
    if (CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void**)&factory) == S_OK) {
        UINT count;
        ImageCodecInfo* imageCodecInfo=NULL;
        if (factory->GetInstalledEncoders(&count, &imageCodecInfo) == S_OK) {
            // Get the particular encoder to use
            LPTSTR formatString;
            if (wcscmp(format, L"png") == 0) {
                formatString = _T("image/png");
            } else if (wcscmp(format, L"jpg") == 0) {
                formatString = _T("image/jpeg");
            } else if (wcscmp(format, L"gif") == 0) {
                formatString = _T("image/gif");
            } else if (wcscmp(format, L"bmp") == 0) {
                formatString = _T("image/bmp");
            } else {
                CoUninitialize();
                return S_FALSE;
            }
            CLSID encoderClassId;
            if (count == 0) {
                CoUninitialize();
                return S_FALSE;
            }
            for(int i=0; i < (int)count; i++) {
                if (wcscmp(imageCodecInfo[i].MimeType, formatString) == 0) {
                    encoderClassId= imageCodecInfo[i].Clsid;
                    free(imageCodecInfo);
                    break;
                } else {
                    continue;
                }
                CoUninitialize();
                return S_FALSE;
            } 
            IImageEncoder* imageEncoder=NULL;
            if (factory->CreateImageEncoderToFile(&encoderClassId, filename, &imageEncoder) == S_OK) {
                IImageSink* imageSink = NULL;
                res = imageEncoder->GetEncodeSink(&imageSink);

                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }

                BITMAP bm;
                GetObject (handle, sizeof(BITMAP), &bm);
                PixelFormatID pixelFormat;
                switch (bm.bmBitsPixel) {
                    case 1: {
                        pixelFormat = PixelFormat1bppIndexed;
                        break;
                    }
                    case 4: {
                        pixelFormat = PixelFormat4bppIndexed;
                        break;
                    }
                    case 8: {
                        pixelFormat = PixelFormat8bppIndexed;
                        break;
                    }
                    case 24: {
                        pixelFormat = PixelFormat24bppRGB;
                        break;
                    }
                    default: {
                        pixelFormat = PixelFormat32bppARGB;
                        break;
                    }
                }

                BitmapData* bmData = new BitmapData();
                bmData->Height = bm.bmHeight;
                bmData->Width = bm.bmWidth;
                bmData->Scan0 = bm.bmBits;
                bmData->PixelFormat = pixelFormat;

                UINT bitsPerLine = bm.bmWidth * bm.bmBitsPixel;
                UINT bitAlignment = sizeof(LONG) * 8;
                UINT bitStride = bitAlignment * (bitsPerLine / bitAlignment);   // The image buffer is always padded to LONG boundaries
                if ((bitsPerLine % bitAlignment) != 0) bitStride += bitAlignment; // Add a bit more for the leftover values
                bmData->Stride = (bitStride / 8);

                IBitmapImage* pBitmap;
                factory->CreateBitmapFromBuffer(bmData, &pBitmap);
                IImage* pImage;
                pBitmap->QueryInterface(IID_IImage, (void**)&pImage); 
                res = pImage->PushIntoSink(imageSink);
                if (res != S_OK) {
                    CoUninitialize();
                    return res;
                }

                pBitmap->Release();
                pImage->Release();
                imageSink->Release();
                imageEncoder->TerminateEncoder();
                imageEncoder->Release();
            }
        }
    }
    CoUninitialize();
} else {
    return res;
}

return res;
}