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

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

戻る


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

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <stdlib.h>
#include <stdio.h>
#include <tiffio.h>

BOOL IsDIBOpaque(HBITMAP hbm)
{
    DWORD cdw;
    BYTE *pb;
    BITMAP bm;
    GetObject(hbm, sizeof(BITMAP), &bm);
    if (bm.bmBitsPixel <= 24)
        return TRUE;
    cdw = bm.bmWidth * bm.bmHeight;
    pb = (BYTE *)bm.bmBits;
    while(cdw--)
    {
        pb++; pb++; pb++;
        if (*pb++ != 0xFF)
            return FALSE;
    }
    return TRUE;
}

BOOL SaveBitmapAsTiff(LPCSTR pszFileName, HBITMAP hbm)
{
    BITMAP bm;
    BOOL no_alpha;
    TIFF *tif;
    BITMAPINFO bi;
    LONG widthbytes;
    BYTE *pbBits, *pb;
    INT c, y;
    BOOL f;
    HDC hdc;

    if (!GetObject(hbm, sizeof(BITMAP), &bm))
        return FALSE;

    ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
    bi.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
    bi.bmiHeader.biWidth    = bm.bmWidth;
    bi.bmiHeader.biHeight   = bm.bmHeight;
    bi.bmiHeader.biPlanes   = 1;
    
    no_alpha = (bm.bmBitsPixel <= 24 || IsDIBOpaque(hbm));
    bi.bmiHeader.biBitCount = no_alpha ? 24 : 32;
#define WIDTHBYTES(i) (((i) + 31) / 32 * 4)
    widthbytes = WIDTHBYTES(bm.bmWidth * bi.bmiHeader.biBitCount);
    pbBits = (BYTE *)malloc(widthbytes * bm.bmHeight);
    if (pbBits == NULL)
        return FALSE;

    hdc = CreateCompatibleDC(NULL);
    if (!GetDIBits(hdc, hbm, 0, bm.bmHeight, pbBits, &bi, DIB_RGB_COLORS))
    {
        free(pbBits);
        DeleteDC(hdc);
        return FALSE;
    }
    DeleteDC(hdc);

    tif = TIFFOpen(pszFileName, "w");
    if (tif == NULL)
    {
        free(pbBits);
        return FALSE;
    }

    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, bm.bmWidth);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, bm.bmHeight);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, no_alpha ? 3 : 4);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    TIFFSetField(tif, TIFFTAG_SOFTWARE, "katayama_hirofumi_mz's software");
    f = TRUE;
    for(y = 0; y < bm.bmHeight; y++)
    {
        pb = &pbBits[(bm.bmHeight - 1 - y) * widthbytes];
        c = bm.bmWidth;
        if (no_alpha)
        {
            BYTE b;
            while(c--)
            {
                b = pb[2];
                pb[2] = *pb;
                *pb = b;
                pb++; pb++; pb++;
            }
        }
        else
        {
            BYTE b;
            while(c--)
            {
                b = pb[2];
                pb[2] = *pb;
                *pb = b;
                pb++; pb++; pb++; pb++;
            }
        }
        if (TIFFWriteScanline(tif, 
            &pbBits[(bm.bmHeight - 1 - y) * widthbytes], y, 0) < 0)
        {
            f = FALSE;
            break;
        }
    }
    TIFFClose(tif);

    if (!f)
        DeleteFile(pszFileName);

    free(pbBits);
    return f;
}

#ifdef UNITTEST
int main(int argc, char **argv)
{
    HBITMAP hbm;
    WIN32_FIND_DATA find;
    HANDLE hFind;
    
    hFind = FindFirstFile("*.bmp", &find);
    if (hFind != INVALID_HANDLE_VALUE)
    {
        do 
        {
            hbm = (HBITMAP)LoadImage(NULL, find.cFileName, IMAGE_BITMAP,
                0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
            printf("%s\n", find.cFileName);
            lstrcat(find.cFileName, ".tif");
            SaveBitmapAsTiff(find.cFileName, hbm);
        } while(FindNextFile(hFind, &find));
        FindClose(hFind);
    }
    return 0;
}
#endif  /* def UNITTEST */

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

ソース: savetiff.zip


戻る

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

inserted by FC2 system