• 2007-12-21

    VC下使用LibTiff处理TIFF文件[转] - [C++ study note]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://xiaojing1983.blogbus.com/logs/12425529.html

    一 TIFF简介
    IFF是Tagged Image File Format(标记图像文件格式)的缩写,这是现阶段印刷行业使用最广泛的文件格式,文件扩展名为tif或tiff.TIFF是一种比较灵活的图像格式,该格式支持单色,8,16,256色、24位真彩色、32位色、48位色等多种色彩位,同时支持rgb、cmyk以及ycbcr等多种色彩模式,支持多平台。tiff文件可以是不压缩的,文件体积较大,也可以是压缩的,支持raw、rle、lzw、jpeg、ccitt3组和4组等多种压缩方式
    TIFF规范第一版本由Aldus公司在1986年发布,到现在已经发布到第六版。
    我们这里只讨论使用libtiff对tif图进行编程,所以关于TIF的详细介绍请见Tiff Revision 6.0。
    下载网址:
    http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf
    阅读本文章之前,要求读者对BMP位图有一定的了解。

    libtiff是在UNIX下用来读写TIFF文件的一个工具软件集合,包括关于TIFF的文档,lib文件,还提供了一些小工具,比如把TIFF转成PDF或传真等文件格式,是完全开放源码的。
    libtiff详细介绍见: http://www.libtiff.orghttp://www.remotesensing.org/libtiff/
    我们可下载完整的Libtiff,现在最新版本是3.7.2,下载网站ftp.remotesensing.org

    http://dl.maptools.org/dl/libtiff/


    解压后,在VC++环境下编译libtiff
    有几种办法,简单举两种:

    1 可以进入CMD环境直接运行命令行 "C:\libtiff\libtiff> nmake /f makefile.vc all" ,假设代码放在C:\libtiff\libtiff> 下面。

    2 如果想利用VC的IDE环境,可以新建立一个生成dll的工程,把刚才下载的.h和.cpp文件导进来,然后在在"project->Settings->C/C++",在"Category"里选"Precompiled Headers",下面有4个单选,缺省选第四个"使用stdafx.h",这里改一下,选中第
    一个:"Not using precompiled headers".然后编译就可以了。

    新建一个MFC工程,把生成的libtiff.lib和libtiff.dll复制过来,并进行如下设置 :
    在"project->Settings->C/C++",在"Category"里选"Preprocessor",在"Additional include directories:"
    里,把libtiff的相对路径或绝对路径写进去,比如"..\libtiff"

    四 使用libtiff读出Tiff文件并显示出来

    TIFF* tiff = TIFFOpen(szFileName, "r");//打开Tiff文件,得到指针,以后所有的操作都通过指针进行。


    int nTotalFrame = TIFFNumberOfDirectories(tiff);
    //一个TIFF文件可以放多幅图,每幅图我们在这里称作一帧,上面这个函数可以得出总帧数。
    //为了便于理解,假定所有图都是真彩24位。

    TIFFSetDirectory(tiff,0);
    //我们打开第一幅图,也就是第0帧,如果是第1帧,第二个参数写1,由此类推。因为Windows下图像基本
    //操作都是以BMP格式进行,我们读出该帧并转成BMP格式。

    char *dtitle;
    TIFFGetField(tiff,TIFFTAG_PAGENAME,&dtitle);
    //得到该帧的名字,存放在dtitle中。

    int width,height;
    TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);  //得到宽度
    TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);//得到高度

    float resolution = max(xres,yres);

    uint16 bitspersample=1;
    uint16 samplesperpixel=1;

    TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
    //每个像素占多少机器字,24位图samplesperpixel应该等于3。
    TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
    //每一个机器字长,这里应为8。

    uint16 bitsperpixel = bitspersample * samplesperpixel;
    //算出每个像素占多少bit,24位图,值为24
    DWORD dwBytePerLine = (width*bitsperpixel+31)/32 *4;
    //由上面几个参数算出图像每行所占字节(BYTE)数。


    DWORD dwLeng = height*dwBytePerLine;//在内存里存放这帧图像数据所需要的长度
    LPBYTE pData = new BYTE[dwLeng];    //为存放数据分配内存空间


    uint32* raster;       
    uint32 *row;
    raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
    TIFFReadRGBAImage(tiff, width, height, raster, 1);
    //以上几行读出该帧数据,保存到raster中
    本篇文章来源于 飞扬教程 原文链接:http://www.51fy.cn/program/VC/200707/41188.htm

    根据上面得到的数据,组成一个新BMP位图:


    LPBITMAPINFO pInfo = new BITMAPINFO;
    pInfo->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
    pInfo->bmiHeader.biWidth        = width;
    pInfo->bmiHeader.biHeight        = width;
    pInfo->bmiHeader.biCompression    = BI_RGB;

    pInfo->bmiHeader.biClrUsed        = 0;
    pInfo->bmiHeader.biClrImportant    = 0;
    pInfo->bmiHeader.biPlanes        = 1;
    pInfo->bmiHeader.biBitCount = 24;
    pInfo->bmiHeader.biSizeImage        = dwLeng;

    float xres,yres;
    uint16 res_unit;
    //解析度单位:如是英寸,厘米
    TIFFGetFieldDefaulted(tiff, TIFFTAG_RESOLUTIONUNIT, &res_unit);

    if(TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &xres) == 0)
    {
        m_pInfo->bmiHeader.biXPelsPerMeter = 0;
    }
    else
    {
        if(res_unit == 2)    //英寸
        {
            pInfo->bmiHeader.biXPelsPerMeter = xres * 10000 / 254;
        }
        else if(res_unit == 3)    //厘米
        {
            pInfo->bmiHeader.biXPelsPerMeter = xres * 100;
        }
        else
        {
            pInfo->bmiHeader.biXPelsPerMeter = 0;
        }
    }
    //得到该帧TIFF横向解析度,并计算出m_pInfo->bmiHeader.biXPelsPerMeter

    if(TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &yres) == 0)
    {
        pInfo->bmiHeader.biYPelsPerMeter = 0;
    }
    else
    {
        if(res_unit == 2)    //英寸
        {
            pInfo->bmiHeader.biYPelsPerMeter = yres * 10000 / 254;
        }
        else if(res_unit == 3)    //厘米
        {
            pInfo->bmiHeader.biYPelsPerMeter = yres * 100;
        }
        else
        {
            pInfo->bmiHeader.biYPelsPerMeter = 0;
        }
    }
    //得到该帧TIFF纵向解析度,并计算出m_pInfo->bmiHeader.biYPelsPerMeter
    本篇文章来源于 飞扬教程 原文链接:http://www.51fy.cn/program/VC/200707/41188_2.htm

     


    历史上的今天:

    seeking 2007-12-21
    tiff[转] 2007-12-21

    随机文章:

    心情不好 2008-01-17
    反思 2008-01-03
    seeking 2007-12-21
    tiff[转] 2007-12-21

    收藏到:Del.icio.us