
Работа с метаданными изображений с помощью GDI+

Работа с метаданными изображений с помощью GDI+
Библиотека Windows GDI+ предназначена для работы с графикой и мультимедиа и включает в себя более 600 различных функций для этого. Особо радует поддержка: все ключевые функции доступны уже начиная с Windows XP. Ранее мы уже немного касались этой темы. Сегодня разберем примеры, как средствами GDI+ можно получить метаданные из изображений различных форматов и изменить их.
Для работы нам понадобятся несколько структур, достаточно обширный список тегов и константы с идентификаторами типов тегов.
Code (Assembler) : Убрать нумерацию
- ; Структура для работы с GDI+
- struct GdiplusStartupInput
- GdiplusVersion dd ?
- DebugEventCallback dd ?
- SuppressBackgroundThread dd ?
- SuppressExternalCodecs dd ?
- ends
- ; Структура для работы с тегами
- struct PropertyItem
- id dd ?
- length dd ?
- type dw ?
- dw ?
- value dd ?
- ends
Code (Assembler) : Убрать нумерацию
- PropertyTagArtist=0x013B
- PropertyTagBitsPerSample=0x0102
- PropertyTagCellHeight=0x0109
- PropertyTagCellWidth=0x0108
- PropertyTagChrominanceTable=0x5091
- PropertyTagColorMap=0x0140
- PropertyTagColorTransferFunction=0x501A
- PropertyTagCompression=0x0103
- PropertyTagCopyright=0x8298
- PropertyTagDateTime=0x0132
- PropertyTagDocumentName=0x010D
- PropertyTagDotRange=0x0150
- PropertyTagEquipMake=0x010F
- PropertyTagEquipModel=0x0110
- PropertyTagExifAperture=0x9202
- PropertyTagExifBrightness=0x9203
- PropertyTagExifCfaPattern=0xA302
- PropertyTagExifColorSpace=0xA001
- PropertyTagExifCompBPP=0x9102
- PropertyTagExifCompConfig=0x9101
- PropertyTagExifContrast=0xA408
- PropertyTagExifCustomRendered=0xA401
- PropertyTagExifDTDigSS=0x9292
- PropertyTagExifDTDigitized=0x9004
- PropertyTagExifDTOrig=0x9003
- PropertyTagExifDTOrigSS=0x9291
- PropertyTagExifDTSubsec=0x9290
- PropertyTagExifDeviceSettingDesc=0xA40B
- PropertyTagExifDigitalZoomRatio=0xA404
- PropertyTagExifExposureBias=0x9204
- PropertyTagExifExposureIndex=0xA215
- PropertyTagExifExposureMode=0xA402
- PropertyTagExifExposureProg=0x8822
- PropertyTagExifExposureTime=0x829A
- PropertyTagExifFNumber=0x829D
- PropertyTagExifFPXVer=0xA000
- PropertyTagExifFileSource=0xA300
- PropertyTagExifFlash=0x9209
- PropertyTagExifFlashEnergy=0xA20B
- PropertyTagExifFocalLength=0x920A
- PropertyTagExifFocalLengthIn35mmFilm=0xA405
- PropertyTagExifFocalResUnit=0xA210
- PropertyTagExifFocalXRes=0xA20E
- PropertyTagExifFocalYRes=0xA20F
- PropertyTagExifGainControl=0xA407
- PropertyTagExifIFD=0x8769
- PropertyTagExifISOSpeed=0x8827
- PropertyTagExifInterop=0xA005
- PropertyTagExifLightSource=0x9208
- PropertyTagExifMakerNote=0x927C
- PropertyTagExifMaxAperture=0x9205
- PropertyTagExifMeteringMode=0x9207
- PropertyTagExifOECF=0x8828
- PropertyTagExifPixXDim=0xA002
- PropertyTagExifPixYDim=0xA003
- PropertyTagExifRelatedWav=0xA004
- PropertyTagExifSaturation=0xA409
- PropertyTagExifSceneCaptureType=0xA406
- PropertyTagExifSceneType=0xA301
- PropertyTagExifSensingMethod=0xA217
- PropertyTagExifSharpness=0xA40A
- PropertyTagExifShutterSpeed=0x9201
- PropertyTagExifSpatialFR=0xA20C
- PropertyTagExifSpectralSense=0x8824
- PropertyTagExifSubjectArea=0x9214
- PropertyTagExifSubjectDist=0x9206
- PropertyTagExifSubjectDistanceRange=0xA40C
- PropertyTagExifSubjectLoc=0xA214
- PropertyTagExifUniqueImageID=0xA420
- PropertyTagExifUserComment=0x9286
- PropertyTagExifVer=0x9000
- PropertyTagExifWhiteBalance=0xA403
- PropertyTagExtraSamples=0x0152
- PropertyTagFillOrder=0x010A
- PropertyTagFrameDelay=0x5100
- PropertyTagFreeByteCounts=0x0121
- PropertyTagFreeOffset=0x0120
- PropertyTagGamma=0x0301
- PropertyTagGlobalPalette=0x5102
- PropertyTagGpsAltitude=0x0006
- PropertyTagGpsAltitudeRef=0x0005
- PropertyTagGpsAreaInformation=0x001C
- PropertyTagGpsDate=0x001D
- PropertyTagGpsDestBear=0x0018
- PropertyTagGpsDestBearRef=0x0017
- PropertyTagGpsDestDist=0x001A
- PropertyTagGpsDestDistRef=0x0019
- PropertyTagGpsDestLat=0x0014
- PropertyTagGpsDestLatRef=0x0013
- PropertyTagGpsDestLong=0x0016
- PropertyTagGpsDestLongRef=0x0015
- PropertyTagGpsDifferential=0x001E
- PropertyTagGpsGpsDop=0x000B
- PropertyTagGpsGpsMeasureMode=0x00A
- PropertyTagGpsGpsSatellites=0x0008
- PropertyTagGpsGpsStatus=0x0009
- PropertyTagGpsGpsTime=0x0007
- PropertyTagGpsIFD=0x8825
- PropertyTagGpsImgDir=0x0011
- PropertyTagGpsImgDirRef=0x0010
- PropertyTagGpsLatitude=0x0002
- PropertyTagGpsLatitudeRef=0x0001
- PropertyTagGpsLongitude=0x0004
- PropertyTagGpsLongitudeRef=0x0003
- PropertyTagGpsMapDatum=0x0012
- PropertyTagGpsProcessingMethod=0x001B
- PropertyTagGpsSpeed=0x000D
- PropertyTagGpsSpeedRef=0x000C
- PropertyTagGpsTrack=0x000F
- PropertyTagGpsTrackRef=0x000E
- PropertyTagGpsVer=0x0000
- PropertyTagGrayResponseCurve=0x0123
- PropertyTagGrayResponseUnit=0x0122
- PropertyTagGridSize=0x5011
- PropertyTagHalftoneDegree=0x500C
- PropertyTagHalftoneHints=0x0141
- PropertyTagHalftoneLPI=0x500A
- PropertyTagHalftoneLPIUnit=0x500B
- PropertyTagHalftoneMisc=0x500E
- PropertyTagHalftoneScreen=0x500F
- PropertyTagHalftoneShape=0x500D
- PropertyTagHostComputer=0x013C
- PropertyTagICCProfile=0x8773
- PropertyTagICCProfileDescriptor=0x0302
- PropertyTagImageDescription=0x010E
- PropertyTagImageHeight=0x0101
- PropertyTagImageTitle=0x0320
- PropertyTagImageWidth=0x0100
- PropertyTagIndexBackground=0x5103
- PropertyTagIndexTransparent=0x5104
- PropertyTagInkNames=0x014D
- PropertyTagInkSet=0x014C
- PropertyTagJPEGACTables=0x0209
- PropertyTagJPEGDCTables=0x0208
- PropertyTagJPEGInterFormat=0x0201
- PropertyTagJPEGInterLength=0x0202
- PropertyTagJPEGLosslessPredictors=0x0205
- PropertyTagJPEGPointTransforms=0x0206
- PropertyTagJPEGProc=0x0200
- PropertyTagJPEGQTables=0x0207
- PropertyTagJPEGQuality=0x5010
- PropertyTagJPEGRestartInterval=0x0203
- PropertyTagLoopCount=0x5101
- PropertyTagLuminanceTable=0x5090
- PropertyTagMaxSampleValue=0x0119
- PropertyTagMinSampleValue=0x0118
- PropertyTagNewSubfileType=0x00FE
- PropertyTagNumberOfInks=0x014E
- PropertyTagOrientation=0x0112
- PropertyTagPageName=0x011D
- PropertyTagPageNumber=0x0129
- PropertyTagPaletteHistogram=0x5113
- PropertyTagPhotometricInterp=0x0106
- PropertyTagPixelPerUnitX=0x5111
- PropertyTagPixelPerUnitY=0x5112
- PropertyTagPixelUnit=0x5110
- PropertyTagPlanarConfig=0x011C
- PropertyTagPredictor=0x013D
- PropertyTagPrimaryChromaticities=0x013F
- PropertyTagPrintFlags=0x5005
- PropertyTagPrintFlagsBleedWidth=0x5008
- PropertyTagPrintFlagsBleedWidthScale=0x5009
- PropertyTagPrintFlagsCrop=0x5007
- PropertyTagPrintFlagsVersion=0x5006
- PropertyTagREFBlackWhite=0x0214
- PropertyTagResolutionUnit=0x0128
- PropertyTagResolutionXLengthUnit=0x5003
- PropertyTagResolutionXUnit=0x5001
- PropertyTagResolutionYLengthUnit=0x5004
- PropertyTagResolutionYUnit=0x5002
- PropertyTagRowsPerStrip=0x0116
- PropertyTagSMaxSampleValue=0x0155
- PropertyTagSMinSampleValue=0x0154
- PropertyTagSRGBRenderingIntent=0x0303
- PropertyTagSampleFormat=0x0153
- PropertyTagSamplesPerPixel=0x0115
- PropertyTagSoftwareUsed=0x0131
- PropertyTagStripBytesCount=0x0117
- PropertyTagStripOffsets=0x0111
- PropertyTagSubfileType=0x00FF
- PropertyTagT4Option=0x0124
- PropertyTagT6Option=0x0125
- PropertyTagTargetPrinter=0x0151
- PropertyTagThreshHolding=0x0107
- PropertyTagThumbnailArtist=0x5034
- PropertyTagThumbnailBitsPerSample=0x5022
- PropertyTagThumbnailColorDepth=0x5015
- PropertyTagThumbnailCompressedSize=0x5019
- PropertyTagThumbnailCompression=0x5023
- PropertyTagThumbnailCopyRight=0x503B
- PropertyTagThumbnailData=0x501B
- PropertyTagThumbnailDateTime=0x5033
- PropertyTagThumbnailEquipMake=0x5026
- PropertyTagThumbnailEquipModel=0x5027
- PropertyTagThumbnailFormat=0x5012
- PropertyTagThumbnailHeight=0x5014
- PropertyTagThumbnailImageDescription=0x5025
- PropertyTagThumbnailImageHeight=0x5021
- PropertyTagThumbnailImageWidth=0x5020
- PropertyTagThumbnailOrientation=0x5029
- PropertyTagThumbnailPhotometricInterp=0x5024
- PropertyTagThumbnailPlanarConfig=0x502F
- PropertyTagThumbnailPlanes=0x5016
- PropertyTagThumbnailPrimaryChromaticities=0x5036
- PropertyTagThumbnailRawBytes=0x5017
- PropertyTagThumbnailRefBlackWhite=0x503A
- PropertyTagThumbnailResolutionUnit=0x5030
- PropertyTagThumbnailResolutionX=0x502D
- PropertyTagThumbnailResolutionY=0x502E
- PropertyTagThumbnailRowsPerStrip=0x502B
- PropertyTagThumbnailSamplesPerPixel=0x502A
- PropertyTagThumbnailSize=0x5018
- PropertyTagThumbnailSoftwareUsed=0x5032
- PropertyTagThumbnailStripBytesCount=0x502C
- PropertyTagThumbnailStripOffsets=0x5028
- PropertyTagThumbnailTransferFunction=0x5031
- PropertyTagThumbnailWhitePoint=0x5035
- PropertyTagThumbnailWidth=0x5013
- PropertyTagThumbnailYCbCrCoefficients=0x5037
- PropertyTagThumbnailYCbCrPositioning=0x5039
- PropertyTagThumbnailYCbCrSubsampling=0x5038
- PropertyTagTileByteCounts=0x0145
- PropertyTagTileLength=0x0143
- PropertyTagTileOffset=0x0144
- PropertyTagTileWidth=0x0142
- PropertyTagTransferFuncition=0x012D
- PropertyTagTransferRange=0x0156
- PropertyTagWhitePoint=0x013E
- PropertyTagXPosition=0x011E
- PropertyTagXResolution=0x011A
- PropertyTagYCbCrCoefficients=0x0211
- PropertyTagYCbCrPositioning=0x0213
- PropertyTagYCbCrSubsampling=0x0212
- PropertyTagYPosition=0x011F
- PropertyTagYResolution=0x011B
Code (Assembler) : Убрать нумерацию
- PropertyTagTypeByte = 1
- PropertyTagTypeASCII = 2
- PropertyTagTypeShort = 3
- PropertyTagTypeLong = 4
- PropertyTagTypeRational = 5
- PropertyTagTypeUndefined = 7
- PropertyTagTypeSLONG = 9
- PropertyTagTypeSRational = 10
Переходим к работе с изображением. Инициализируем GDI+ и загружаем графический файл. Путь к файлу обязательно должен быть в юникоде.
Code (Assembler) : Убрать нумерацию
- ; Инициализация GDI+
- mov [gdiplusSInput.GdiplusVersion],1
- mov [gdiplusSInput.DebugEventCallback],0
- mov [gdiplusSInput.SuppressBackgroundThread],0
- mov [gdiplusSInput.SuppressExternalCodecs],0
- invoke GdiplusStartup,gdiplusToken,gdiplusSInput,0
- ; Загрузить изображение
- invoke GdipLoadImageFromFile,fname,hImage
Code (Assembler) : Убрать нумерацию
- ; Получить количество тегов, содержащихся в метаданных
- invoke GdipGetPropertyCount,[hImage],nCount
- mov eax,[nCount]
- ; Необходимый размер памяти
- shl eax,2
- invoke GdipAlloc,eax
- mov [pMeta],eax
- ; Получить список тегов из файла
- invoke GdipGetPropertyIdList,[hImage],[nCount],[pMeta]
- mov esi,[pMeta]
- loc_get_tag:
- lodsd
- mov [nTag],eax
- push esi
- ; Получить размер данных тега
- invoke GdipGetPropertyItemSize,[hImage],[nTag],nSize
- or eax,eax
- jnz loc_next
- mov eax,[nSize]
- invoke GdipAlloc,eax
- mov ebx,eax
- ; Получить значение тега
- invoke GdipGetPropertyItem,[hImage],[nTag],[nSize],ebx
- ...
- ...
- ; Действия с полученным тегом
- ; [ebx+PropertyItem.id] -> идентификатор тега
- ; [ebx+PropertyItem.type] -> тип тега
- ; [ebx+PropertyItem.length] -> размер данных
- ; [ebx+PropertyItem.value] -> указатель на данные
- ...
- ...
- invoke GdipFree,ebx
- loc_next:
- pop esi
- dec [nCount]
- cmp [nCount],0
- ja loc_get_tag
- invoke GdipFree,[pMeta]
Code (Assembler) : Убрать нумерацию
- ; Модель камеры
- invoke GdipGetPropertyItemSize,[hImage],\
- PropertyTagEquipModel,nSize
- mov eax,[nSize]
- shl eax,1
- invoke GdipAlloc,eax
- mov ebx,eax
- invoke GdipGetPropertyItem,[hImage],\
- PropertyTagEquipModel,[nSize],ebx
- ; [ebx+PropertyItem.value] -> указатель на строку с моделью камеры
- ; [ebx+PropertyItem.length] -> длина строки
- invoke GdipFree,ebx
- ; ISO
- invoke GdipGetPropertyItemSize,[hImage],\
- PropertyTagExifISOSpeed,nSize
- mov eax,[nSize]
- shl eax,1
- invoke GdipAlloc,eax
- mov ebx,eax
- invoke GdipGetPropertyItem,[hImage],\
- PropertyTagExifISOSpeed,[nSize],ebx
- mov eax,[ebx+PropertyItem.value]
- ; Этот параметр приходит в формате WORD, надо преобразовать в DWORD
- movzx eax,word[eax]
- ; EAX -> значение ISO при съемке
- invoke GdipFree,ebx
Для изменения метаданных используется функция GdipSetPropertyItem. Перед ее вызовом надо указать идентификатор изменяемого тега и настроить его новые значения в зависимости от типа. В следующем примере будет заменено название производителя камеры и встроенная превьюшка файла.
Code (Assembler) : Убрать нумерацию
- ; Настроить новое значение тега EquipMake
- mov [prop.id],PropertyTagEquipMake
- mov [prop.type],PropertyTagTypeASCII
- invoke lstrlen,szNew
- ; Длина строки с учетом завершающего нулевого символа
- inc eax
- mov [prop.length],eax
- mov [prop.value],szNew
- ; Установить новое значение тега
- invoke GdipSetPropertyItem,[hImage],prop
- ; Настроить новое значение тега ThumbnailData
- mov [prop.id],PropertyTagThumbnailData
- mov [prop.type],PropertyTagTypeByte
- ; Размер файла превьюшки
- mov [prop.length],th_len
- ; Содержимое превьюшки
- mov [prop.value],tn
- ; Установить новое значение тега
- invoke GdipSetPropertyItem,[hImage],prop
Добавление новых тегов выполняется точно так же. Удалять ненужные теги вроде как можно при помощи функции GdipRemovePropertyItem, однако на практике она у меня так и не заработала как надо. В загруженном изображении данные удаляются нормально, это подтверждает ошибочный результат функции GdipGetPropertyItemSize, но при сохранении в файл удаленные теги остаются на месте. Более того, если тег сперва изменить, а потом удалить, то в файл будет записано первоначальное значение этого тега. Очередная непонятка, на которую у меня нет ответа.
Перед тем, как сохранить изображение в файл, нужно получить CLSID кодировщика, формат которого будет задействован. Я вынес код в отдельную вспомогательную функцию, так как она может еще не раз пригодиться в других примерах по работе с графикой GDI+.
Code (Assembler) : Убрать нумерацию
- ;----------------------------------------------------------
- ; Получение CLSID кодировщика нужного mime-type
- ;----------------------------------------------------------
- ; На входе:
- ; pEncoder - указатель на строку mime-type (unicode)
- ; pCLSID - указатель на 16-байтный буфер для CLSID
- ; На выходе:
- ; EAX=1 - CLSID успешно получен
- ; EAX=0 - произошла какая-то ошибка
- ;----------------------------------------------------------
- proc GetEncoderCLSID pEncoder:DWORD, pCLSID:DWORD
- struct _ImageCodecInfo
- Clsid rb 16
- FormatID rb 16
- CodecName dd ?
- DllName dd ?
- FormatDescription dd ?
- FilenameExtension dd ?
- MimeType dd ?
- Flags dd ?
- Version dd ?
- SigCount dd ?
- SizeSize dd ?
- SigPattern dd ?
- SigMask dd ?
- ends
- locals
- encoders_count dd ?
- encoders_size dd ?
- result dd ?
- endl
- pusha
- ; По умолчанию результат - ошибка
- mov [result],0
- ; Получить размер памяти для списка кодировщиков
- lea eax,[encoders_size]
- push eax
- lea eax,[encoders_count]
- push eax
- invoke GdipGetImageEncodersSize
- test eax,eax
- jnz .loc_ret
- ; Выделить память
- invoke VirtualAlloc,0,[encoders_size],\
- MEM_COMMIT,PAGE_READWRITE
- test eax,eax
- jz .loc_ret
- mov ebx,eax
- ; Получить список кодировщиков
- invoke GdipGetImageEncoders,[encoders_count],\
- [encoders_size],ebx
- test eax,eax
- jnz .loc_clear
- ; Поочередно сравнить mime-type полученных
- ; кодировщиков с искомым
- .scan_encoders:
- mov esi,[ebx+_ImageCodecInfo.MimeType]
- mov edi,[pEncoder]
- @@:
- lodsw
- cmp ax,0
- je .encoder_found
- inc edi
- inc edi
- cmp ax,word[edi-2]
- je @b
- ; Следующий кодировщик
- add ebx,sizeof._ImageCodecInfo
- dec [encoders_count]
- jnz .scan_encoders
- jmp .loc_clear
- .encoder_found:
- ; Скопировать CLSID найденного кодировщика
- lea esi,[ebx+_ImageCodecInfo.Clsid]
- mov edi,[pCLSID]
- movsd
- movsd
- movsd
- movsd
- ; Успешный результат
- mov [result],1
- .loc_clear:
- ; Прибраться за собой
- invoke VirtualFree,ebx,0,MEM_RELEASE
- .loc_ret:
- popa
- mov eax,[result]
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ; mime-type кодировщика
- encoder du 'image/jpeg',0
- encoder_clsid rb 16
- ...
- ...
- ; Получить CLSID кодировщика для image/jpeg
- stdcall GetEncoderCLSID,encoder,encoder_clsid
- ; Сохранить изменения в новый файл
- invoke GdipSaveImageToFile,[hImage],nname,encoder_clsid,NULL
Осталось прибраться за собой. После чтения или изменения метаданных освобождаем все задействованные ресурсы:
Code (Assembler) : Убрать нумерацию
- ; Освободить графику
- invoke GdipDisposeImage,[hImage]
- ; Выключение GDI+
- invoke GdiplusShutdown,[gdiplusToken]
Просмотров: 1137 | Комментариев: 10

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
gob
(22.11.2022 в 19:35):
хех, даже из png печатает текст в UTF-8 верно. А комментарии в jpg не извлекаются

ManHunter
(19.12.2021 в 11:13):
Полно редакторов тегов, от консольного ExifTool до всяких гуишных комбайнов. Недавно тут один выкладывал на исследование. По запросу "каталогизатор фото" гуглояндексы тоже выдают немало полезного.

Barm
(19.12.2021 в 10:34):
Приветствую! Ассоциативно тут вопрос созрел чутка оффтопный:
Фотки и видосы с фотоаппарата я сохраняю папками по месяцам. И в разные месяцы там может быть природа, город, семья, животные и т.д.
Уже который раз думаю, как бы удобнее всего подобных тегов напрописывать в фотографии и видосы, чтобы потом при необходимости легко найти все фото и видео (в моём случае JPG и MOV) во всех этих ежемесячных папках?
Фотки и видосы с фотоаппарата я сохраняю папками по месяцам. И в разные месяцы там может быть природа, город, семья, животные и т.д.
Уже который раз думаю, как бы удобнее всего подобных тегов напрописывать в фотографии и видосы, чтобы потом при необходимости легко найти все фото и видео (в моём случае JPG и MOV) во всех этих ежемесячных папках?

ManHunter
(07.12.2021 в 16:11):
Сайт ExifTool ожил

ManHunter
(29.11.2021 в 11:54):
Я имел в виду начало структуры.
align 4
struct abc
a dw ?
b db ?
c dd ?
ends
в этом случае само местоположение структуры (но не ее полей!!!) в памяти будет выровнено.
А для выравнивания полей придется лепить что-то типа
struct abc
a dw ?
dw ?
b db ?
rb 3
c dd ?
ends
или
struct abc
a rw 2
b rb 4
c dd ?
ends
Это FASM, сишные и MASMовские трюки тут не прокатывают
align 4
struct abc
a dw ?
b db ?
c dd ?
ends
в этом случае само местоположение структуры (но не ее полей!!!) в памяти будет выровнено.
А для выравнивания полей придется лепить что-то типа
struct abc
a dw ?
dw ?
b db ?
rb 3
c dd ?
ends
или
struct abc
a rw 2
b rb 4
c dd ?
ends
Это FASM, сишные и MASMовские трюки тут не прокатывают

Nemo
(29.11.2021 в 11:47):
Выравнивание структуры - и есть выравнивание полей
В С директивой
struct s{
#pragma align 8 /* поле a выравнено по 8-байтной границе адреса */
int a;
int bar;
#pragma align 16 /* поле b выровнено по 16-байтной границе адреса */
int b;
} t[2];
В С директивой
struct s{
#pragma align 8 /* поле a выравнено по 8-байтной границе адреса */
int a;
int bar;
#pragma align 16 /* поле b выровнено по 16-байтной границе адреса */
int b;
} t[2];

ManHunter
(29.11.2021 в 11:44):
В этом-то и дело, что в доках не пишут. В лучшем случае упоминают про выравнивание самой структуры, а не ее полей. Значит я правильно подумал.
Джефри Рихтер "Создание эффективных Win-32 приложений с учетом специфики 64 разрядной версии Windows"
Джефри Рихтер "Создание эффективных Win-32 приложений с учетом специфики 64 разрядной версии Windows"

Nemo
(29.11.2021 в 11:41):
>> Если верить официальной документации, то ее размер получается 14 байт, а
>> указатель на данные value должен начинаться на 10-м байте в памяти от
>> начала структуры. Фактически же структура PropertyItem занимает в
>> памяти 16 байт указатель на данные начинается с 12-го байта
Выравнивание полей структуры на DWORD. В доках не везде пишут (и не все структуры выравниваются)
В синтаcисе МАСМ:
str STRUCT 4 ; (для win32 или 8 for x64)
A DW ? ; offset 0
b DW ? ; offset 4
c DW ? ; offset 8
d dd ? ; offset 12
str ENDS
>> указатель на данные value должен начинаться на 10-м байте в памяти от
>> начала структуры. Фактически же структура PropertyItem занимает в
>> памяти 16 байт указатель на данные начинается с 12-го байта
Выравнивание полей структуры на DWORD. В доках не везде пишут (и не все структуры выравниваются)
В синтаcисе МАСМ:
str STRUCT 4 ; (для win32 или 8 for x64)
A DW ? ; offset 0
b DW ? ; offset 4
c DW ? ; offset 8
d dd ? ; offset 12
str ENDS

ManHunter
(29.11.2021 в 11:21):
Вот ничоси, сайт ExifTools реально не работает. Пару дней назад проверял, все было нормально. Подождем, может Фил просто хостинг не продлил или еще чего-то.

NeshAliNehrin
(29.11.2021 в 11:15):
Доброго дня.
Проверял кликабельность ссылки на ExifTools (от 29.11.21 не рабочая),
возможно пригодится другая: https://github.com/exiftool/exiftool
Проверял кликабельность ссылки на ExifTools (от 29.11.21 не рабочая),
возможно пригодится другая: https://github.com/exiftool/exiftool

Добавить комментарий
Заполните форму для добавления комментария
