Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Задача по автоматизации. Склейка 2х jpg файлов (http://forum.oszone.net/showthread.php?t=213850)

irvicon 22-08-2011 19:11 1737209

Задача по автоматизации. Склейка 2х jpg файлов
 
Добрый день.

Есть более тысячи файлов изображений. Размер маленький, каждый 400-600кб. Файлы одинаковые - ширина, высота, ориентация (книжная) и битность (серый 8bit). Имена файлов последовательно (2011_0001, 2011_0002 ... и т.д.). Склейка - по узкой стороне.

Требуется "взять" первый (нечетный) и снизу приклеить второй (четный) и сохранить в файл 2011_s***. Вместо звездочек нарастающий номер. Идеальный вариант: указать 2 папки - откуда брать и куда складывать. Работа разовая - ПО не критично, поставим, сделаем и снесем.

Какие уважаемое общество может предложить варианты.

ferget 22-08-2011 20:47 1737269

с ImageMagick идет утилита convert.exe, она может объединять файлы

а bat-файл помогут написать здесь http://forum.oszone.net/forum-102.html

Iska 23-08-2011 02:01 1737450

irvicon, попробуйте так:
читать дальше »
Код:

Option Explicit

Dim objFSO
Dim objFile
Dim objRegExp

Dim strFileSource2
Dim strFileDest

Dim objImageFileSource1
Dim objImageFileSource2
Dim objImageFileWork

Dim objImageProcess

Dim lngCount


If WScript.Arguments.Count = 2 Then
        Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
       
        If objFSO.FolderExists(WScript.Arguments.Item(0)) Then
                If objFSO.FolderExists(WScript.Arguments.Item(1)) Then
                        Set objRegExp = WScript.CreateObject("VBScript.RegExp")
                       
                        With objRegExp
                                .IgnoreCase = True
                                .Pattern = "2011_\d{3}[13579]{1}\.jpg"
                        End With
                       
                        lngCount = 0
                       
                        For Each objFile In objFSO.GetFolder(WScript.Arguments.Item(0)).Files
                                If objRegExp.Test(objFile.Name) Then
                                        lngCount = lngCount + 1
                                       
                                        WScript.Echo "Iteration #" & CStr(lngCount)
                                        WScript.Echo "  Source #1:  " & objFile.Path
                                       
                                        strFileSource2 = objFSO.BuildPath( _
                                                objFile.ParentFolder, _
                                                "2011_" & Right("0000" & CStr(CLng(Right(objFSO.GetBaseName(objFile.Name), 4)) + 1), 4) & "." & _
                                                objFSO.GetExtensionName(objFile.Name) _
                                        )
                                       
                                        WScript.Echo "  Source #2:  " & strFileSource2
                                       
                                        If objFSO.FileExists(strFileSource2) Then
                                                Set objImageFileSource1 = WScript.CreateObject("WIA.ImageFile")
                                                Set objImageFileSource2 = WScript.CreateObject("WIA.ImageFile")
                                               
                                                Set objImageProcess    = WScript.CreateObject("WIA.ImageProcess")
                                               
                                                objImageFileSource1.LoadFile objFile.Path
                                                objImageFileSource2.LoadFile strFileSource2
                                               
                                                With objImageProcess
                                                        ' Создаём «болванку» итогового изображения посредством
                                                        ' масштабирования первого изображения до нужного размера
                                                        ' Это работает быстрее, нежели формирование его вручную
                                                       
                                                        .Filters.Add .FilterInfos("Scale").FilterID
                                                       
                                                        With .Filters.Item(.Filters.Count).Properties
                                                                ' По первому изображению определяем, где у него «узкая» сторона
                                                                ' В ту сторону и увеличиваем изображение, влево или вниз
                                                                If objImageFileSource1.Width / objImageFileSource1.Height >= 1 Then
                                                                        .Item("MaximumWidth")  = objImageFileSource1.Width + objImageFileSource2.Width
                                                                        .Item("MaximumHeight") = objImageFileSource1.Height
                                                                Else
                                                                        .Item("MaximumWidth")  = objImageFileSource1.Width
                                                                        .Item("MaximumHeight") = objImageFileSource1.Height + objImageFileSource2.Height
                                                                End If
                                                               
                                                                .Item("PreserveAspectRatio") = False
                                                        End With
                                                       
                                                        ' Получаем «болванку» изображения
                                                        Set objImageFileWork = .Apply(objImageFileSource1)
                                                       
                                                        .Filters.Remove .Filters.Count
                                                       
                                                       
                                                        ' Накладываем на полученное изображение первое изображение
                                                        .Filters.Add .FilterInfos("Stamp").FilterID
                                                       
                                                        With .Filters.Item(.Filters.Count).Properties
                                                                .Item("ImageFile") = objImageFileSource1
                                                                .Item("Left")      = 0
                                                                .Item("Top")      = 0
                                                        End With
                                                       
                                                        ' Накладываем на полученное изображение второе изображение
                                                        .Filters.Add .FilterInfos("Stamp").FilterID
                                                       
                                                        With .Filters.Item(.Filters.Count).Properties
                                                                .Item("ImageFile") = objImageFileSource2
                                                               
                                                                ' По первому изображению определяем, где у него «узкая» сторона
                                                                ' К той стороне и прикладываем второе изображение, слева или снизу
                                                                If objImageFileSource1.Width / objImageFileSource1.Height >= 1 Then
                                                                        .Item("Left")      = objImageFileSource1.Width
                                                                        .Item("Top")      = 0
                                                                Else
                                                                        .Item("Left")      = 0
                                                                        .Item("Top")      = objImageFileSource1.Height
                                                                End If
                                                        End With
                                                       
                                                        ' Получаем итоговое изображение
                                                        Set objImageFileWork = .Apply(objImageFileWork)
                                                       
                                                        .Filters.Remove .Filters.Count
                                                        .Filters.Remove .Filters.Count
                                                End With
                                               
                                                ' Сохраняем полученное итоговое изображение
                                                strFileDest = WScript.Arguments.Item(1) & "\2011_s" & Right("0000" & CStr(lngCount), 4) & "." & objImageFileWork.FileExtension
                                               
                                                If objFSO.FileExists(strFileDest) Then
                                                        objFSO.DeleteFile strFileDest, True
                                                End If
                                               
                                                objImageFileWork.SaveFile strFileDest
                                               
                                                WScript.Echo "  Destination: " & strFileDest
                                                WScript.Echo
                                        Else
                                                WScript.Echo "    Can't find odd source file [" & strFileSource2 & "]"
                                                WScript.Echo
                                        End If
                                Else
                                        ' Nothing to do
                                End If
                        Next
                       
                        Set objImageProcess    = Nothing
                       
                        Set objImageFileSource1 = Nothing
                        Set objImageFileSource2 = Nothing
                       
                        Set objRegExp          = Nothing
                Else
                        WScript.Echo "Can't find destination folder [" & WScript.Arguments.Item(1) & "]"
                End If
        Else
                WScript.Echo "Can't find source folder [" & WScript.Arguments.Item(0) & "]"
        End If
       
        Set objFSO = Nothing
Else
        WScript.Echo "Usage: " & WScript.ScriptName & " <Source folder> <Destination folder>"
End If

WScript.Quit

Код сохранить в файл с кодировкой ANSI (win-1251) с расширением «.vbs». Исполнять, указав папку-источник и папку назначения аргументами скрипта. Например:
Код:

cscript.exe "e:\Песочница\0082\Script.vbs" "e:\Песочница\0082\Source" "e:\Песочница\0082\Destination"
Примерный результат работы
Код:

Iteration #1
  Source #1:  E:\Песочница\0082\Source\2011_0001.jpg
  Source #2:  E:\Песочница\0082\Source\2011_0002.jpg
  Destination: E:\Песочница\0082\Destination\2011_s0001.jpg

Iteration #2
  Source #1:  E:\Песочница\0082\Source\2011_0003.jpg
  Source #2:  E:\Песочница\0082\Source\2011_0004.jpg
  Destination: E:\Песочница\0082\Destination\2011_s0002.jpg

Iteration #3
  Source #1:  E:\Песочница\0082\Source\2011_0005.jpg
  Source #2:  E:\Песочница\0082\Source\2011_0006.jpg
  Destination: E:\Песочница\0082\Destination\2011_s0003.jpg


ferget 23-08-2011 05:27 1737493

а зачем столько echo?

Iska 23-08-2011 06:03 1737494

Я исполняю скрипты под консольным «cscript.exe» (я указал на это обстоятельство в примере; более того — «cscript.exe» у меня назначен как стандартный сервер сценариев [вместо «wscript.exe»]). Это даёт такое преимущество, как возможность вывода текста, индикаторы прогресса в консоли, простое перенаправление вывода в файл и т.п.

Ну, и работаю я под Far Manager'ом, где вывод консольной программы сразу можно перенаправить в его вьюер, або в редактор.

irvicon 23-08-2011 07:41 1737520

Цитата:

Цитата Iska
irvicon, попробуйте так: »

Сегодня попробую.

irvicon 23-08-2011 09:54 1737569

Цитата:

Цитата Iska
irvicon, попробуйте так »

Работает! :) Большое спасибо.
Куда слать пиво?)

Iska 23-08-2011 12:22 1737669

Цитата:

Цитата irvicon
Куда слать пиво?) »

Спросите у Администрации. Может им нужно ;).

ivang 15-02-2014 17:46 2309535

Цитата:

Цитата Iska
irvicon, попробуйте так:
читать дальше » »

Прекрасное решение, мощь не уступающая линукс консоли, но менее понятная большинству.
Большое спасибо за предложенный вариант, немного допилив использовал и в своих целях.
:clapping:

pzh2393 27-01-2015 14:48 2462169

А с чем может быть связана ошибка "Could not locate automation class named "WIA.ImageFile"" при запуске указанного выше VBS скрипта?

И каким образом там вообще осуществляется склейка изображений, с пережатием или без?

Собственно был бы очень благодарен если подскажите решение по объединению двух JPEG файлов (одинаковая ширина и высота, а так же параметры сжатия) в один, желательно lossless.

А так же прошу подсказать, что необходимо поправить в скрипте, если правому файлу "***.jpg" соответсвует левый "***_.jpg" (имя файла произвольной длинны).

Iska 27-01-2015 15:13 2462186

Цитата:

Цитата pzh2393
А с чем может быть связана ошибка "Could not locate automation class named "WIA.ImageFile"" при запуске указанного выше VBS скрипта? »

С отсутствием данного объекта Automation. На какой ОС была попытка исполнить скрипт?

Цитата:

Цитата pzh2393
И каким образом там вообще осуществляется склейка изображений, с пережатием или без? »

Полагаю, что первое. Точный ответ может дать только команда разработчиков из Microsoft.

Цитата:

Цитата pzh2393
Собственно был бы очень благодарен если подскажите решение по объединению двух JPEG файлов (одинаковая ширина и высота, а так же параметры сжатия) в один, »

Излагайте детали. В подробностях.

Цитата:

Цитата pzh2393
…желательно lossless. »

А это возможно в принципе?! При любых значениях ширины и высоты?

Цитата:

Цитата pzh2393
А так же прошу подсказать, что необходимо поправить в скрипте, если правому файлу "***.jpg" соответсвует левый "***_.jpg" (имя файла произвольной длинны). »

Например?

pzh2393 27-01-2015 15:42 2462199

Цитата:

Цитата Iska
С отсутствием данного объекта Automation. »

Для работы скрипта нужен дополнительный софт?
Цитата:

Цитата Iska
На какой ОС была попытка исполнить скрипт? »

Windows XP SP3 x86 RU
Цитата:

Цитата Iska
Излагайте детали. В подробностях. »

Есть парочка сотен (до тысячи) JPEG картинок в с вое время нарезанных в Фотошоп с одинаковым размером (230х153 пикселей) и сжатыми с одними параметрами (если не ошибаюсь Baseline:Optimized 8/12)
В связи с оптимизацией веб-страниц на которых они располагаются встал вопрос с объединением пар изображений в одно.
Цитата:

Цитата Iska
Например? »

1.jpg и соответствующая ему пара 1_.jpg объединить например в 1_out.jpg
0909.jpg и соответствующая ему пара 0909_.jpg в 0909_out.jpg

Хотел попробовать приведенный здесь скрипт (т.к. ввариант с "входящей" и "исходящей" папками тоже подходит), но почти сразу появилась вышеуказанная ошибка.
Цитата:

Цитата Iska
А это возможно в принципе?! »

Всемирный источник знаний однозначно не отвечает на этот вопрос...
Вот пару найденных мной обсуждений данного вопроса:
http://www.programmersforum.ru/showthread.php?t=245229
http://forum.ru-board.com/topic.cgi?forum=36&topic=1429
http://forum.ixbt.com/topic.cgi?id=20:15554
http://sasgis.org/mantis/view.php?id=1203

В ходе поисков так же нашлась и эта когда-то решенная тема.

Iska 27-01-2015 16:35 2462220

Цитата:

Цитата pzh2393
Для работы скрипта нужен дополнительный софт? »

Описания:
Windows Image Acquisition Automation Layer
Windows Image Acquisition (WIA) (Windows)

Ссылка на загрузку библиотеки «Windows Image Acquisition Library v2.0» и SDK: … Упс, убрали с сайта Microsoft. Попробую вечером посмотреть, что можно сделать.

pzh2393 27-01-2015 19:08 2462301

Спасибо за объяснения, буду пробовать.

Кстати, если я правильно определил и нашел, то скачать можно по этой ссылке:
http://vbnet.mvps.org/files/updates/wiaautsdk.zip

Iska 27-01-2015 19:24 2462316

Цитата:

Цитата pzh2393
Кстати, если я правильно определил и нашел, »

Правильно. Это оно. Я сейчас загрузил архив и сравнил с имеющимся у меня в наличии — полностью совпадает. Описание установки «ручками» приведено в файле «ReadMe.txt» внутри архива.

Выложите для экспериментов штуки три-четыре пары изображений на RGhost, упаковав их в архив.

pzh2393 27-01-2015 20:23 2462340

Теперь все сработало, но видимо все же придется искать другое решение.
С таким уровнем компрессии по умолчанию - мне никак не подходит.
Жаль что lossless склейка JPG похоже до ума так и не доведена.
Я так до конца и не понял, может ли эта утилита соединять.
http://jpegclub.org/jpegtran/
Все попытки её вызова так ни к ему и не привели, у меня постоянно пишет какую-нибудь ошибку синтаксиса командной строки.

Цитата Iska:
Выложите для экспериментов штуки три-четыре пары изображений на RGhost, упаковав их в архив. »
http://rghost.ru/8WhBJn5t8

Iska 28-01-2015 06:58 2462496

pzh2393, это те реальные файлы, что требуется объединить? Я что-то сомневаюсь. Как Вы их ранее могли «нарезать» из одной картинки, если это и есть одна и та же картинка, только разных форматах?

Так же не представляю, как Вы вообще предполагали без пересжатия объединить изображения в разных форматах:
Скрытый текст
Код:

                            Common
File name            : E:\Песочница\0427\sample\woman.jpg
File size            : 6542 bytes
Image type          : image/jpeg
Width                : 153 px
Height              : 200 px
Pixel format        : 8 bpp, indexed
Color space          : Grayscale
                              EXIF
GDI+.Luminance Table : 10


и
Скрытый текст
Код:

                            Common
File name              : E:\Песочница\0427\sample\woman_.jpg
File size              : 9044 bytes
Image type            : image/jpeg
Width                  : 153 px
Height                : 200 px
Pixel format          : 24 bpp, RGB
Color space            : YCBCR
                              EXIF
GDI+.Luminance Table  : 10
GDI+.Chrominance Table : 11


Поясните этот вопрос.

pzh2393 28-01-2015 12:42 2462581

Цитата Iska:
это те реальные файлы, что требуется объединить? Я что-то сомневаюсь. »

Да, вы меня подловили - это не именно те файлы.
Дело в том, что руководитель категорически запретил выкладывать какие-либо файлы проекта, пришлось выкручиваться.
Мне, как дизайнеру, не пришло в голову, что могут быть такие технические отличия, мне просто было так проще обозначить отличия.
Суть "истинных" файлов почти такая же - два состояния одного и того же изображения, правда действительно обе картинки 24 bpp, RGB.
Если вам действительно интересна эта задача - можно попытаться объединить 1_.jpg c 0909_.jpg, обе картинки цветные, и уж точно сжаты с одними параметрами.

P.S. Собственно говоря это моя личная инициатива по автоматизации склейки старых изображений, задача изначально поставлена - сделать с "нуля" заново. :(

Iska 01-02-2015 02:48 2464560

pzh2393, посмотрел, почитал… Полагаю, с Вашими изображениями — фокус не удастся.

Но почему Вам категорически не нравится простое склеивание:
Код:

"C:\Program Files\ImageMagick-6.8.0-Q16\convert.exe" 1_.jpg 0909_.jpg +append Result.jpg
?
Скрытый текст

pzh2393 01-02-2015 16:09 2464747

Да, это один из возможных вариантов, я даже пробовал ключ позволяющий указать "качество" выходного JPEG.
Но для своих нужд, методом проб, так и не подобрал оптимальный вариант.
Либо выходной файл получается намного большим (примерно в 1,5, иногда в 2 раза) по "весу" (в килобайтах) чем суммарно два его "прародителя", либо уровень искажений при повторном сжатии практически уничтожает все мелкие элементы изображения, что так же нельзя принять как приемлемый результат.

P.S. Кстати, lossless склеивание с этими изображениями все равно не получился бы, поскольку выяснилось что для такой операции необходимо чтобы сторона была кратна 16.

Iska 01-02-2015 19:59 2464860

Цитата:

Цитата pzh2393
я даже пробовал ключ позволяющий указать "качество" выходного JPEG. »

Если не указывать — возьмёт из оригинала. Как и sampling-factor. В выложенных Вами файлах и там, и там — 91% и 1x1, 1x1, 1x1 соответственно.

Цитата:

Цитата pzh2393
Либо выходной файл получается намного большим (примерно в 1,5, иногда в 2 раза) по "весу" (в килобайтах) чем суммарно два его "прародителя", »

Угу, есть нечто такое похожее.

Цитата:

Цитата pzh2393
P.S. Кстати, lossless склеивание с этими изображениями все равно не получился бы, поскольку выяснилось что для такой операции необходимо чтобы сторона была кратна 16. »

Угу. 8 или 16, судя по описаниям. В паре мест удачно обошлись «наращиванием» стороны до нужной кратности и последующей склейкой.

Ну, нет — так нет. Тогда хоть расскажите, как Вы их делаете «с нуля»?

pzh2393 01-02-2015 21:26 2464883

Цитата:

Цитата Iska
Тогда хоть расскажите, как Вы их делаете «с нуля»? »

Надеюсь вопрос касается автоматизации действий, поскольку описывать творческий процесс без показа примеров (картинок) бесполезно, да и есть ли в этом смысл?
Для себя же решил делать следующим образом:
0. Создаем (или уже имеем) набор "базовых" изображений. Мне, например, надо будет сначала нарезать их из векторного формата, скорее всего с доработкой по ходу дела. Именно этой части работы и хотелось избежать склеивая уже когда-то подготовленные изображения.
1. На одном изображении в Фотошоп вручную записываем "action" приводящий к нужному конечному результату с этой картинкой, и сохраняем в PNG или TIFF (главное чтобы формат без потерь).
2. Пакетной обработкой, в том же Фотошоп, обрабатываем все нужные изображения (указав папку источник) записанным "action".
3. ImageMagick или любым другим пакетным образом склеиваем "полукадры", сохраняя исходящим форматом PNG или TIFF.
4. Любым пакетным образом перекодируем полученные "склейки" в JPEG (с подходящей степенью сжатия). Тут уже большой простор для выбора софта.

Собственно, если изображений около 1000, как у меня, это здорово сберегает время и нервы.

Iska 01-02-2015 22:49 2464922

Цитата:

Цитата pzh2393
Надеюсь вопрос касается автоматизации действий, поскольку описывать творческий процесс без показа примеров (картинок) бесполезно, да и есть ли в этом смысл? »

Ну, да, её.

Цитата:

Цитата pzh2393
0. Создаем (или уже имеем) набор "базовых" изображений. Мне, например, надо будет сначала нарезать их из векторного формата, скорее всего с доработкой по ходу дела. Именно этой части работы и хотелось избежать склеивая уже когда-то подготовленные изображения. »

Ясно.

Скрытый текст
pzh2393, у меня возникло ощущение дикого дежавю: мы раньше не общались на подобную тему, имеющую касательство к Photoshop? Может быть, не здесь. Вы никогда ранее не описывали что-либо на похожую тему, так же начиная с нулевого пункта?


Как я понимаю, промежуточные результаты в формате «без потерь качества» не сохранились, остались только Jpeg'и, и посему надо начинать с нуля, да? Тут действительно, можно только посочувствовать. Всё, что можно автоматизировать, Вы уже автоматизировали, а оставшуюся ручную работу ничем не заменишь.

pzh2393 02-02-2015 12:19 2465104

Цитата:

Цитата Iska
Как я понимаю, промежуточные результаты в формате «без потерь качества» не сохранились, остались только Jpeg'и, и посему надо начинать с нуля, да? »

именно.. :(
как говорится "знать бы где упадешь - постелил бы соломки".
кто же знал, что спустя годы могут снова понадобится промежуточные файлы.
Хранили только "исходники" и используемые конечные файлы.


Время: 21:32.

Время: 21:32.
© OSzone.net 2001-