图像属性信息的获取

准确地说,图像的属性是指所有构成图片的数据元素。从编程的角度来讲,属性与图片的文件头对文件信息的约束是一样的。对于一个图形文件,文件的属性根据图片的不同格式而具有不同的属性值。对于BMP文件,它的属性值有宽度、高度、色彩浓度及编码方式等;对于JPEG文件,它的属性有压缩使用的方式、压缩的质量、压缩的数据区数据等;而对于所有的图形文件,都具备有文件的作者、文件创建时间等属性。属性实际上是对图片的一个完整详细的描述。
    接下来介绍GDI+处理属性的方式。
    GDI+使用214种属性名来表示不同格式的图片可能具有的各种属性。具体内容请参见MSDN的“Image Property TagConstants(属性标记常量)”相关内容。这里列出几个简单、常用的属性名,如表1-1所示。

表格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个函数的所有使用方法,即如何获取图形文件的属性列表。

例程1-2获取属性列表

            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”的过程。

例程1-3修改图片属性

            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”的效果。从图中可以看出,文件的作者已经修改成功了。

图1-4查看文件属性

在C#中获取WIA(Windows Image Acquisition)设备的属性信息,通常需要使用WIA库,这是一个Windows平台上的COM组件,用于简化图像设备的访问和操作。以下是一个基本的示例,展示了如何通过WIA获取设备信息: 首先,你需要确保项目的COM引用中包含了WIA自动安装程序的引用。通常,这可以通过在Visual Studio中添加引用到"COM"项下的"WIA 2.0 Object Library"来实现。 然后,你可以使用以下代码来获取设备信息: ```csharp using System; using System.Runtime.InteropServices; using WIA; namespace WIAExample { class Program { static void Main(string[] args) { // 初始化COM库 try { WIA.Item item = null; WIA.DeviceManager deviceManager = new DeviceManagerClass(); WIA.Device device = null; // 获取所有的WIA设备 foreach (WIA.DeviceInfo deviceInfo in deviceManager.GetDevicesOfUnknownType(WIA.WIA_DEVICE_TYPE.WIA_DEVICE_TYPE_ALL, true)) { // 获取第一个设备 device = deviceInfo.Connect(); item = device.Items[1]; // 获取设备上的第一个项目,通常为默认设备 break; // 取得第一个设备即可,根据需要进行修改 } if (item != null) { // 输出设备名称和其他属性信息 Console.WriteLine("设备名称: " + item.Properties["Name"].get_Value().ToString()); Console.WriteLine("设备描述: " + item.Properties["Description"].get_Value().ToString()); // 遍历并输出所有可用的属性 for (int i = 1; i <= item.Properties.Count; i++) { Console.WriteLine("{0}: {1}", item.Properties[i].Name, item.Properties[i].get_Value()); } } } catch (COMException ex) { Console.WriteLine("COM异常: " + ex.Message); } catch (Exception ex) { Console.WriteLine("异常: " + ex.Message); } Console.ReadKey(); } } } ``` 这段代码首先初始化WIA库,然后使用`DeviceManager`类来查找所有的WIA设备,并连接到第一个找到的设备。之后,通过设备的`Items`属性来访问设备上的项目,并输出设备的相关属性信息。 注意:在实际使用中,你可能需要根据具体的设备类型和项目索引来获取特定的信息,因为不同的设备和项目可能有不同的属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值