ソフトウェア開発 Win32プログラミング

ビットマップをJPEG画像として保存する

戻る


ビットマップをJPEG画像として保存したい場合は、次のような コードを使うとよい。

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
 
#include <stdio.h>
 
#ifdef __cplusplus
extern "C"
{
#endif
#define XMD_H
#include <jpeglib.h>
#include <jerror.h>
#ifdef __cplusplus
}
#endif
 
#pragma comment(lib, "libjpeg.lib")

BOOL SaveBitmapAsJpeg(LPCSTR pszFileName, HBITMAP hbm, INT quality, BOOL progression)
{
    FILE *fp;
    BITMAP bm;
    struct jpeg_compress_struct comp;
    struct jpeg_error_mgr jerr;
    JSAMPLE * image_buffer;
    BITMAPINFO bi;
    HDC hDC, hMemDC;
    LPBYTE pbBits;
    INT nWidthBytes;
    DWORD cbBits;
    BOOL f;
 
    if (GetObject(hbm, sizeof(BITMAP), &bm) != sizeof(BITMAP))
        return FALSE;
 
    fp = fopen(pszFileName, "wb");
    if (fp == NULL)
        return FALSE;
    
    comp.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&comp);
    jpeg_stdio_dest(&comp, fp);
    
    comp.image_width  = bm.bmWidth;
    comp.image_height = bm.bmHeight;
    comp.input_components = 3;
    comp.in_color_space = JCS_RGB;
    jpeg_set_defaults(&comp);
    jpeg_set_quality(&comp, quality, TRUE);
    if (progression)
        jpeg_simple_progression(&comp);
 
    jpeg_start_compress(&comp, TRUE);
    ZeroMemory(&bi, sizeof(BITMAPINFOHEADER));
    bi.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
    bi.bmiHeader.biWidth    = bm.bmWidth;
    bi.bmiHeader.biHeight   = bm.bmHeight;
    bi.bmiHeader.biPlanes   = 1;
    bi.bmiHeader.biBitCount = 24;
 
    f = FALSE;
#define WIDTHBYTES(i) (((i) + 31) / 32 * 4)
    nWidthBytes = WIDTHBYTES(bm.bmWidth * 24);
    cbBits = nWidthBytes * bm.bmHeight;
    pbBits = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, cbBits);
    if (pbBits != NULL)
    {
        image_buffer = (JSAMPLE *)HeapAlloc(GetProcessHeap(), 0, nWidthBytes);
        if (image_buffer != NULL)
        {
            hDC = GetDC(NULL);
            if (hDC != NULL)
            {
                hMemDC = CreateCompatibleDC(hDC);
                if (hMemDC != NULL)
                {
                    f = GetDIBits(hMemDC, hbm, 0, bm.bmHeight, pbBits, 
                                  (BITMAPINFO*)&bi, DIB_RGB_COLORS);
                    DeleteDC(hMemDC);
                }
                ReleaseDC(NULL, hDC);
            }
            if (f)
            {
                INT x, y;
                LPBYTE src, dest;
                for(y = 0; y < bm.bmHeight; y++)
                {
                    dest = image_buffer;
                    src = &pbBits[(bm.bmHeight - y - 1) * nWidthBytes];
                    for(x = 0; x < bm.bmWidth; x++)
                    {
                        *dest++ = *src++;
                        *dest++ = *src++;
                        *dest++ = *src++;
                    }
                    jpeg_write_scanlines(&comp, &image_buffer, 1);
                }
            }
            HeapFree(GetProcessHeap(), 0, image_buffer);
        }
        HeapFree(GetProcessHeap(), 0, pbBits);
    }
 
    jpeg_finish_compress(&comp);
    jpeg_destroy_compress(&comp);
 
    fclose(fp);
    if (!f)
    {
        DeleteFile(pszFileName);
        return FALSE;
    }
    return TRUE;
}
 
#ifdef UNITTEST
HBITMAP CreateWindowBitmap(HWND hWnd)
{
    HBITMAP hbmNew;
    HDC hDC, hMemDC;
    HGDIOBJ hbmOld;
    RECT rc;
    SIZE siz;
    BITMAPINFO bi;
    VOID *pvBits;
    DWORD dwError = 0;
 
    GetWindowRect(hWnd, &rc);
    siz.cx = rc.right - rc.left;
    siz.cy = rc.bottom - rc.top;
 
    hbmNew = NULL;
    hDC = GetWindowDC(hWnd);
    if (hDC != NULL)
    {
        hMemDC = CreateCompatibleDC(hDC);
        if (hMemDC != NULL)
        {
            ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
            bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
            bi.bmiHeader.biWidth        = siz.cx;
            bi.bmiHeader.biHeight       = siz.cy;
            bi.bmiHeader.biPlanes       = 1;
            bi.bmiHeader.biBitCount     = 24;
            hbmNew = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits,
                                      NULL, 0);
            if (hbmNew != NULL)
            {
                hbmOld = SelectObject(hMemDC, hbmNew);
                BitBlt(hMemDC, 0, 0, siz.cx, siz.cy,
                       hDC, 0, 0, SRCCOPY);
                SelectObject(hMemDC, hbmOld);
            }
            else
                dwError = GetLastError();
            DeleteDC(hMemDC);
        }
        else
            dwError = GetLastError();
        ReleaseDC(hWnd, hDC);
        SetLastError(dwError);
    }
 
    return hbmNew;
}
 
int main(void)
{
    HBITMAP hbm = CreateWindowBitmap(GetDesktopWindow());
    SaveBitmapAsJpeg("30%.jpg", hbm, 30, FALSE);
    SaveBitmapAsJpeg("50%.jpg", hbm, 50, FALSE);
    SaveBitmapAsJpeg("80%.jpg", hbm, 80, FALSE);
    SaveBitmapAsJpeg("100%.jpg", hbm, 100, FALSE);
    DeleteObject(hbm);
    return 0;
}
#endif  /* def UNITTEST */

なお、このコードをコンパイルするには、libjpegライブラリが必要だ。

ソース: savejpeg.zip


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system