实验报告显示tif图像Word格式.docx
- 文档编号:22485121
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:24
- 大小:158.19KB
实验报告显示tif图像Word格式.docx
《实验报告显示tif图像Word格式.docx》由会员分享,可在线阅读,更多相关《实验报告显示tif图像Word格式.docx(24页珍藏版)》请在冰豆网上搜索。
Version成员总是包含十进制42(0x2a),它用于进一步校验该文件是否为TIF格式,42这个数并不是一般人想象中的那样认为是TIF软件的版本,实际上,42这个数大概永远不会变化;
第三个成员是IFD(接下来要说的第二个数据结构)相对文件开始处的偏移量。
2、图像文件目录(ImageFileDirectory简称IFD):
图二IFD及DE结构描述
IFD是TIF图中最重要的数据结构,它包含了一个TIF文件中最重要的信息,一个TIF图可能有多个IFD,这说明文件中有多个图像,每个IFD标识1个图像的基本属性。
IFD结构中包含了三类成员,DirectoryEntryCount指出该结构里面有多少个目录入口;
接下来就是N个线性排列的DE序列,数量不定(这就是为什么称TIF格式文件为可扩充标记的文件,甚至用户可以添加自定义的标记属性),每个DE标识了图像的某一个属性;
最后就是一个偏移量,标识下一个文件目录相对于文件开始处的位置,当然,如果该TIF文件只包含了一幅图像,那么就只有一个IFD,显然,这个偏移量就等于0;
3、目录入口(DirectoryEntry简称DE):
共12个字节,见图二。
简单说,一个DE就是一幅图像的某一个属性。
例如图像的大小、分辨率、是否压缩、像素的行列数、一个像素由几位表示(1位代表黑白两色,8位代表256色等等)等。
其中:
tag成员是该属性的编号,在图像文件目录中,它是按照升序排列的。
我们可以通过读这些编号,然后到TIF格式官方白皮书中查找相应的含义。
属性是用数据来表示的,那么type就是代表着该数据的类型,TIF官方指定的有5种数据类型。
type=1就是BYTE类型(8位无标记整数)、type=2是ASCII类型(7位ASCII码加1位二进制0)、type=3是SHORT类型(16位无标记整数)、type=4是LONG类型(32位无标记整数)、type=5是RATIONAL类型(2个LONG,第一个是分子,第二个是分母)。
length成员是数据的数量而不是数据类型的长度。
第4个成员valueOffset很重要,它是tag标识的属性代表的变量值相对文件开始处的偏移量。
如果变量值占用的空间小于4个字节,那么该值就存放在valueOffset中即可,没必要再另外指向一个地方了
4、图像数据
本程序提供的图像是基于256灰度级的,即一个字节代表一个像素点,它是0x00~0xff区间中256个灰度级的任意一个整数。
通过使用UltraEdit工具观察,我们发现该图像文件的组织形式是:
IFH--数据--IFD。
以下的示例说明遵循了这一观察结果。
四、程序设计
1、VC创建一个MFCAppWizard(exe)工程取名TiffTest,选择单文档程序。
2、添加TiffStruct.h文件,定义IFH和DE结构(参考前面的结构描述),用来接收读TIF文件的信息。
#ifndef_TIFFSTRUCT_
#define_TIFFSTRUCT_
typedefstructtagIMAGEFILEHEADER
{
WORDbyteOrder;
WORDversion;
DWORDoffsetToIFD;
}IFH;
typedefstructtagDIRECTORYENTRY
WORDtag;
WORDtype;
DWORDlength;
DWORDvalueOffset;
}DE;
#endif
3、在文档类中添加4个公有变量,并将其初始化为0。
在TiffTestDoc.cpp中#include"
TiffStruct.h"
DWORDm_dwBmSize;
//图象的数据部分的大小
CPalettem_palDIB;
//BMP图象调色板
HANDLEm_hDIB;
//BMP图象内存块句柄
CSizem_sizeDoc;
//图象的长和宽
4、在文档类的OnOpenDocument函数中定义局部工具变量并读文件
DWORDdwFileLength=0;
CStringstrTemp=_T("
"
);
WORDwDECount=0;
BYTE*pDIB=NULL;
inti=0;
IFHifh;
ZeroMemory(&
ifh,sizeof(IFH));
CFilefile;
CFileExceptionfe;
if(0==file.Open(lpszPathName,CFile:
:
modeRead|CFile:
shareDenyWrite,&
fe))
AfxMessageBox("
打开文件失败"
returnFALSE;
}
dwFileLength=file.GetLength();
5、读IFH文件头
if(sizeof(IFH)!
=file.Read(&
ifh,sizeof(IFH)))
{
读TIF文件头失败"
if(0x2a!
=ifh.version)
该文件不是TIF格式,读文件失败"
if(0x4949!
=ifh.byteOrder)
该TIF文件不是IBMPC字节序,读文件失败"
file.Seek(ifh.offsetToIFD,CFile:
begin);
//将文件指针定位到IFD
6、读文件有多少个目录入口
if(2!
wDECount,2))
无法获得TIF文件目录入口数量"
}
strTemp.Format("
该TIF文件有%d个目录入口"
wDECount);
AfxMessageBox(strTemp);
//显示有多少个目录入口
7、创建DE数组,接收信息,数组中有wDECount个元素
DE*pde=newDE[wDECount];
DE*pTemp=pde;
memset(pde,0,sizeof(DE)*wDECount);
if(sizeof(DE)*wDECount!
=file.ReadHuge(pde,sizeof(DE)*wDECount))
读图象文件目录失败"
delete[]pde;
}
8、显示图像文件目录信息
for(i=0;
i<
wDECount;
i++)
{
pTemp=pde+i;
strTemp.Format("
DE[%d].tag=%d\r\nDE[%d].type=%d\r\nDE[%d].length=%d\r\nDE[%d].valueOffset=%d"
i,pTemp->
tag,i,pTemp->
type,i,pTemp->
length,i,pTemp->
valueOffset);
AfxMessageBox(strTemp);
//显示目录文件信息
}
9、把图像的大小和图像数据的容量保存到成员变量中
for(i=0;
{
pTemp=pde+i;
if(256==pTemp->
tag) //tag为256的目录入口中的变量标识了图象宽度
{
m_sizeDoc.cx=pTemp->
valueOffset;
}
if(257==pTemp->
tag) //tag为257的目录入口中的变量标识了图象长度
m_sizeDoc.cy=pTemp->
if(273==pTemp->
tag) //计算图象数据占用字节数
m_dwBmSize=m_sizeDoc.cx*m_sizeDoc.cy;
}
10、在文档类中创建一个成员工具函数CreateBmpBuffer,申请全局内存块以存放BMP文件结构数据
BOOLCTiffTestDoc:
CreateBmpBuffer()
//申请BMP内存块
m_hDIB=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPINFOHEADER)+
256*sizeof(RGBQUAD)+
m_dwBmSize);
if(NULL==m_hDIB)
AfxMessageBox("
申请BMP内存块失败"
returnFALSE;
else
returnTRUE;
}
11、回到OnOpenDocument成员函数中调用工具函数并获得全局内存块指针
//构造BMP图象内存块
if(!
CreateBmpBuffer())
构造BMP图象内存块失败"
//获得BMP内存块指针
pDIB=(BYTE*)GlobalLock(m_hDIB);
if(NULL==pDIB)
获得BMP内存块指针失败"
GlobalUnlock(m_hDIB);
12、将图像信息填充到BMP内存块中,(注:
BMP文件中图像数据的第一行代表的是最终显示光栅的最后一行,所以在数据排列中要颠倒过来。
)
//构造BITMAPFILEHEADER并复制到BMP内存块
BITMAPFILEHEADERbmfHdr;
memset(&
bmfHdr,0,sizeof(BITMAPFILEHEADER));
bmfHdr.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
256*sizeof(RGBQUAD);
bmfHdr.bfReserved1=0;
bmfHdr.bfReserved2=0;
bmfHdr.bfSize=bmfHdr.bfOffBits+m_dwBmSize;
bmfHdr.bfType=0x4d42;
memmove(pDIB,&
bmfHdr,sizeof(BITMAPFILEHEADER));
//构造BITMAPINFOHEADER并复制到BMP内存块
BITMAPINFOHEADERbmiHdr;
bmiHdr,0,sizeof(BITMAPINFOHEADER));
bmiHdr.biBitCount=8;
bmiHdr.biClrImportant=0;
bmiHdr.biClrUsed=0;
bmiHdr.biCompression=0;
bmiHdr.biHeight=m_sizeDoc.cy;
bmiHdr.biPlanes=1;
bmiHdr.biSize=sizeof(BITMAPINFOHEADER);
bmiHdr.biSizeImage=0;
bmiHdr.biWidth=m_sizeDoc.cx;
bmiHdr.biXPelsPerMeter=2834;
bmiHdr.biYPelsPerMeter=2834;
memmove((BITMAPFILEHEADER*)pDIB+1,&
bmiHdr,sizeof(BITMAPINFOHEADER));
//构造256个RGBQUAD并复制到BMP内存块
RGBQUAD*pRgbQuad=(RGBQUAD*)(pDIB+sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPINFOHEADER));
RGBQUAD*pOldQuad=pRgbQuad;
RGBQUADrgbQuad;
rgbQuad,0,sizeof(RGBQUAD));
for(i=0;
256;
rgbQuad.rgbBlue=i;
rgbQuad.rgbGreen=i;
rgbQuad.rgbRed=i;
rgbQuad.rgbReserved=0;
pRgbQuad=pOldQuad+i;
memmove(pRgbQuad,&
rgbQuad,sizeof(RGBQUAD));
//填充所有像素数据,颠倒图象数据从最后一行开始读起
intj=0;
for(i=m_sizeDoc.cy-1;
i>
=0;
i--)
file.Seek(sizeof(IFH)+i*m_sizeDoc.cx,CFile:
file.Read((BYTE*)(pRgbQuad+1)+j*m_sizeDoc.cx,m_sizeDoc.cx);
j++;
13、初始化BMP调色板,为显示BMP文件做准备
//初始化专用调色板
BYTEbuf[2+2+4*256];
LOGPALETTE*pPal=(LOGPALETTE*)buf;
pPal->
palVersion=0x300;
palNumEntries=256;
255;
pPal->
palPalEntry[i].peBlue=i;
palPalEntry[i].peFlags=0;
palPalEntry[i].peGreen=i;
palPalEntry[i].peRed=i;
m_palDIB.CreatePalette(pPal);
14、(附加功能)生成bmp文件
CFilefileWrite("
C:
\DocumentsandSettings\Administrator\桌面\mytiff.bmp"
CFile:
modeCreate|CFile:
modeWrite);
fileWrite.WriteHuge(pDIB,sizeof(BITMAPFILEHEADER)+
sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)+m_dwBmSize);
15、OnOpenDocument成员函数返回前的清理工作
GlobalUnlock(m_hDIB);
delete[]pde;
returnTRUE;
至此,TIF文件信息已转换为BMP图像并保存在全局内存块中了,接下来就可以在OnDraw中调用WinAPI函数StretchDIBits来显示它。
流程图:
N
Y
五、使用说明
方法一:
1、双击图标TiffView
2、点击文件
3、点打开,并找到自己所要显示的TIF图片点击即可
方法二:
1、双击图标TiffVie.dsp
2、进行编译和链接,然后点击运行
3、点击文件
4、点打开,并找到自己所要显示的TIF图片点击即可
六、测试结果
1、使用方法一打开文件夹中的测试图片。
2、图片显示如下:
七、心得体会
本次我的实验题目为:
显示TIF文件格式。
刚刚接触这个题目时,并没有什么想法,因为平时看图片都是直接用图片浏览器看,并没有自己动手编程来实现过。
拿道题目之后,我到网上查阅了相关资料,初步了解了什么是TIF格式,并初步掌握了TIF格式的组成部分,但在查阅资料的时候,我也发现了一个问题,就是TIF是可扩充标记的文件,所以理论上是不可能编写一个能识别所有类别TIF格式的读写程序,于是我结合相关知识,以及网上的一些程序,觉得可以将TIF图像先转换成BMP图像,然后再将其显示出来。
在程序的编写过程中,因为要实现可视化的功能,所以我建立了工程,在以前的编程题目中很少有需要建工程来完成的题目,所以对此我也是比较陌生的,关于此我请教了一些同学,并对工程有了初步的认识。
在编写具体代码的时候,多少遇到了一些困难,于是我主要是参照网上和书上的一些代码和程序块,结合自己所需要的程序,进行了拼接和修改,并对自己很不熟悉的语句进行了逐一的查找和翻译,最终实现了功能。
本次的实验,让我重新巩固了之前学习过的编程知识和程序的编译和调试,虽然在过程中遇到了不少的困难,但是结果还是令人欣喜的,同时感谢指导老师对我耐心的指导。
八、附录
核心源代码:
BOOLCTiffViewDoc:
OnOpenDocument(LPCTSTRlpszPathName)
{
if(!
CDocument:
OnOpenDocument(lpszPathName))
returnFALSE;
/*初始化*/
DWORDdwFileLength=0;
CStringstrTemp=_T("
WORDwDECount=0;
BYTE*pDIB=NULL;
inti=0;
IFHifh;
ZeroMemory(&
//将IFH对应变量的空间大小赋予ifh
CFilefile;
//定义文件
CFileExceptionfe;
if(0==file.Open(lpszPathName,CFile:
AfxMessageBox("
}
dwFileLength=file.GetLength();
//读取文件长度赋值
if(sizeof(IFH)!
ifh,sizeof(IFH)))//判断规模是否相同(字节)
if(0x2a!
if(0x4949!
=ifh.byteOrder)//判断整数格式
file.Seek(ifh.offsetToIFD,CFile:
//寻找偏移量(找目录)
if(2!
strTemp.Format("
//AfxMessageBox(strTemp);
//显示具体的入口数
DE*pde=newDE[wDECount];
DE*pTemp=pde;
memset(pde,0,sizeof(DE)*wDECount);
//初始化pde(置零大小不变)
if(sizeof(DE)*wDECount!
delete[]pde;
//显示图象目录入口信息--测试用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 报告 显示 tif 图像