Сжатие JPEG и наложение на него водяного знака




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

54 Comments

  1. ЗАК

    А исходники публиковать не будешь ? 🙂

    Reply
  2. maxpiter

    Чтобы исходники выкладывать, надо их причесывать, чтобы не стыдно за них было 🙂

    Reply
  3. zuza

    (3) Спасибо, то что нужно.

    Reply
  4. Armando

    Смотрю, последнее время тема стала актуальна 🙂

    Интерактивная обрезка изображений в 1С:Предприятие 8

    IMAGE RESIZE

    Reply
  5. DoctorRoza

    Старина! 🙂 Давай исходники, хоть криво и косо написанные, зато до ума доведем! 😉

    Reply
  6. CheBurator

    ну тогда заодно сделал бы ключяи дл яполучения размеров исходного изображения (хотя и штатно можно получить)

    Reply
  7. maxpiter

    to CheBurator

    не понял че за ключи? чтобы передавать значение имеющегося изображения что ли?

    размер исходного изображения получаю внутри программы и в зависимости от того какая сторона больше по той и уменьшаю до заданного размера в ключ3 или ключ4, а вторую сторону пропорционально.

    Код в понедельник залью.

    Reply
  8. maxpiter

    (1) (5) исходники на Delphi7 в архиве. Если сделаете из исходников dll которая в 1С будет цепляться, цены вам не будет 😉

    Reply
  9. markers

    Всё это конечно замечательно, но к сожалению без танцев с бубном (Точней с COM`ом) запустить внешнее приложение под Сервер 1С низя 🙁 а иногда это бывает очень нужно. + Что тоже тупо нельзя под сервер 1С использовать ВК. 🙁 Тока COM`ы а сами понимаете что 1С не идеальна в плане возможностей… 🙁

    Reply
  10. maxpiter

    (9) а зачем запускать данное приложение под сервер 1С? (хотя оно и должно запуститься)

    Подразумевается, что эта … как ее назвать, «штука», обрабатывает картинку по ключам. Ее можно запустить из 1С или через батник, или еще как хочешь, главное ключи передать.

    Тут я немного другую цель преследую, нежели запуски под сервер 1С 🙂

    Reply
  11. markers

    (10) Да я понимаю что другие цели, это просто наболело (крик души) что хотелось бы запускать приложения под сервером 1С, а низя (Ни там батник ни через что-то другое, только через вызов COM объекта VBScript и скармливая скрипт запускающий приложение, и то не нашёл как запустить с ожиданием выполнения) По этому тривиальную задачу запустить распаковку архива и подождать пока распакуется архив (Не обязательно ZIP) под сервером 1С пришлось реализовывать через одно место. Вам в любом случае +

    ЗЫ: Под сервером 1С я понимаю регламентное задание выполняемое на сервере 1С

    Reply
  12. markers

    Как пример зачем мне эта прога под сервером 1С, у меня в номенклатуру загружаются фотки с сайта нашего, но они большиватые для 1С (много места занимают), делать скриптом автоизменение размеров картинки и складывание в отдельную папку не очень удобно и пр, а так-бы можно было сделать вызов автоизменения размера при загрузке в базу при помощи вашей проги или аналогов.

    Reply
  13. maxpiter

    (11) по работе с архивами, может поможет:

    Работа с zip-архивами с помощью UtilZip.dll. http://infostart.ru/public/20800/

    вообще, немного не понятно, что вы имеет ввиду под «сервер 1С» — это в вашем понимании выделенный сервер на котором крутится база 1С или это приложение «сервер 1С» для 8 ?

    Reply
  14. maxpiter

    (12) по хорошему, нужно из exe сделать dll и тогда с ней будет намного приятнее работать.

    Постараюсь сделать из нее библиотеку и более правильный код.

    Reply
  15. markers

    (13) Чистая поддержка Зип есть и внутри 8-ки (вроде и под сервером работает), но мне надо было реализовать автораспаковку заказов клиентов которые могут быть пожаты и в RAR и прочие… Речь о сервере идёт в том ключе что когда 1С 8 работает с БД например MS SQL Server она работает через Сервер 1С и регламентные задания выполняются именно на сервере 1С в котором реализованы не все процедуры и функции что реализованы в клиенте 1С. Что накладывает определённые проблемы.

    Reply
  16. markers

    К примеру ЗапуститьПриложение() КомандыСистемы() не реализованы под сервером 1С

    Reply
  17. Душелов

    +(15) и внешние компоненты не работают в контексте сервера

    Reply
  18. maxpiter

    (15) а такой код там будет работать?

    код под 7ку, на 8ке сходу не знаю как написать, но переделать наверно не проблемно.

    exe = Создатьобъект(«WScript.Shell»);

    exe.EXEC(«calc.exe»);

    exe=0;

    или WScript.Shell тоже относится к ВК?

    Reply
  19. markers

    (18) Почти такой код будет работать, но насколько я помню он без ожидания! Т.е. запустил и пошёл в 1С код дальше…. а хотелось бы уж если пользоватся комом с ожиданием выполнения.

    Reply
  20. markers

    (17) Да, я писал об этом выше, я вообще не понимаю 1С ну ладно вы в целях безопасности или ещё чего запретили вызов внешних приложений, но зачем использование ВК обламывать? 🙁 Может в тех целях что будут юзать Вкашки и внешние приложения с интерфесом пользователя и ожиданием команды от него, но коли уже программист пишет для сервера 1С я думаю он должен догадыватся что если он будет использовать ВК требующее взаимодействие с пользователем оно просто «повиснет»… Вообщем не понимаю я 1С. Вещь (регламентные задания они придумали классную (Юзаю в доль и попирёк)), но как-то недоработали её… Ах, а чего только бы нельзя было сделать в регламентном!!!! *мечтательно*

    Reply
  21. maxpiter

    (19) да, без ожидания, но для конвертации картинки этого будет достаточно.

    Можно повесить цикл до 1000 и проверять в нем, не появился ли новый файл.

    Если не появится, то можно куда-нибудь послать уведомление, что где-то косяк.

    Понимаю что с циклом не красиво, но при небольших количествах изображений, может и подойдет.

    Reply
  22. markers

    (21) в таких ситуациях считаю использование ком неоправданным, уж лучше тогда как у меня сделано (тоже криво) стоит программа nnCron которая следит за изменением определённой папки, 1с туда ложит архив и так-же в цикле ждёт, nnCron увидев архив тут же его распоковывает 7zипом (Он поддерживает тучу архивов включая RAR), 1С переодически с задержками смотрит появились ли файлы, если появились перестаёт циклить и начинает их обрабатывать дальше.

    Reply
  23. markers

    Продолжение (22), просто в моём случае nnCron используется и так постоянно, следовательно я не буду тратить лишних ресурсов и т.д. на открытие в 1С COM

    Reply
  24. maxpiter

    (23) вот с ожиданием завершения

    Функция Ждемс()

    exe = СоздатьОбъект(«WScript.Shell»);

    exe.Run(«calc.exe»,1,1);

    exe = 0;

    Возврат 1;

    КонецФункции

    Процедура Сформировать()

    Сообщить(Ждемс());

    КонецПроцедуры

    Reply
  25. maxpiter

    а еще лучше вот так, чтобы не завешивать сервер 🙂

    Перем Процесс;

    Процедура Сформировать()

    exe = СоздатьОбъект(«WScript.Shell»);

    Процесс = exe.Exec(«calc.exe»);

    КонецПроцедуры

    Процедура Проверка()

    Если Процесс.Status =0 Тогда

    Сообщить(«Работает»);

    Иначе

    Сообщить(«Отработал»);

    КонецЕсли;

    КонецПроцедуры

    Reply
  26. markers

    (25, 26) Спасибо за варианты, правда «Перем Процесс;» нельзя использовать в общем модуле, тока в обработках и т.д. Но всё-равно спасибо!

    Reply
  27. maxpiter

    (27) ну я же как примеры только, да и на 7ке 🙂

    Reply
  28. Abadonna

    (0)

    если кто-то сделает из нее dll, чтобы она в 1С цеплялась

    Присобачил к http://infostart.ru/public/59436/#postform (пост 197)

    Изменение размеров в соответствии с выбранным масштабом и изменение качества сжатия

    (CompressionQuality)

    Ты бы, кстати, у себя тоже приделал:

    jpg.CompressionQuality := Q;// от 1 до 100
    jpg.DIBNeeded;
    jpg.Compress;
    jpg.SaveToFile(ВыходнойФайл);
    

    P.S. И, имхо, лучше не задавать отдельно Ширину и Высоту (а то накосячат непропорциональных), а просто масштаб числом

    Reply
  29. maxpiter

    (29) здорово

    >> P.S. И, имхо, лучше не задавать отдельно Ширину и Высоту (а то накосячат непропорциональных), а просто масштаб числом

    при изменении размеров, проверяю, какая сторона больше, то значение и использую, так что, не накосячат 🙂

    Reply
  30. Abadonna

    (30) Зато с масштабом один параметр убирается, что тоже неплохо 😉

    Reply
  31. maxpiter

    Сделал таки DLLку 🙂

    Reply
  32. gerasan

    Почему-то DLL-ка в 8-ке выдает сообщение:ImgResize : Access violation at address 0A6333A2 in module ‘ImgResize.dll’. Read of address 00000001.

    Reply
  33. maxpiter

    (33) Вы все флаги передаете?

    Я не делал проверку на неверно переданные параметры.

    Скорее всего проблема в этом.

    Reply
  34. gerasan

    Спасибо! Получилось!

    Код в итоге такой:

    ПутьКФайлам = «D:111111333»;

    Картинка = «big.JPG»;

    НоваяКартинка = «sm.jpg»;

    ВодянойЗнак = «watermark.png»;

    ВысотаК = 400;

    ШиринаК = 275;

    ЗагрузитьВнешнююКомпоненту(ПутьКФайлам + «»+»ImgResize.dll»);

    ИМЖ = Новый («AddIn.ImgResize»);

    ф1 = ПутьКФайлам + «» + Картинка;

    ф2 = ПутьКФайлам + «» + НоваяКартинка;

    ф3 = ПутьКФайлам + «» + ВодянойЗнак;

    ИМЖ.ПережатьФайл(ф1, ф2, ВысотаК, ШиринаК, ф3);

    Проблема была в том, что имя файла водяного знака было с пробелом: ВодянойЗнак = «watermark.png «;

    Reply
  35. anc2002

    Программа взята за основу в обработке картинок на живой базе, помогает при загрузке изображений в базу данных, автору респект

    Reply
  36. maxpiter

    (36) и вам спасибо за отзыв 🙂

    Reply
  37. osavv

    (37) скажите пожалуйста, в какое место картинки вы ставите водный знак?

    Reply
  38. maxpiter

    (38) по центру

    Reply
  39. osavv

    (39) а как сделать так, чтобы водный знак располагался в правом нижнем углу

    Reply
  40. maxpiter

    (40) в данной скомпилированной версии никак.

    Исходники на Delphi 7 прилагаются. Там есть закоментированный кусок по установке координат, посмотрите, может получится.

    Reply
  41. osavv

    в каком файле исходники? может в файле JPGResize.zip?

    просто при попытке скачать JPGResize.zip — скачивается почему-то ImgResize.zip, в котором лежит библиотека

    Reply
  42. maxpiter

    (42) перезалил исходники на dll, странно что они подменились на другой файл. 19.07.10 судя по комментам там все таки исходники были 🙂

    Reply
  43. pumbaE

    Извините, но правда дороже.

    http://www.imagemagick.org/script/ImageMagickObject.php мощный функционал, делай с картинками что хочешь и как хочешь. Также спокойно подключается к 1C.

    Труд, то хороший, но при выборе между вашим вариантом с исходниками, с определенным функционалом и imagemagick тоже с исходниками и с еще большим функционалом я бы выбрал imagemagick.

    P.s.: не качал но осуждаю :). Извините если, что за резкий тон.

    Reply
  44. osavv

    огромное спасибо!!!

    скачалось, буду разбираться

    Reply
  45. maxpiter

    (44) вот если бы, вы эту ссылку дали в июле 2010 года, то ничего бы этого не было, потому как никто до вашего коммента, ранее не давал эту ссылку.

    также функционал этой публикации использован здесь http://infostart.ru/public/59436/

    так что у каждого своя правда 🙂

    осуждения здесь выражаются минусами 🙂

    спасибо за ссылку.

    Reply
  46. pumbaE

    Не посмотрел «дата начала публикации», по правде сказать в 2010 году imagemagick для работы com требовал ручной сборки и только в 2011 они сделали инсталятор…

    Reply
  47. Dima_Mazhor

    Потратил последний рубль на скачку exe файла, а надо было ддлку блин)) Сейчас мучаюсь, подскажите пожалуйста допустим батник с таким содержанием JPGResize.exe «1.jpg» «2.jpg» 100 100 «ttt.png» ошибок не выскакивает файл запускается но ничего не делается.

    Reply
  48. MartyNSK

    +, еще бы прозрачность водяного знака добавить)

    Reply
  49. maxpiter

    (49) Прозрачность регулируете с помощью файла png 🙂

    Reply
  50. MartyNSK

    (50)=) Это ясно, однако центровка странная, я прозрачность сделал у пнг файла, фона нет, исходное изображение 1024х768, водяной знак тоже 1024х768(нет фона, прозрачность 20), встала на центр левым верхним краем, во вложении тот же логотип, но размер 200х300.

    Reply
  51. maxpiter

    (51) файл png не нужно делать размером с исходную картинку.

    Я как-то даже не предполагал что такое кто-то будет делать 🙂

    Обычно файл watermark имеет минимально необходимый размер, так как его можно располагать не только по центру но и скажем по синусоиде 🙂 или рандомно по области картинки.

    Reply
  52. maxpiter

    (48) попробуйте указать полные пути к файлам. Если конечно еще актуально 🙂

    Reply
  53. 7OH

    А без файлов можно сделать ?

    Чтобы на клиенте при выводе фоток из базы добавлять watermark.

    Reply
  54. maxpiter

    (54) 7OH, добрый день.

    В каждом случае это очень индивидуально. В какое ПО вы подключаете dll, каким образом выдаются картинки…

    Исходники во вложении. Доработкой этой dll заниматься не планирую.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *