关于Libtiff库的使用(zz)


(1)下载tiff库文件
http://www.libtiff.org/
无法下载,镜像下载处http://libtiff.maptools.org/dl/可以,目前版本3.8.2
可以处理5.0或6.0标准的TIFF文件
(2)第1次编译tiff库
按说明(http://www.libtiff.org/build.html#PC)需要使用命令行
nmake /f makefile.vc
cd ..\tools
nmake /f makefile.vc
原文如下
Building the Software under Windows 95/98/NT/2000 with MS VC++ With Microsoft Visual C++ installed, and properly configured for commandline use (you will likely need to source VCVARS32.BAT in AUTOEXEC.bAT or somewhere similar) you should be able to use the provided makefile.vc.

C:\LIBTIFF\LIBTIFF> nmake /f makefile.vc
C:\LIBTIFF\LIBTIFF> cd ..\tools
C:\LIBTIFF\TOOLS> nmake /f makefile.vc

This will build the library file LIBTIFF\LIBTIFF\LIBTIFF.LIB. This can be used in Win32 programs. If used in a project using the /MD compiler switch (using the runtime C library), it may be necessary to modify the CFLAGS macro in makefile.vc to correspond.
The makefile also builds a DLL (libtiff.dll) with an associated import library (libtiff_i.lib). Any builds using libtiff will need to include the LIBTIFF\LIBTIFF directory in the include path.
The libtiff\tools\makefile.vc should build .exe's for all the standard TIFF tool programs.
NOTE: The contents of the contrib/win32 directory should no longer be needed, and are kept in the distribution temporarily.

编译提示
tif_jpeg.c(87) : fatal error C1083: Cannot open include file: 'jpeglib.h': No such file or directory
NMAKE : fatal error U1077: 'cl' : return code '0x2'
(3)下载并编译jpeg库文件
看源文件中让去ftp.uu.net:/graphics/jpeg/下载,但是没有用户名和密码进不去,去http://www.ijg.org/下载jpegsr8c.zip
解压jpeg文件后执行命令行
nmake /f makefile.vc setup-vc6 这是准备工作,makefile里有但是文档没写
nmake /f makefile.vc
如果不放心再来一个
nmake /f makefile.vc test
比较无误后可以使用了
(4)第2次编译tiff库文件
把jpeg目录加入lib和include环境变量
nmake /f makefile.vc
提示需要zlib.h
tif_pixarlog.c(90) : fatal error C1083: Cannot open include file: 'zlib.h': No s
uch file or directory
NMAKE : fatal error U1077: 'cl' : return code '0x2'
(5)zlib库
这次源文件中没有提示下载位置,搜索到主页http://zlib.net/无法打开
去http://gnuwin32.sourceforge.net/packages/zlib.htm下载个不带源文件的安装包,这回省得编译了。
安装后加入include和lib环境变量
***\psoftware\lib\zconf.h(289) : fatal error C1083: Cannot open include file:
 'unistd.h': No such file or directory
去文件中把那里的#if 1改为#if 0重新编译(unistd表示unix standard)
(6)第3次编译tiff库文件
链接时提示
tif_jpeg.obj : error LNK2001: unresolved external symbol _jpeg_read_header
tif_jpeg.obj : error LNK2001: unresolved external symbol _jpeg_resync_to_restart
...
反正很多没找到就是了
用 dumpbin /linkermember libjpeg.lib 可以找到对应函数,看来是路径问题
查找makefile.vc,发现引用nmake.opt
nmake.opt里默认把jpeg和zlib取消了(靠,编译时需要,输出库文件不用?),修改其路径
(7)第4次编译tiff库文件
出现很多警告,但是lib和dll文件生成了,tools下部分工具没有生成,不管了,现在tiff库可以使用了

 

使用VC编译时自己的程序时需要修改编译选项中的/MLd改为/MDd(/MDd link with MSVCRTD.LIB debug lib, /MLd link with LIBCD.LIB debug lib),这样会产生程序库链接冲突的警告,可能由于调试库和编译的libTIFF库不兼容引起,目前来看可以忽略。

-----------------------------------------------
tiff库使用方式(来自帮助文档,后面涉及到文件格式部分可能理解错误)
1、打开文件
#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("foo.tif", "r"); // 打开,关闭
    // TIFF* tif = TIFFOpen("foo.tif", "w"); // 写入方式,不能像stdio那样同时为rw方式
    ... do stuff ...
    TIFFClose(tif);
}
2、TIFF Directories
TIFF文件每个图像都有相关的数据结构,称为directory保存图形信息,不同图形的directory可以无关。
通常不需要读取directory,库函数在打开和写入文件时会自动处理(调用TIFFClose或TIFFFlush时)。
读取文件时TIFFSetDirectory可以用从0开始的序号选择任意directory,TIFFReadDirectory和TIFFWriteDirectory可以用于顺序读写directory。
计算文件中的directory数:
#include "tiffio.h"
main(int argc, char* argv[])
{
    TIFF* tif = TIFFOpen(argv[1], "r");
    if (tif) {
      int dircount = 0;
      do {
        dircount++;
      } while (TIFFReadDirectory(tif)); // 读入每个Directory
      printf("%d directories in %s\n", dircount, argv[1]);
      TIFFClose(tif);
    }
  exit(0);
}
TIFFCurrentDirectory返回当前directory的序号,TIFFLastDirectory返回当前directory是否为最后一个directory,TIFFPrintDirectory可以显示当前directory的格式化信息。
3、TIFF Tags
图像信息如宽度和高度、采样数、方向、色度信息等保存在每个图像directory的tags中,tags用数字表示,Adobe有相关说明,但是部分公司的TIFF文件使用自定义的tags没有说明。
TIFFGetField and TIFFSetField 是针对tag操作的
 uint32 w, h;
 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);

字节顺序:big-endian and little-endian

数据位置
TIFF标准除了对前8字节的文件头数据有要求外,其他数据位置均没有要求,因此可以在图像数据后放一些信息。

libtiff提供了读取TIFF文件的接口,默认使用32bit形式的ABGR像素,也可以以其他格式读入,然后对数据进行解释。有两种方式读入图像数据,一次读入所有数据用TIFFReadRGBAImage函数。
#include "tiffio.h"
main(int argc, char* argv[])
{
    TIFF* tif = TIFFOpen(argv[1], "r");
    if (tif) {
        uint32 w, h;
        size_t npixels;
        uint32* raster;
        
        TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
        npixels = w * h;
        raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); // 分配适当格式的内存
        if (raster != NULL) {
            if (TIFFReadRGBAImage(tif, w, h, raster, 0)) { // 读入图像数据
                ...处理数据 process raster data...
            }
            _TIFFfree(raster); // 释放内存
        }
        TIFFClose(tif);
    }
    exit(0);
}
另一函数可以代替TIFFReadRGBAImage并控制读入过程,上述程序的等价程序为
#include "tiffio.h"
main(int argc, char* argv[])
{
    TIFF* tif = TIFFOpen(argv[1], "r");
    if (tif) {
        TIFFRGBAImage img;
        char emsg[1024];
        
        if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) { // 开始读入
            size_t npixels;
            uint32* raster;
            
            npixels = img.width * img.height;
            raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
            if (raster != NULL) {
                if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) { // 控制读入
                    ...process raster data...
                }
                _TIFFfree(raster);
            }
            TIFFRGBAImageEnd(&img);
        } else
            TIFFError(argv[1], emsg);
        TIFFClose(tif);
    }
    exit(0);
}
tools/*.c中有使用TIFFRGBAImage的例子程序。

Scanline-based图像IO
libtiff提供的最简单的接口是scanline方式的接口,用于读取条状或块状的图像,scanline是一个像素高度×图像宽度的图像,这种方式只能用于非压缩格式图像。函数为TIFFReadScanline和TIFFWriteScanline。
#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
        uint32 imagelength;
        tdata_t buf;
        uint32 row;
        
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
        buf = _TIFFmalloc(TIFFScanlineSize(tif));
        for (row = 0; row < imagelength; row++)
            tiffreadscanline(tif, buf, row);
        _tifffree(buf);
        tiffclose(tif);
    }
}
TIFFScanlineSize可以返回解码后的scanline大小,类似TIFFReadScanline返回的数据。
如果图像中存在多个图形数据,上面程序只返回第一个图形,需要用下面程序代替
#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
        uint32 imagelength;
        tdata_t buf;
        uint32 row;
        
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
        TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
        buf = _TIFFmalloc(TIFFScanlineSize(tif)); // 调用TIFFScanlineSize
        if (config == PLANARCONFIG_CONTIG) {
            for (row = 0; row < imagelength; row++)
                tiffreadscanline(tif, buf, row);
        } else if (config == planarconfig_separate) {
            uint16 s, nsamples;
            
            tiffgetfield(tif, tifftag_samplesperpixel, &nsamples);
            for (s = 0; s < nsamples; s++)
                for (row = 0; row < imagelength; row++)
                    tiffreadscanline(tif, buf, row, s);
        }
        _tifffree(buf);
        tiffclose(tif);
    }
}

Strip-oriented图像处理
可以处理压缩或非压缩数据
#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
        tdata_t buf;
        tstrip_t strip;
        
        buf = _TIFFmalloc(TIFFStripSize(tif));
        for (strip = 0; strip < tiffnumberofstrips(tif); strip++)
            tiffreadencodedstrip(tif, strip, buf, (tsize_t) -1); // -1表示自动计算strip大小
        _tifffree(buf);
        tiffclose(tif);
    }
}
最后一个strip的数据可能少于RowsPerStrip tag的数,因此读入时不能对读入的数据数进行假定。
#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
        tdata_t buf;
        tstrip_t strip;
        uint32* bc;
        uint32 stripsize;
        
        TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
        stripsize = bc[0];
        buf = _TIFFmalloc(stripsize);
        for (strip = 0; strip < tiffnumberofstrips(tif); strip++) {
            if (bc[strip] > stripsize) {
                buf = _TIFFrealloc(buf, bc[strip]);
                stripsize = bc[strip];
            }
            TIFFReadRawStrip(tif, strip, buf, bc[strip]);
        }
        _TIFFfree(buf);
        TIFFClose(tif);
    }
}
上述例子中的strip是按物理存储的顺序读入的,可能与逻辑顺序不同。
其他略,前面有很多不理解地方,后面无法继续了。

-----------------------------------------------

有时程序输出时出现类似下面的警告:

TIFFReadDirectory: Warning, ***.tif: unknown field with tag 33550 (0x830e) encountered.
TIFFReadDirectory: Warning, ***.tif: invalid TIFF directory; tags are not sorted in ascending order.
要抑制程序的警告输出,根据帮助文件使用TIFFWarningHandler出错,解决问题方法如下
http://www.asmail.be/msg0055340520.html
1994.12.06 08:41 "TIFFWarningHandler doesn't exist", by Glenn Herteg
Documentation bug:

In the man/man3/TIFFWarning.3t file from the 3.3beta021 release, all
references to TIFFWarningHandler should be changed to TIFFErrorHandler,
to match tiff/libtiff/tiffio.h (or perhaps the latter file should be
changed to match the documentation, though this would make it difficult
to use one handler for both warnings and errors, if the compiler runs
strong type checks).

Glenn Herteg
[email protected]
即用TIFFErrorHandler替换TIFFWarningHandler。(TNND,帮助文档也写错,而且目前还没有修改)

你可能感兴趣的:(面向对象的程序设计)