找回密码
 加入
搜索
查看: 30122|回复: 19

[交流] 第十六讲 GDI+图像之图像属性项读取EXIF信息及缩略图读取

 火... [复制链接]
发表于 2013-6-17 22:24:46 | 显示全部楼层 |阅读模式
一、缩略图读取
_GDIPlus_ImageGetThumbnail($hImage, $ThumbnailSize, $ThumbnailSize)
返回缩略图像句柄
二、图像属性项
_GDIPlus_ImageGetAllPropertyItems;获取保存在图像对象中的所有属性项(元数据)
_GDIPlus_ImageGetPropertyCount;获取保存在图像对象中的属性(元数据片段)的数量
_GDIPlus_ImageGetPropertyIdList;获取保存在图像对象元数据中的属性标识列表
_GDIPlus_ImageGetPropertyItem;获取图像对象的指定属性项
_GDIPlus_ImageGetPropertyItemSize;获取图像对象指定属性项的字节大小
_GDIPlus_ImageGetPropertySize;获取保存在图像对象中所有数量的属性的字节大小
由于属性标识较多,具体可以参看
本人正在一项一项翻译,工作量好大
每项属性值的获取方法
大部分属性项有固定的方法,当属性项类型为7时,要根据属性项ID来调整读取方法
_GDIPlus_ImageGetPropertyItem;获取图像对象的指定属性项
或者_GDIPlus_ImageGetAllPropertyItems;获取保存在图像对象中的所有属性项(元数据)
得到的多是四个数据,分别是ID,类型,数据长度,指向值的指针
所以要根据ID或者类型来设置一个数据结构
读取做完后,写入属性项就是一个相反的过程,就比较好弄了
先看一下预览版吧

源码如下
#include <APIConstants.au3>
#include <WinAPIEx.au3>
#include <GDIPlus.au3>
#include <GDIPlusEx.au3>

Global $sFile, $hImageFile, $hImageThumbnail
Global $ThumbnailSize = 128
$hWnd = GUICreate("第十六讲GDI+图像之图像属性项", 390, 200)
$hPic = GUICtrlCreatePic("", 5, 5, 150, 150)
$hPicWnd = GUICtrlGetHandle(-1)
$iMemo = GUICtrlCreateEdit("", 160, 5, 225, 190)
GUISetState()
_GDIPlus_Startup()
update()

While 1
        $Msg = GUIGetMsg()
        Switch $Msg
                Case -3
                        ExitLoop

                Case $hPic
                        open()

        EndSwitch
WEnd
_GDIPlus_ImageDispose($hImageFile)
_GDIPlus_ImageDispose($hImageThumbnail)
_GDIPlus_Shutdown()
GUIDelete()
Exit

Func update()
        Local $HWND_CX = _WinAPI_GetWindowWidth($hPicWnd)
        Local $HWND_CY = _WinAPI_GetWindowHeight($hPicWnd)
        Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hPicWnd)
        Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics($HWND_CX, $HWND_CY, $hGraphics)
        Local $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
        Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFA0A0A0)
        Local $iImageType = _GDIPlus_ImageGetType($hImageThumbnail)
        
        If @error = 10 Then
                _GraphicsDrawString($hBackbuffer, "无法生成缩略图", 10, 70, $hBrush, "Arial", 8)
        Else
                _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $hImageThumbnail, 5, 5, $ThumbnailSize, $ThumbnailSize)
                _GraphicsDrawString($hBackbuffer, "点击打开图片", 10, 5 + $ThumbnailSize + 5, $hBrush, "Arial", 8)
        EndIf
        _GDIPlus_BrushDispose($hBrush)
        _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $HWND_CX, $HWND_CY)
        _GDIPlus_BitmapDispose($hBitmap)
        _GDIPlus_GraphicsDispose($hBackbuffer)
        _GDIPlus_GraphicsDispose($hGraphics)
EndFunc   ;==>update
Func open()
        $sFile = FileOpenDialog("请选择文件", "", "图像 (*.jpg;*.bmp;*.png;*.gif;*.tiff)|所有文件 (*.*)")
        If @error Then
                MsgBox(4096, "", "没有选择文件!")
        Else
                _GDIPlus_ImageDispose($hImageFile)
                _GDIPlus_ImageDispose($hImageThumbnail)
                $hImageFile = _GDIPlus_ImageLoadFromFile($sFile)
                $hImageThumbnail = _GDIPlus_ImageGetThumbnail($hImageFile, $ThumbnailSize, $ThumbnailSize)
                update()
                _GetMetaData()
        EndIf
EndFunc   ;==>open

Func save()
        Local $sCLSID = _GDIPlus_EncodersGetCLSID("JPG")
        _GDIPlus_ImageSaveToFileEx($hImageFile, @DesktopDir & "\15讲图像.jpg", $sCLSID)
        MsgBox(4096, "", "图像保存成功!")
EndFunc   ;==>save

Func _GetMetaData()
        Local $aItems = _GDIPlus_ImageGetAllPropertyItems($hImageFile)
        If $aItems = -1 Then
                MemoWrite("图像没有属性项")
                Return 0
        EndIf
        Local $Struct_String, $string = ""
        For $i = 1 To $aItems[0][0];遍历所有属性项
                Switch $aItems[$i][2];根据属性项类型设置数据结构来读取属性值                        
                        Case 1;$GDIP_EPTBYTE
                                $Struct_String = DllStructCreate("BYTE[" & $aItems[$i][1] & "];", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, 1)
                        Case 2;$GDIP_EPTASCII
                                $Struct_String = DllStructCreate("CHAR[" & $aItems[$i][1] & "];", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, 1)
                        Case 3;$GDIP_EPTSHORT
                                $Struct_String = DllStructCreate("USHORT[" & $aItems[$i][1] & "];", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, 1)
                        Case 4;$GDIP_EPTLONG
                                $Struct_String = DllStructCreate("ULONG[" & $aItems[$i][1] & "];", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, 1)
                        Case 5;$GDIP_EPTRATIONAL
                                $Struct_String = DllStructCreate("ULONG numberator;ULONG denominator;", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, "numberator") / DllStructGetData($Struct_String, "denominator")
                        Case 7;$GDIP_EPTUNDEFINED;未定义的要根据ID来决定用哪个方式;这个还要处理,暂且先这样,下次做成UDF再改
                                $Struct_String = DllStructCreate("CHAR[" & $aItems[$i][1] & "];", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, 1)
                        Case 6;读文件的话是9$GDIP_EPTLONGRANGE
                                $Struct_String = DllStructCreate("LONG[" & Ceiling($aItems[$i][1] / 4) & "];", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, 1)
                        Case 8;读文件的话是是10$GDIP_EPTRATIONALRANGE
                                $Struct_String = DllStructCreate("LONG numberator;LONG denominator;", $aItems[$i][3])
                                $string = DllStructGetData($Struct_String, "numberator") / DllStructGetData($Struct_String, "denominator")
                EndSwitch
                MemoWrite(tags2string($aItems[$i][0], $string))
                $string = ""
                $Struct_String = 0
        Next
EndFunc   ;==>_GetMetaData

; Write a line to the memo control
Func MemoWrite($sMessage = '')
        GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
EndFunc   ;==>MemoWrite

;根据属性ID翻译为中文,属性值拆分分析,属性项太多未完成
Func tags2string($TagId, $string, $split = @TAB)
        Switch $TagId
                Case 0x8769
                        Return "特殊ExifPoint" & $split & $string & @CR
                Case 0x8825
                        Return "GPSPoint" & $split & $string & @CR
                Case 0xA005
                        Return "通用ExifPoint" & $split & $string & @CR
                        ;TIFF
                Case 0x100
                        Return "图像宽" & $split & $string & @CR
                Case 0x101
                        Return "图像高" & $split & $string & @CR
                        
                Case 0x102
                        Return "像素字节" & $split & $string & @CR
                Case 0x103
                        Switch $string
                                Case 1
                                        Return "压缩" & $split & "未压缩" & @CR
                                Case 6
                                        Return "压缩" & $split & "JPEG压缩" & @CR
                                Case Else
                                        Return "压缩" & $split & "保留" & @CR
                        EndSwitch
                Case 0x106
                        Switch $string
                                Case 2
                                        Return "JPEG压缩" & $split & "RGB" & @CR
                                Case 6
                                        Return "JPEG压缩" & $split & "YCbCr" & @CR
                                Case Else
                                        Return "JPEG压缩" & $split & "保留" & @CR
                        EndSwitch
                Case 0x112;没来的及进行分类
                        Return "图像排列" & $split & $string & @CR
                Case 0x115
                        Return "每点采样率" & $split & $string & @CR
                Case 0x11C
                Case 0x212, 0x213
                Case 0x11A
                        Return "X分辨率" & $split & $string & @CR
                Case 0x11B
                        Return "Y分辨率" & $split & $string & @CR
                Case 0x128
                        Switch $string
                                Case 2
                                        Return "分辨率单位" & $split & "英吋" & @CR
                                Case 3
                                        Return "分辨率单位" & $split & "厘米" & @CR
                                Case Else
                                        Return "分辨率单位" & $split & "保留" & @CR
                        EndSwitch
                        ;特殊exif
                Case 0x9000
                        Return "Exif版本" & $split & $string & @CR
                Case 0xA000
                        Return "闪光版本" & $split & $string & @CR
                Case 0xA001
                        Switch $string
                                Case 1
                                        Return "色彩空间" & $split & "sRGB" & @CR
                                Case 3
                                        Return "色彩空间" & $split & "未校准" & @CR
                                Case Else
                                        Return "色彩空间" & $split & "保留" & @CR
                        EndSwitch
                Case 0xA500
                        Return "Gamma值" & $split & $string & @CR
                Case 0xA002
                        Return "X点数" & $split & $string & @CR
                Case 0xA003
                        Return "Y点数" & $split & $string & @CR
                Case 0x9101
                        Return "compressed" & $split & $string & @CR
                Case 0x9102
                        Return "像素每单位" & $split & $string & @CR
                Case 0x9003
                        Return "建立时间" & $split & $string & @CR
                Case 0x9004
                        Return "保存时间" & $split & $string & @CR
                Case 0x9290, 0x9291, 0x9292
                Case 0x829A
                        Return "曝光时间" & $split & $string & @CR
                Case 0x829D
                        Return "焦距比数" & $split & $string & @CR
                Case 0x8822
                        Switch $string
                                Case 0
                                        Return "曝光程序" & $split & "未定义" & @CR
                                Case 1
                                        Return "曝光程序" & $split & "手动" & @CR
                                Case 2
                                        Return "曝光程序" & $split & "自动" & @CR
                                Case 3
                                        Return "曝光程序" & $split & "光圈预定" & @CR
                                Case 4
                                        Return "曝光程序" & $split & "快门预定" & @CR
                                Case 5
                                        Return "曝光程序" & $split & "景物" & @CR
                                Case 6
                                        Return "曝光程序" & $split & "运动" & @CR
                                Case 7
                                        Return "曝光程序" & $split & "肖像" & @CR
                                Case 8
                                        Return "曝光程序" & $split & "风景" & @CR
                                Case Else
                                        Return "曝光程序" & $split & "保留" & @CR
                        EndSwitch
                Case 0x8824
                        Return "感光度" & $split & $string & @CR
                Case 0x8827
                        Return "感光度ISO" & $split & $string & @CR
                        ;未完成中,谁来帮我完成,工作量好大
        EndSwitch
        
        Return Hex($TagId, 4) & $split & $string & @CR
EndFunc   ;==>tags2string

Func _GraphicsDrawString($hGraphics, $sString, $nX, $nY, $hBrush = 0, $sFont = "Arial", $nSize = 10, $iFormat = 0)
        Local $hFormat = _GDIPlus_StringFormatCreate($iFormat)
        Local $hFamily = _GDIPlus_FontFamilyCreate($sFont)
        Local $hFont = _GDIPlus_FontCreate($hFamily, $nSize)
        Local $tLayout = _GDIPlus_RectFCreate($nX, $nY, 0, 0)
        Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $sString, $hFont, $tLayout, $hFormat)
        __GDIPlus_BrushDefCreate($hBrush)
        Local $aResult = _GDIPlus_GraphicsDrawStringEx($hGraphics, $sString, $hFont, $aInfo[0], $hFormat, $hBrush)
        Local $iError = @error
        __GDIPlus_BrushDefDispose()
        _GDIPlus_FontDispose($hFont)
        _GDIPlus_FontFamilyDispose($hFamily)
        _GDIPlus_StringFormatDispose($hFormat)
        Return SetError($iError, 0, $aResult)
EndFunc   ;==>_GraphicsDrawString

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 6威望 +2 金钱 +270 贡献 +47 收起 理由
vigiles + 30
xms77 + 80 + 20
afan + 2 + 50 + 5 +
破帽遮颜 + 30 精品文章
user3000 + 11 nice job~!

查看全部评分

发表于 2013-6-17 23:24:32 | 显示全部楼层
一直在关注,加分不解释。
发表于 2013-6-18 02:11:30 | 显示全部楼层
在关注~~~~~~~~~~~~~
发表于 2013-6-18 17:35:27 | 显示全部楼层
等教程完了,求CHM
发表于 2013-6-20 17:41:36 | 显示全部楼层
支持一下...
发表于 2013-6-22 23:04:46 | 显示全部楼层
seniors,你是专门研究图像处理的吧
 楼主| 发表于 2013-6-23 09:05:45 | 显示全部楼层
回复 7# netegg


    不是,我只是喜欢图像,在386电脑的时代我就喜欢编图形界面,那时用的c编程,现在c忘的差不多了
发表于 2013-8-6 15:52:45 | 显示全部楼层
回复 1# seniors


    请教如何使用_GDIPlus_ImageGetPropertyItem,譬如获取创建时间?谢谢
 楼主| 发表于 2013-8-6 19:33:01 | 显示全部楼层
回复 9# llztt
Local $tGPRITEM = _GDIPlus_ImageGetPropertyItem($hImageFile, 0x9003);0x9003是相片拍摄时间
Local $size = DllStructGetData($tGPRITEM, "length");指$pvalue指向的数据长度
Local $type = DllStructGetData($tGPRITEM, "type");相片拍摄时间的type是2,$GDIP_EPTASCII指$pvalue指向的是字符串
Local $pvalue = DllStructGetData($tGPRITEM, "value");不知道为什么_GDIPlus_ImageGetPropertyItem返回值有误,所以这行不能用,用下面的遍列,寻找这个数值
Local $ti = _GDIPlus_ImageGetAllPropertyItems($hImageFile)
For $i = 1 To $ti[0][0]
        If $ti[$i][0] = 0x9003 Then;找到0x9003是相片拍摄时间
                $pvalue = $ti[$i][3];rcn _GDIPlus_ImageGetAllPropertyItems返回的值给$pvalue
                ExitLoop
        EndIf
Next
$Struct_String = DllStructCreate("CHAR[" & $size & "]", $pvalue)
$string = DllStructGetData($Struct_String, 1)

_GDIPlus_ImageGetPropertyItem返回的指向数值的指针有问题
$string就是返回的创建时间
发表于 2013-8-6 20:12:07 | 显示全部楼层
回复 10# seniors


  恩,之前改了顶贴的例子,通过遍历实现了,但总觉得不如一个函数搞定来的简洁,可惜不会处理 _GDIPlus_ImageGetPropertyItem的返回值。。。

多谢指教,既然该函数有问题,那只能用遍历的办法了。。

呵呵,我在整理照片准备冲印呢,想加上时间水印,但有些照片看创建时间和修改时间是不准确的,所以想从EXIF下手,搜来搜去只找到了楼主的帖子,非常感谢哈。。
 楼主| 发表于 2013-8-6 20:20:30 | 显示全部楼层
回复 11# llztt
exif信息太多,一直没时间弄好,我也想弄好后,给照片加上好看的水印
发表于 2013-8-6 21:05:01 | 显示全部楼层
回复 12# seniors


哈哈,希望你早弄好啊,我目前的计划只想到用AU3把批量图片的EXIF信息读出来后,重新用读出来的拍照时间 命名文件,然后剩下的工作就是用PS或美图秀秀 加水印了。。。
也曾考虑用AU3直接加水印到图片,但一是GDI函数不熟,二是怕这么做影响图片质量,所以后来没再想下去。。

哦,其实,我要加的水印是通过拍照时间计算出的宝宝出生日子,哈哈
发表于 2014-7-27 22:12:56 | 显示全部楼层
还是要遍历获取拍照时间啊,另外楼主能不能把你的gdiplus.au3和gdiplusex.au3上传一份啊
发表于 2015-1-13 10:34:18 | 显示全部楼层
高!
发表于 2015-4-3 13:28:02 | 显示全部楼层
厉害...
遇到高手忍不住问下.
我在处理图片时,遇到这样的情况.
从原图中截取部分图片.另存为一张图片后,发现产生色差.
请看下面2张图片,人的肤色发生了明显的改变
我使用的函数是:
        _GDIPlus_StartUp ()
        $hImage = _GDIPlus_BitmapCreateFromFile($p_pic_old)
        $hClone = _GDIPlus_BitmapCloneArea($hImage,829,0,3456,3456,$GDIP_PXF24RGB)        ;5114*3456 800*800 (5114-3456)/2=829
        _GDIPlus_ImageSaveToFile($hClone,$p_pic_new)

        _GDIPlus_ImageDispose($hClone)
        _GDIPlus_ImageDispose($hImage)
        _GDIPlus_ShutDown()

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-24 01:28 , Processed in 0.129487 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表