Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Графика и игры
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 12.03.2017, 15:03
tsa tsa вне форума
Прохожий
 
Регистрация: 12.03.2017
Сообщения: 3
Версия Delphi: Delphi 2010
Репутация: 10
Вопрос Чтение данных Exif файла jpg

Прошу помочь с решением следующей проблемы. Я написал функцию FileSetDateExif, устанавливающую время модификации файла JPG равным времени его создания 'CreateDate', прописанному в Exif. Функция необходима для сведения в один временной ряд уже модифицированных файлов JPG от разных фотоаппаратов.
Выполнение данной функции сопровождается возникновением исключения "Project … raised exception class EExternalException with message ‘External exception c0000002’" при установке времени каждого файла.
Проблему частично решил обрамлением вызова функции конструкцией "try ... except" и установкой опции игнорирования данного сообщения. Однако видимо есть еще иные побочные эффекты упомянутого выше исключения, так как после вызова написанной функции при работе встроенного мною в оболочку моего программного комплекса медиаплеера стали возникать невиданные ранее прерывания от access violation до полного вылета программы.
Работу функции исследовал под Windows 7 x64, Delphi 2010. Путем последовательного комментирования операторов установил, что возникновение исключения при выполнении оператора SetFileTime(hndl,nil,nil,@aFileTime) происходит если ранее выполнялся оператор WicDecoder.GetFrame(0,FrameDecode).
Буду благодарен за любой совет, так как собственная фантазия уже исчерпалась. Также буду благодарен за любое прояснение ситуации по характеристике возникающего исключения.

Ответ на вопрос дан lmikle : "вызывать _release напрямую не рекомендуется... достаточно просто ... присвоить Nil".
Приведенный ниже код исправлен в соответствии с данной рекомендацией и теперь работает безукоризненно.


Код:
unit uHDDCam;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, MMSystem, Math, Mask, ExtCtrls, ComCtrls, Buttons, uChildAis,
  ToolWin, DateUtils, wincodec, ComObj, ValEdit, ActiveX;
.........................................................

var
  fmHDDCam: TfmHDDCam;
  function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation;
   var lpLocalTime, lpUniversalTime: TSystemTime): BOOL; stdcall;
  function SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation: PTimeZoneInformation;
   var lpUniversalTime,lpLocalTime: TSystemTime): BOOL; stdcall;

implementation

uses ....................................................;

  function TzSpecificLocalTimeToSystemTime; external kernel32 name 'TzSpecificLocalTimeToSystemTime';
  function SystemTimeToTzSpecificLocalTime; external kernel32 name 'SystemTimeToTzSpecificLocalTime';

{$R *.dfm}

function FileSetDateExif : Integer;
  var
    WicFactory                    : IWICImagingFactory;
    WicDecoder                    : IWICBitmapDecoder;
    FrameDecode                   : IWICBitmapFrameDecode;
    mdReader                      : IWICMetadataQueryReader;
    Prop                          : TPropVariant;
    hndl                          : THandle;
    NewTime                       : TDateTime;
    tzi                           : TTimeZoneInformation;
    LocalTime,UniversalTime       : TSystemTime;
    aFileTime                     : TFileTime;
begin
  Result:=0;
  hndl:=CreateFile(PChar(LastSelectImageName),GENERIC_READ or GENERIC_WRITE,
   0,nil,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
  if hndl=THandle(-1) then Result:=GetLastError {INVALID_HANDLE_VALUE}
  else
  begin
    try
      WicFactory:=CreateComObject(CLSID_WICImagingFactory) as IWICImagingFactory;
      WicFactory.CreateDecoderFromFileHandle(hndl,TGUID(nil^),WICDecodeMetadataCacheOnDemand,WicDecoder);
      WicFactory:=nil;
      {выполнение следующего оператора приводит к ошибке при записи времени файла!!!}
      WicDecoder.GetFrame(0,FrameDecode);
      WicDecoder:=nil;
      if FrameDecode.GetMetadataQueryReader(mdReader)<>S_OK then
      begin
        ShowMessage('Не могу прочесть Exif '+LastSelectImageName);
        System.Exit;
      end;
      FrameDecode:=nil;
      zeroMemory(@Prop,SizeOf(Prop));
      mdReader.GetMetadataByName('/xmp/CreateDate',prop);
      mdReader:=nil;
      s:=String(Prop.pwszVal);
      s:=BackDateToRight(s);
      NewTime:=StrToDateTime(s);
      GetTimeZoneInformation(tzi);
      DateTimeToSystemTime(NewTime,LocalTime);
      {локальное время файла пересчитывается с учетом часового пояса}
      TzSpecificLocalTimeToSystemTime(@tzi,LocalTime,UniversalTime);
      SystemTimeToFileTime(UniversalTime,aFileTime);
      if SetFileTime(hndl,nil,nil,@aFileTime) then System.Exit;
      Result:=GetLastError;
    finally
      FileClose(hndl);
    end; {finally}
  end; {hndl<>THandle(-1)}
end; {FileSetDateExif}

Последний раз редактировалось tsa, 13.03.2017 в 02:34.
Ответить с цитированием
 


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 17:04.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter