Дата съёмки

Mar 29, 2018 12:15

Возникла задача пакетно менять файлы jpeg, а именно изменить дату создания, дату модификации, дату съёмки, и вставить на фото дату и время съёмки (как  делают многие "мыльницы"). Т.е. задаёшь дату и время, натравливаешь на папку с фотографиями - на выходе получаешь фотографии с заданной датой и немного разным временем (если время будет одинаково, то это совсем палево) Не спрашивайте, зачем - ответ один "капитализм".
Решил писать на PowerShell(PS). Если с изменением стандартных файловых аттрибутов (дата создания, модификации) особых проблем нет, то с датой съёмки несколько сложнее - данные EXIF являются метаданными, к тому же необязательными, поэтому изменение их методами PS довольно длинно, а хотелось сделать всё одной строкой (исключительно чтобы помучится). Поэтому для изменения даты съёмки решил использовать утилиту с открытым кодом exiftool , ну а для вставки штампа с датой на фото проверенный ImageMagick, утилита convert.

$CurDate=get-date -DATE '2001/01/01 12:00:00'
$tempFolder='E:\Users\Admin\Download\Photo\Photo\1'
$tempexiftool='E:\Users\Admin\Download\Photo\Photo\exiftool.exe'
$tempconvert='C:\Program Files\ImageMagick-6.7.4-Q16\convert.exe'
Get-ChildItem $tempFolder -Recurse -Force | ? {!$_.PSIsContainer} | % {$tTI=Get-Random -Maximum 15.5 -Minimum 1.1;$CurDate1=$CurDate.AddMinutes($tTI);$args1='-pointsize 20 -fill yellow -draw "text 100,100 '+"'"+$CurDate1.ToString("yyyy:MM:dd hh:mm:ss")+"'"+'" -gravity SouthEast "'+$_.Name+'" "'+$_.Name+'"';$args1;Start-Process $tempconvert -arg $args1 -WorkingDirectory $tempFolder -Wait ;$args=' -AllDates="'+$CurDate1.ToString("yyyy:MM:dd hh:mm:ss")+'" -overwrite_original "'+$_.FullName+'"'; Start-Process $tempexiftool -arg $args -WorkingDirectory $tempFolder -Wait;$_.CreationTime = $CurDate1; $_.LastAccessTime=$CurDate1; $_.LastWriteTime=$CurDate1}

$CurDate - желаемая дата, $tempFolder - папка с фото, $tempexiftool, $tempconvert - пути до exiftool и convert соответственно. Время ставится в + от заданного случайным образом от +1,1 минуты до 15,5 (Get-Random -Maximum 15.5 -Minimum 1.1).
Одной строкой - это конечно... ээээ перебор! Она получается очень уж длинной и непонятной, прямо обфускация какая прости господи.

Вот так конечно понятнее:

$CurDate=get-date -DATE '2001/01/01 12:00:00'
$tempFolder='E:\Users\Admin\Download\Photo\Photo\1'
$tempexiftool='E:\Users\Admin\Download\Photo\Photo\exiftool.exe'
$tempconvert='C:\Program Files\ImageMagick-6.7.4-Q16\convert.exe'
$ListFile = Get-ChildItem $tempFolder
foreach ($File in $ListFile)
{
$tTI=Get-Random -Maximum 15.5 -Minimum 1.1
$CurDate1=$CurDate.AddMinutes($tTI)
$args1='-pointsize 20 -fill yellow -draw "text 100,100 '+"'"+$CurDate1.ToString("yyyy:MM:dd hh:mm:ss")+"'"+'" -gravity SouthEast "'+$File.Name+'" "'+$File.Name+'"'
Start-Process $tempconvert -arg $args1 -WorkingDirectory $tempFolder -Wait
$args=' -AllDates="'+$CurDate1.ToString("yyyy:MM:dd hh:mm:ss")+'" -overwrite_original "'+$File.FullName+'"'
Start-Process $tempexiftool -arg $args -WorkingDirectory $tempFolder -Wait
$File.CreationTime = $CurDate1
$File.LastAccessTime=$CurDate1
$File.LastWriteTime=$CurDate1
}

Если кому интересно, привожу код на PS, меняющий дату съёмки. Запихивать такое в одну строку - слишком даже для такого Захер-Мазоха, как я ))) :

$tempFolder='E:\Users\Admin\Download\Photo\Photo\1'
$FileItems=Get-ChildItem $tempFolder
$CurDate=get-date -DATE '2001/01/01 12:00:00'
Foreach ($FileItem in $FileItems)
{
$ImageFile = $FileItem.FullName
Write-Host $ImageFile
$FileStreamArgs = @(
$ImageFile
[System.IO.FileMode]::Open
[System.IO.FileAccess]::Read
[System.IO.FileShare]::Read
1024, # Buffer size
[System.IO.FileOptions]::SequentialScan
)
$FileStream = New-Object System.IO.FileStream -ArgumentList $FileStreamArgs
$Img = [System.Drawing.Imaging.Metafile]::FromStream($FileStream)
$ExifDT = $Img.GetPropertyItem('20625')
$ExifDT.Id= 36867
$ExifDT.Len=20
$ExifDT.Type=2
$tTI=Get-Random -Maximum 15.5 -Minimum 1.1
$NewTime = $CurDate.AddMinutes($tTI)
$ExifTime = $NewTime.ToString("yyyy:MM:dd HH:mm:ss`0")
Write-Host -Message "New Time is $($NewTime.ToString('F')) (Exif: $ExifTime)"
$ExifDT.Value = [Byte[]][System.Text.Encoding]::ASCII.GetBytes($ExifTime)
$Img.SetPropertyItem($ExifDT)
$MemoryStream = New-Object System.IO.MemoryStream
Try {
$Img.Save($MemoryStream, $Img.RawFormat)
}
Catch {
Write-Warning -Message "Problem modifying image $ImageFile ($_)"
$MemoryStream.Close()
$MemoryStream.Dispose()
Break
}
Finally {
$Img.Dispose()
$FileStream.Close()
}

Try {
$Writer = New-Object System.IO.FileStream($ImageFile, [System.IO.FileMode]::Create)
$MemoryStream.WriteTo($Writer)
}
Catch {
Write-Warning -Message "Problem saving to $ImageFile ($_)"
Break
}
Finally {
If ($Writer) {$Writer.Flush(); $Writer.Close()}
$MemoryStream.Close(); $MemoryStream.Dispose()
}
}

P.S. - собственно, писать/рисовать на фото можно и прямо из PS, используя API Windows. Но код будет ещё длиннее, конечно, и перезаписать файл так и не удалось - через раз выскакивают неопределённые ошибки, пришлось делать копию.

Add-Type -AssemblyName System.Drawing
$tempFolder='E:\Users\Admin\Download\Photo\Photo\1'
$CurDate=get-date -DATE '2001/01/01 12:00:00'
$ListFile = Get-ChildItem $tempFolder
foreach ($File in $ListFile)
{
$filename = "E:\Users\Admin\Download\Photo\Photo\1\foo.png"
$bmp = new-object System.Drawing.Bitmap $File.FullName
$tTI=Get-Random -Maximum 15.5 -Minimum 1.1
$CurDate1=$CurDate.AddMinutes($tTI)
$font = new-object System.Drawing.Font Consolas,12
$brushBg = [System.Drawing.Brushes]::Yellow
$brushFg = [System.Drawing.Brushes]::Yellow
$graphics = [System.Drawing.Graphics]::FromImage($bmp)
#$graphics.FillRectangle($brushBg,0,0,100,30)
$graphics.DrawString($CurDate1.ToString("yyyy:MM:dd hh:mm:ss"),$font,$brushFg,10,10)
$graphics.Dispose()
$newF = $tempFolder+'\st_'+$File.BaseName+$File.Extension
$bmp.Save($newF, ([system.drawing.imaging.imageformat]::jpeg))
$bmp.Dispose()
#Invoke-Item $newF
}

Ну и конечно, после написания скрипта надобность в нём отпала ))))))

free soft, моё, ИТ

Previous post Next post
Up