2004.10.06 15:05 "[Tiff] Converting DIB to Tif using libtiff", by Curt C

2004.10.09 08:00 "Re: [Tiff] Converting DIB to Tif using libtiff", by Andrey Kiselev

I was wondering if anyone knows of a general routine that will convert generic Windows DIB (given handle, etc) to a corresponding tiff file?

You can found the sample code attached. It was written for specific purpose to save the monocrome and grayscale images only, but it should give you a basic idea how to do the conversion.

Best regards,
Andrey

Andrey V. Kiselev
Home phone: +7 812 5274898 ICQ# 26871517

/******************************************************************************
 * Project:  ???
 * Purpose:  Routine to save Windows Device Dependent Bitmaps (DDB)
 *           as TIFF files.
 * Author:   Andrey Kiselev, dron@at1895.spb.edu
 *
 ******************************************************************************
 * Copyright (c) 2002, Andrey Kiselev <dron@at1895.spb.edu>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 ******************************************************************************
 */

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

/* Hack to test function without Windows development environment */

#ifndef __WIN32__

#define BYTE    unsigned char
typedef struct tagBITMAP
{
    int     bmType;
    int     bmWidth;
    int     bmHeight;
    int     bmWidthBytes;
    BYTE    bmPlanes;
    BYTE    bmBitsPixel;
    void    *bmBits;
} BITMAP;

#else

#include <windows.h>

#endif

/******************************************************************************
 *                               SaveAsTIFF()                                 *
 ******************************************************************************
 * SYNOPSIS:
 *
 * psBmp        pointer to input BITMAP structure
 * pszFilename  pointer to string which containes path to output TIFF file
 *
 * Only 1-bit (monochrome) or 8-bit (grayscale) images supported.
 * pszFilename file will be overwritten, caller responsible to check
 * if it is not desirable.
 *
 * RETURN VALUE:
 * The number of actually written scanlines returned or -1 if function fails.
 ****************************************************************************** */

int SaveAsTIFF(BITMAP *psBmp, char *pszFilename)
{
    uint32  iWidth, iHeight;
    float   fXRes, fYRes;
    uint16  iSPP, iBPP, iResUnit, iRowsPerStrip;
    int     iRow;
    TIFF    *fpOut;
    BYTE    *pbBuf;

    if (psBmp->bmWidth <= 0 || psBmp->bmHeight <= 0   ||
        (psBmp->bmBitsPixel != 1 && psBmp->bmBitsPixel != 8) ||
        psBmp->bmPlanes < 1 || psBmp->bmBits == NULL)
    {
        fprintf (stderr, "Input image has wrong dimesions.\n");
        return -1;
    }

    fpOut = TIFFOpen(pszFilename, "w");
    if (!fpOut)
    {
        fprintf (stderr, "Can't open %s for writing.\n", pszFilename);
        return -1;
    }

    iWidth = psBmp->bmWidth;
    iHeight = psBmp->bmHeight;
    iBPP = psBmp->bmBitsPixel;
    if (psBmp->bmPlanes == 1)
        iSPP = 1;
    else
        iSPP = 8;

    TIFFSetField(fpOut, TIFFTAG_IMAGEWIDTH, iWidth);
    TIFFSetField(fpOut, TIFFTAG_BITSPERSAMPLE, iBPP);
    TIFFSetField(fpOut, TIFFTAG_SAMPLESPERPIXEL, iSPP);
    TIFFSetField(fpOut, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(fpOut, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(fpOut, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

    /* It is good to set resolutions too */
    fXRes = fYRes = 100;            /* dots per resolution unit (see below) */
    iResUnit = RESUNIT_INCH;        /* or RESUNIT_CENTIMETER */
    TIFFSetField(fpOut, TIFFTAG_XRESOLUTION, fXRes);
    TIFFSetField(fpOut, TIFFTAG_YRESOLUTION, fYRes);
    TIFFSetField(fpOut, TIFFTAG_RESOLUTIONUNIT, iResUnit);

    /* Uncomment the next line if you need compression.
     * Possible options are:
     *
     * COMPRESSION_CCITTRLE        CCITT modified Huffman RLE
     * COMPRESSION_CCITTFAX3       CCITT Group 3 fax encoding
     * COMPRESSION_CCITTFAX4       CCITT Group 4 fax encoding
     * COMPRESSION_PACKBITS        Macintosh RLE
     *
     * You may try all of these with your data to choose
     * which one produces best results.
     */
    /* TIFFSetField(fpOut, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); */

    iRowsPerStrip = TIFFDefaultStripSize(fpOut, 0);
    TIFFSetField(fpOut,TIFFTAG_ROWSPERSTRIP, iRowsPerStrip);

    pbBuf = (BYTE *)psBmp->bmBits;
    for (iRow = 0; iRow < iHeight; iRow++)
    {
        if (TIFFWriteScanline(fpOut, pbBuf, iRow, 0) < 0)
        {
            fprintf(stderr, "Can't write scanline %d to file %s.\n",
                    iRow, pszFilename);
            break;
        }
        pbBuf += psBmp->bmWidthBytes;
    }

    TIFFClose(fpOut);

    return iRow; /* Number of successfuly written scanlines */
}

/* Below is the testsuite for the SavaAsTIFF() function */

BYTE bTest[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

BITMAP sTest[]=
{
    {
        0, 64, 18, 8, 1, 1, &bTest
    },
    {
        0, 8, 18, 8, 1, 8, &bTest
    },
    {
        0, 0, 0, 0, 0, 0, NULL
    }
};

int main()
{
    int     i;
    char    szName[1024];

    i = 0;
    while (sTest[i].bmBits)
    {
        sprintf(szName, "out%d.tif", i);
        if (SaveAsTIFF(&sTest[i], szName) < 0)
            fprintf(stderr, "Test %d failed!\n", i);
        else
            fprintf(stderr, "Test %d succeeded!\n", i);
        i++;
    }

    return 0;
}