Работа с изображениями

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

Работа с изображениями

Сообщение arriah » 15.07.2016 12:26:02

Прошу помощи, уважаемое сообщество :)

Мне надо сделать следующее:

1. Получить изображение с сервера по протоколу http - сделал
2. В зависимости от размера изображения сделать его ресайз - сделал, но возникли проблемы, сейчас буду описывать:)

Вобщем написал данный функционал, начал тестировать - все замечательно работает, и тут программа спотыкается с JPEG error, я так понял ошибка с кодом 53 (попутный вопрос - в случае возникновеня исключений, лазарь как-то мало сообщает подробности, хотя бы код ошибки писал - это где-то настраивается?)

Работаю с TJPGImage, вот кусочек кода:

Код: Выделить всё
procedure TForm1.Button5Click(Sender: TObject);
var
  FileIMG:TImage;
  IMG:TJPGImage;
begin
     srcURL:=copy(srcURL,1,pos('"',srcURL)-1); //получаю url картинки из уже обработанных данных
     srcFileName:=FloatToStr(DateTimeToUnix(now))+'_'+IntToStr(GetCountFiles(DirNews)+1); //генерирую новое название картинки без расширения GetCountFiles - функция возвращает количество файлов в каталоге, чтобы картинки имели название 1,2,3.... DirNews - каталог в котором будут жить картинки
     extFileName:=ExtractFileExt(srcURL); //получаю текущее расширение картинки
     if HTTP.HTTPMethod('GET',srcURL) then begin
      HTTP.Document.SaveToFile(DirNews+'\'+srcFileName+extFileName); //забрал картинку к себе и сохранил на диск
      IMG:=TJPGImage.Create;
      FileIMG:=TImage.Create(Nil);
      IMG.LoadFromFile(DirNews+'\'+srcFileName);
      if IMG.Width>=450 then begin
        scale:=450/IMG.Width;
        FileIMG.Height:=round(IMG.Height*scale);
        FileIMG.Width:=450;
        FileIMG.Canvas.StretchDraw(rect(0,0,FileIMG.Width,FileIMG.Height),IMG);
        If DirectoryExists (DirNews+'\thumbs')=false then ForceDirectories(DirNews+'\thumbs\');
        FileIMG.Picture.SaveToFile(DirNews+'\thumbs\'+srcFileName);
  end;
end;


Но иногда IMG.LoadFromFile(DirNews+'\'+srcFileName) вызывает исключение, с кодом 53 (насколько я смог понять)
Покопавшись немного увидел, что картинка имеет расширение jpg, а сигнатура показывает что это PNG
В компонентах лазаря есть пример работы с TJPGImage - попробовал через нее загрузить проблемную картинку - результат такой же - возникает исключение.
Да, можно конечно обработать экзепшн и забить на картинку, но увы - не выход - картинка должна быть обработана.
Написал функцию, которая анализирует сигнатуру:

Код: Выделить всё
Function TForm1.GetSign(const FileName : string) : string;
Var
   FStream:TFileStream;
   buff: int64;
begin
   result:='';
   buff:=0;
   FStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyRead);
   FStream.Read(buff, sizeof(buff));
   FStream.Free;
   if (buff and $FFFFFF)=$FFD8FF then result := '.jpg';
   if (buff and $FFFFFFFF)=$38464947 then result := '.gif';
   if buff=$0A1A0A0D474E5089 then result := '.png';
end;     


Кусок кода переписал в таком виде:
Код: Выделить всё
     srcURL:=copy(srcURL,1,pos('"',srcURL)-1);
     srcFileName:=FloatToStr(DateTimeToUnix(now))+'_'+IntToStr(GetCountFiles(DirNews)+1);
     extFileName:=ExtractFileExt(srcURL);
     if HTTP.HTTPMethod('GET',srcURL) then begin
        HTTP.Document.SaveToFile(DirNews+'\image.tmp');
     //showmessage(IntToStr(FStream.Read(buff, sizeof(buff))));
     //Обработка картинки
     //создание превью
     IMG:=TJPGImage.Create;
     FileIMG:=TImage.Create(Nil);
     FileType:=GetSign(DirNews+'\image.tmp');
     If (FileType=UTF8LowerCase(extFileName)) or ((UTF8LowerCase(extFileName)='.jpeg') and (FileType='.jpg'))
        then srcFileName:=srcFileName+extFileName else srcFileName:=srcFileName+FileType;
     renamefile(DirNews+'\image.tmp',DirNews+'\'+srcFileName);
     IMG.LoadFromFile(DirNews+'\'+srcFileName);
     if IMG.Width>=450 then begin
        scale:=450/IMG.Width;
        FileIMG.Height:=round(IMG.Height*scale);
        FileIMG.Width:=450;
        FileIMG.Canvas.StretchDraw(rect(0,0,FileIMG.Width,FileIMG.Height),IMG);
        If DirectoryExists (DirNews+'\thumbs')=false then ForceDirectories(DirNews+'\thumbs\');
        FileIMG.Picture.SaveToFile(DirNews+'\thumbs\'+srcFileName);
     end;           
end;

То есть, если сигнатура не совпадает с расширением, то файлу даем расширение согласно сигнатуре
Но все равно получаю исключение.
Попробовал загрузить уже переименованный файл в пример от лазаря - там нормально все загружается.
Может я что-то не учел?
arriah
новенький
 
Сообщения: 85
Зарегистрирован: 29.07.2015 16:42:35

Re: Работа с изображениями

Сообщение DYUMON » 15.07.2016 13:31:29

53 The network path was not found. ERROR_BAD_NETPATH
Аватара пользователя
DYUMON
постоялец
 
Сообщения: 179
Зарегистрирован: 11.03.2009 13:32:54

Re: Работа с изображениями

Сообщение arriah » 15.07.2016 14:40:51

DYUMON писал(а):53 The network path was not found. ERROR_BAD_NETPATH

Ну иногда это может значить и OUT_OF_MEMORY
Касательно TJPGImage - загрузка неверного формата.

Хотя в uses Подключено и LasJPG, LazPNG, LazPNM, LazBMP

кстати, попробовал в TJPGImage загрузить BMP - ситуация та же. Походу он умееет грузить только JPG
arriah
новенький
 
Сообщения: 85
Зарегистрирован: 29.07.2015 16:42:35

Re: Работа с изображениями

Сообщение MysticCoder » 15.07.2016 17:41:49

arriah писал(а): JPEG error, я так понял ошибка с кодом 53 (попутный вопрос - в случае возникновеня исключений, лазарь как-то мало сообщает подробности, хотя бы код ошибки писал - это где-то настраивается?)


В delphi с jpeg та же беда, просто Jpeg Error 53 выдает и все. В интернетах говорят, что такое бывает если файл скачался с интернета с ошибками. Т.е. поврежден. Ну или другой формат под jpeg притворяется. Самый лучший вариант - это использовать библиотеку по загрузке изображений, по типу Vampyre Imaging Library, эти библиотеки анализируют заголовки файла, чтоб определить формат, ну или как сейчас сам определяй.

arriah писал(а): renamefile(DirNews+'\image.tmp',DirNews+'\'+srcFileName);
IMG.LoadFromFile(DirNews+'\'+srcFileName);


Ты здесь переименовал допустим в .png, а пытаешься загрузить его в TJpegImg. По моему TJpegImg вообще не нужен, пользуй TImage, он автоматом может загружать jpeg если модуль Jpeg в uses есть.
MysticCoder
постоялец
 
Сообщения: 118
Зарегистрирован: 14.09.2013 00:20:28

Re: Работа с изображениями

Сообщение pupsik » 15.07.2016 20:25:52

Код: Выделить всё
   buff:=0;
   FStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyRead);
   FStream.Read(buff, sizeof(buff));
Буфер = 0??? Вроде как сигнатура побольше будет... Или ошибаюсь?
pupsik
энтузиаст
 
Сообщения: 1017
Зарегистрирован: 20.08.2014 16:20:13

Re: Работа с изображениями

Сообщение arriah » 19.07.2016 17:45:38

pupsik писал(а):
Код: Выделить всё
   buff:=0;
   FStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyRead);
   FStream.Read(buff, sizeof(buff));
Буфер = 0??? Вроде как сигнатура побольше будет... Или ошибаюсь?

FStream.Read(buff, sizeof(buff)); - buff получит не более 64бит (buff:int64, для заголовка 8 байт достаточно);

MysticCoder писал(а):В delphi с jpeg та же беда, просто Jpeg Error 53 выдает и все. В интернетах говорят, что такое бывает если файл скачался с интернета с ошибками. Т.е. поврежден. Ну или другой формат под jpeg притворяется. Самый лучший вариант - это использовать библиотеку по загрузке изображений, по типу Vampyre Imaging Library, эти библиотеки анализируют заголовки файла, чтоб определить формат, ну или как сейчас сам определяй.

Да, использую библиотеку Vampyre Imaging Library - все нормально
arriah
новенький
 
Сообщения: 85
Зарегистрирован: 29.07.2015 16:42:35


Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru