作者:ZhouMY
准确地说,图像的属性是指所有构成图片的数据元素。从编程的角度来讲,属性与图片的文件头对文件信息的约束是一样的。对于一个图形文件,文件的属性根据图片的不同格式而具有不同的属性值。对于BMP文件,它的属性值有宽度、高度、色彩浓度及编码方式等;对于JPEG文件,它的属性有压缩使用的方式、压缩的质量、压缩的数据区数据等;而对于所有的图形文件,都具备有文件的作者、文件创建时间等属性。属性实际上是对图片的一个完整详细的描述。
接下来介绍GDI+处理属性的方式。
GDI+使用214种属性名来表示不同格式的图片可能具有的各种属性。具体内容请参见MSDN的“Image Property TagConstants(属性标记常量)”相关内容。这里列出几个简单、常用的属性名,如表1-1所示。
|
|
|
| PropertyTagExifVer | EXIF文件版本号 |
| PropertyTagFrameDelay | GIF图片的子图片之间的时间延迟 |
| PropertyTagLoopCount | GIF文件的循环播放次数 |
| PropertyTagJPEGQuality | JPEG丈件的质量 |
| PropertyTagCopyright | 版权信息 |
| PropertyTagDateTime | 文件创建时间 |
| PropertyTagGamma | 文件的Gamma较正 |
| PropertyTagArtist | 文件的作者 |
表1-1中列出的属性名实际上对应着一个常量,所以,属性名也称为属性标记(PropertyTag)。图形文件的属性标记究竟有什么用处?可以做一个这样的比喻,如果把整个图形文件看成是一个注册表,那么,属性标记(PropertyID)就是主键,属性项(PropertyItem)就是键值。属性标记为GDI+查询图形文件提供查询条件,而属性项保存具体的查询结果。
在使用属性标记之前,应该明白这样一个概念:属性标记不具有通用性,比如,程序开发人员不可能在BMP文件中查找ProperyTagJPEGQuality标记。换句话说,在进行属性标记、属性项的查找时,首先应在程序中查找可供查询的属性标记列表。
在GDI+中查询图形文件属性标记,可以通过Image类的下列成员函数来完成。
·GetPropertyCount:获取图形文件中存储的属性总数。
·GetPropertyIdList:获取属性列表。
·GetProperCyItem;获取属性项。
·GetPropertyItemSize:获取属性项大小。
·GetPropertySize:获取属性大小。
以上5个函数的使用并不复杂,这里略去函数的调用方法。这5个函数在使用中也是有规律可循的:先获取属性标记(项)的数目(大小),然后据此分配内存空间。例程1-2演示了这5个函数的所有使用方法,即如何获取图形文件的属性列表。
void CEncodersDecodersView::OnQueryImage()
{
Graphics graphics(this->m_hWnd);
this->RedrawWindow();
SolidBrush brush(Color(255, 0, 0, 255));
FontFamily fontFamily(L"宋体");
Font myFont(&fontFamily, 16, FontStyleRegular, UnitPixel);
UINT count = O;
Image image(L"father.jpg");
∥图片中共有多少属性名可供查询
count= image.GetPropertyCount();
if(count==0)
{
AfxMessageBox("无属性名可供查询");
return;
}
∥为属性项分配空间
PROPID* propIDs = new PROPID[count];
∥获取属性标识列表
image.GetPropertyIdList(count, propIDs);
CString tmp,msg;
for(UINTj=O;j < count; ++j)
{
tmp.Format("第%d个可供查找的属性名的标记值为:%x\n",j,propIDs[j]);
msg+=tmp;
}
msg.AppendChar('\n\n');
∥查找每一个属性标记对应的属性项信息
UINT size=O;
PropertyItem* propertyItem = NULL;
for(int i=O;i < count;i++)
{
size= image.GetPropertyItemSize(propIDs[i]);
tmp.Format("第%d个属性名对应的属性项需要%d个字节来描述\n",i,size);
msg+=tmp;
∥为属性项分配空间
propertyItem= (PropertyItem*)malloc(size);
tmp.Format("第%d个属性名对应的属性项的信息为:\n",i);
msg+=tmp;
∥获取属性项详细描述信息
image.GetPropertyItem(propIDs[i], size, propertyItem);
tmp.Format("\t属性项的长度为%u\n\t数据类型为%d\n”,
propertyItem->length,propertyItem->type);
msg+=tmp;
}
∥输出属性名信息
CStringW msgW((LPCSTR)msg);
graphics.DrawString (msgW, -l,&myFont,
PointF(O,O),NULL,&SolidBrush(Color::Black));
delete[] propIDs;
}
例程1-2头两行的输出信息为:
第O个可供查找的属性名的标记值为:5090
第1个可供查找的属性名的标记值为:5091
在查询MSDN的“Image Property Tag Constants”之后,5090和5091这两个十六进制值分别对应属性名PropertyTagLuminanceTable(属性标记高亮度)和PropertyTagChrominanceTable(属性标记色度表),即JPEG的亮度表和色度表属性。也就是说,这两项属性标记是可供程序查询的。因此,例程1-2获取了属性标记之后,继续对这两个标记的属性项进行详细查询。GetPropertyItem函数将属性项的信息保存在一个PropertyItem对象中。
PropertyItem是GDI+中的一个类,它的类成员很简单,只有id(属性标记值)、length(属性项长度)、type(类型)、value(属性项值)4个部分。一般来说,PropertyItem类前3个数据成员是可以随意访问的,但是最后一个value是指向一个void类型的指针,在明白这个值所具体表示的值之前,不要去访问这个指针值。
与GetPropertyItem函数相对应的是,GDI+也提供了对图片的属性信息进行修改的函数SetPropertyItem,该函数的调用格式为:
Status SetPropertyItem( const PropertyItem* item );
参数item表示指向PropertyItem对象的一个指针。
例程1-3演示了将一幅图片的作者更改为“ZhouMingYang”的过程。
void CEncodersDecodersView::OnSetProp()
{
∥载入图片以供修改
Image image(L"beetle.jpg");
∥设置图片的作者为ZhouZY
PropertyItem* propItem= new PropedyItem;
CHAR newWriterValue[]= "ZhouMingYang";
∥初始化属性项对象PropertyItem
propItem->id = PropertyTagArtist;
propItem->length= strlen(newWriterValue);
∥数据类型
propItem->type= PropertyTagTypeASCⅡ;
//数据值
propItem->value= newWriterValue;
∥设置图形属性
if(image.SetPropertyItem(propItem)!=Ok)
{
AfxMessageBox(”属性修政失败!");
return;
}
∥获取JPEG文件的解码器信息
CLSID encoderClsid;
GetEncoderClsid(L"image/jpeg", &encoderClsid);
∥按照修改后的图形属性保存文件
image.Save(L"newwriter.jpg",&encoderClsid);
∥重新加载修改后的图片
Image image2(L"newwriter.jpg");
∥查看图片的作者信息
UINT size= image2.GetPropertyItemSize(PropertyTagArtist);
PropertyItem* title= (PropertyItem*)malloc(size);
image2.GetPropertyItem(PropertyTagArtist, size, title);
char* writer=(char*)title->value;
CString msg;
msg.Format("图片的作者已经更改为\n%s",writer);
AfxMessageBox(msg);
}
在使用SetPropertyItem函数时,一定要注意其返回值,它表明了对属性的修改是否成功。图1-4所示为使用UltraEdit程序查看例程1-3中新生成的图片“newwriter.jpg”的效果。从图中可以看出,文件的作者已经修改成功了。
本文深入探讨了GDI+处理图像属性的方式,包括属性名、属性标记、属性项以及属性标记常量等内容,并通过实例展示了如何获取和修改图片属性。重点介绍了属性名的用途、属性标记与属性项的概念,以及如何使用GDI+函数进行属性查询和修改。

301

被折叠的 条评论
为什么被折叠?



