Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2015.10.04;
Скачать: CL | DM;

Вниз

TPicture.LoadFromFile - интерпритация формата по содержимому.   Найти похожие ветки 

 
Akad   (2011-02-27 16:56) [0]

Есть много картинок. У части из них попутаны расширения, то есть png имеют расширение jpeg, gif - png и так далее.
Как известно в борланде работая над TPicture.LoadFromFile пошли по самому простому пути - интерпретация формата файла по расширению, то есть картинки с не правильным расширением эта функция не загрузит.
Вопрос: как с минимумом телодвижений загрузить картинку в TPicture.Graphic? Очень не хочется самому анализировать и переименовывать файл. Должно же быть нормальное готовое решение!


 
clickmaker ©   (2011-02-27 18:06) [1]

GraphicEx


 
Amoeba_   (2011-02-27 22:19) [2]


> clickmaker ©   (27.02.11 18:06) [1]
>
> GraphicEx

Оно самое тута:
http://www.soft-gems.net/index.php?option=com_content&task=view&id=13&Itemid=33


 
Akad   (2011-03-17 22:36) [3]

А как его включить? Делаю:

uses ..., GraphicEx;
....
Image1.Picture.LoadFromFile("321.tmp"); // Получаю Unknown picture file extention (.tmp)
Image1.Picture.LoadFromFile("321.bmp"); // Получаю bitmap image is not valid.

Оба раза пытаюсь грузить jpeg.


 
brother ©   (2011-03-18 05:39) [4]

нужно создать новый объект (подозреваю TGraphicEx) и в него уже грузить картинки, а не в стандартный:

> Image1.Picture.LoadFromFile("321.tmp"); // Получаю Unknown
> picture file extention (.tmp)
> Image1.Picture.LoadFromFile("321.bmp"); // Получаю bitmap
> image is not valid.

это стандарные ошибки Image те,

> интерпретация формата файла по расширению


 
Amoeba_   (2011-03-18 11:14) [5]


> Akad   (17.03.11 22:36) [3]
>
> А как его включить? Делаю:
>
> uses ..., GraphicEx;

Здесь все делаешь правильно.


> Image1.Picture.LoadFromFile("321.tmp"); // Получаю Unknown
> picture file extention (.tmp)
> Image1.Picture.LoadFromFile("321.bmp"); // Получаю bitmap
> image is not valid.
>
> Оба раза пытаюсь грузить jpeg.
>


Не то что странного, а просто невозможного хочешь. Формат сперва идентифицируется по расширению. Затем уже проверяется сигнатура, и если она не та, то получаешь по лбу.


 
Akad   (2011-03-18 11:20) [6]


> Не то что странного, а просто невозможного хочешь.

Почему не возможного? См. первый пост. 2 человека ответило, что это без проблем делается через GraphicEx.
А вообще говоря мне надо всё это дело из потока грузить, из БД. Ну это уже мелочи, главное научиться нормально загружать картинки. Например из .tmp файла.


 
Dimka Maslov ©   (2011-03-18 11:47) [7]

По сигнатурам файлов вполне возможно отличить джипег от битмапа и пнга.


 
Amoeba_   (2011-03-18 11:54) [8]


> Очень не хочется самому анализировать
> и переименовывать файл. Должно же быть нормальное готовое
> решение!

Хоть и не хочется анализировать и переименовывать, а придется. Готового решения нет.


 
clickmaker ©   (2011-03-18 12:01) [9]

use TGraphicExGraphic


 
clickmaker ©   (2011-03-18 12:04) [10]

+ CanLoad()


 
Akad   (2011-03-18 12:08) [11]


> По сигнатурам файлов вполне возможно отличить джипег от
> битмапа и пнга.

Мне нужно не отличить, а загрузить. Понятно, что можно убить неделю и самому написать нормальные загрузчики, вместо кривых дельфёвых, но подозреваю, что это будет изобретением велосипеда.
Хотя с другой стороны поиск в гугле выводит только на GraphicEx, которая работать у меня отказывается, а во всех их примерах они вместо нормальной загрузки просто определяют что за тип изображения в файле и грузят соответствующим классом. Всё бы ничего, но FileFormatList например не умеет потоки.
Так что похоже всё-же придётся велосипед изобрести. :(


 
Akad   (2011-03-18 12:12) [12]


> use TGraphicExGraphic

Ну тоже с ходу не умеет.
  Graphic := TGraphicExGraphic.Create;
  Graphic.LoadFromStream(stream); //Получаю bitmap image is not valid.

> + CanLoad()

А что это даст? Мне надо загрузить, а не спрашивать может ли он загрузить jpeg.


 
clickmaker ©   (2011-03-18 12:24) [13]

> Мне надо загрузить, а не спрашивать может ли он загрузить
> jpeg.

CanLoad не зря сделана class function для удобства.
Т.е. запросто можно реализовать перебор вызовов TXXXGraphic.CanLoad с последующим созданием подошедшего объекта


 
Akad   (2011-03-18 12:41) [14]


> CanLoad не зря сделана class function для удобства.Т.е.
> запросто можно реализовать перебор вызовов TXXXGraphic.CanLoad
> с последующим созданием подошедшего объекта

Т.е резюме: ни какого преимущества/удобства и пр. GraphicEx не даёт. Всё та же убогость, что и в стандартной поставке дельфи. Просто добавляет немного экзотических форматов картинок и всё.
Неужели не существует нормальных библиотек для работы с графикой в дельфи??? Не верю!


 
Dimka Maslov ©   (2011-03-18 12:45) [15]

Akad   (18.03.11 12:08) [11]

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

Дополнительно сообщу, что
а) в начале bmp находятся два байта BM
б) начиная с 7-го байта в файлах jpg находятся знаки JFIF
в) в начале png со 2-го байта есть символы PNG


 
Amoeba_   (2011-03-18 12:46) [16]


> Неужели не существует нормальных библиотек для работы с
> графикой в дельфи???

Нормальные библиотеки совершенно не обязаны разбираться с бардаком в виде перепутанных расширений. Это никак не входит в круг их задач.


 
Akad   (2011-03-18 12:55) [17]


> Что мешает перед загрузкой файла проверить по сигнатуре
> тип файла, дать ему (или копии) правильное расширение, а
> потом загрузить файл обычным порядком?

В том-то и дело, я надеялся на то, что
Во-первых не придётся изобретать велосипед.
Во-вторых например с тем-же jpeg не всё так просто. Надо первые 2 байта смотреть, а потом идти по SOI/EOI что бы убедиться, что это jpeg, а не например mpeg или mjpeg или что-нибудь подобное. В общем это далеко не минута по времени написания кода.

> Нормальные библиотеки совершенно не обязаны разбираться
> с бардаком в виде перепутанных расширений. Это никак не
> входит в круг их задач.

Обязаны. Нормальные библиотеки обязаны грузиться из потока. А там расширений нет. В прочем как и нет нормальных библиотек для открытия картинок под дельфи, на сколько я понял...


 
clickmaker ©   (2011-03-18 13:09) [18]

> Неужели не существует нормальных библиотек для работы с
> графикой в дельфи??? Не верю!

у тебя есть шанс стать первым и войти в историю. Тем более, что не с нуля придется начинать


 
sniknik ©   (2011-03-18 13:55) [19]

> обязаны грузиться из потока.
но ты грузишь почему то с файла... библиотека виновата?


 
Dimka Maslov ©   (2011-03-18 14:09) [20]


> общем это далеко не минута по времени написания кода.


А я вот всегда замечал, что к коде, написанном за минуту, больше удельное число ошибок на один байт, нежели в коде, написанном за час.


 
Akad   (2011-03-18 15:11) [21]


> но ты грузишь почему то с файла... библиотека виновата?

Где я такое написал? У меня все файлы из web перекачёвывают в БД.

P.S. Ладно. Обошёл я эту кривость дельфи и всех сторонних приблуд к ней с помощью анализа трафика. Вопрос закрывается, так как нормального решения не имеет.


 
Amoeba_   (2011-03-18 17:01) [22]


> кривость дельфи и всех сторонних приблуд к ней

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


 
clickmaker ©   (2011-03-18 17:08) [23]

а я вообще не понял, как "как с минимумом телодвижений загрузить картинку в TPicture.Graphic?" связано с "Обошёл я эту кривость дельфи и всех сторонних приблуд к ней с помощью анализа трафика" и "У меня все файлы из web перекачёвывают в БД"?


 
Соискатель   (2012-03-30 13:41) [24]


> То, что сперва проверяется расширение файла, а только потом
> он открывается и считывается (а если его формат не соответствует
> ожидаемому только тогда следует ругань) - это как раз стандарт.
>

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


 
Соискатель   (2012-03-30 13:42) [25]

Библиотек мало, потому что язык не тот и не в топе


 
Кщд   (2012-03-30 15:26) [26]

>Соискатель   (30.03.12 13:42) [25]
толсто


 
DVM ©   (2012-03-30 16:29) [27]


> Akad   (27.02.11 16:56) 

Ищешь сигнатуры известных форматов и по аналогии с:

class function TMimeType.GuessContentTypeFromContent(AContent: PAnsiChar): string;
var
 c1, c2, c3, c4, c5, c6, c7, c8: AnsiChar;
begin
 c1 := AContent[0];
 c2 := AContent[1];
 c3 := AContent[2];
 c4 := AContent[3];
 c5 := AContent[4];
 c6 := AContent[5];
 c7 := AContent[6];
 c8 := AContent[7];
 result := "";
 if (c1 = "G") and (c2 = "I") and (c3 = "F") and (c4 = "8") then
   result := "image/gif"
 else if (c1 = "#") and (c2 = "d") and (c3 = "e") and (c4 = "f") then
   result := "image/x-bitmap"
 else if (c1 = "!") and (c2 = " ") and (c3 = "X") and (c4 = "P")
   and (c5 = "M") and (c6 = "2") then
   result := "image/x-pixmap"
 else if (c1 = #137) and (c2 = #80) and (c3 = #78) and (c4 = #71) and (c5 = #13)
   and
   (c6 = #10) and (c7 = #26) and (c8 = #10) then
   result := "image/png"
 else if (c1 = #$2E) and (c2 = #$73) and (c3 = #$6E) and (c4 = #$64) then
   result := "audio/basic" // .au format, big endian
 else if (c1 = #$64) and (c2 = #$6E) and (c3 = #$73) and (c4 = #$2E) then
   result := "audio/basic" // .au format, little endian
 else if (c1 = "<") then
 begin
   if ((c2 = "!")) or
     ((c2 = "h") and (c3 = "t") and (c4 = "m") and (c5 = "l")) or
     ((c2 = "h") and (c3 = "e") and (c4 = "a") and (c5 = "d")) or
     ((c2 = "b") and (c3 = "o") and (c4 = "d") and (c5 = "y")) or
     ((c2 = "H") and (c3 = "T") and (c4 = "M") and (c5 = "L")) or
     ((c2 = "H") and (c3 = "E") and (c4 = "A") and (c5 = "D")) or
     ((c2 = "B") and (c3 = "O") and (c4 = "D") and (c5 = "Y")) then
     result := "text/html"
   else if (c2 = "?") and (c3 = "x") and (c4 = "m") and (c5 = "l") and (c6 =
     " ") then
     result := "application/xml";
 end
 else if (c1 = #$FF) and (c2 = #$D8) and (c3 = #$FF) and (c4 = #$E0) then
   result := "image/jpeg"
 else if (c1 = #$FF) and (c2 = #$D8) and (c3 = #$FF) and (c4 = #$EE) then
   result := "image/jpg"
 else if (c1 = "R") and (c2 = "a") and (c3 = "r") and (c4 = "!") then
   result := "application/x-rar"
 else if (c1 = "F") and (c2 = "W") and (c3 = "S") then
   result := "application/x-shockwave-flash"
 else if (c1 = "M") and (c2 = "S") and (c3 = "C") and (c4 = "F") then
   result := "application/cab"
 else if (c1 = "M") and (c2 = "Z") then
   result := "application/x-msdos-program"
 else if (c1 = "P") and (c2 = "K") and (c3 = #$03) and (c4 = #$04) then
   result := "application/zip"
 else if (c1 = "B") and (c2 = "M") then
   result := "image/bmp";
end;


 
DVM ©   (2012-03-30 16:30) [28]

У этого подхода даже название есть какое то, но я забыл его.


 
Anatoly Podgoretsky ©   (2012-03-30 16:55) [29]

С HTML так не пойдет, совсем не обязательно что это первые символы текста.


 
DVM ©   (2012-03-30 17:00) [30]


> Anatoly Podgoretsky ©   (30.03.12 16:55) [29]

Да я ясное дело, но лучше хоть что-то, чем вообще ничего.

Вот кстати куча сигнатур http://mark0.net/download/triddefs_xml.rar


 
brother ©   (2012-03-30 18:58) [31]

> С HTML так не пойдет,

не понял, о чем речь? сигнатуры отменили?


 
Anatoly Podgoretsky ©   (2012-03-30 19:26) [32]


> не понял, о чем речь? сигнатуры отменили?

Сигнатура когда опрделеный текст в определеном месте, для HTML ни одно из условий не выполняетсяю


 
Dimka Maslov ©   (2012-03-30 19:51) [33]

РОБЯТО! Посмотрите на дату первого поста этой темы! Вопрос закрыт год назад!


 
Anatoly Podgoretsky ©   (2012-03-30 20:05) [34]

Ты зря думаешь что закрыт, как видели это вопрос на протяжение десятка лет, так и будем видеть еще.


 
brother ©   (2012-03-30 21:01) [35]

> для HTML ни одно из условий не выполняетсяю

я не понял о чем речь?


 
Anatoly Podgoretsky ©   (2012-03-30 21:09) [36]

> brother  (30.03.2012 21:01:35)  [35]

Не совпадает в части местоположения сигнатуры


 
brother ©   (2012-03-30 21:27) [37]

> местоположения сигнатуры

а понял! почемуже нет?:
<!DOCTYPE
местоположение вполне точно определено


 
brother ©   (2012-03-30 21:29) [38]

> С HTML так не пойдет,

впрочем, разговор шел про графические файлы и их сигнатуры. Я потому и не въехал сразу о чем речь ;)


 
Anatoly Podgoretsky ©   (2012-03-30 21:45) [39]

> brother  (30.03.2012 21:27:37)  [37]

<!DOCTYPE

Вставляют генераторы, люди редко, учитывая поголовное “воровство” и это не
срабатывает, сайты тупо вставляют свой текст в начале текста, и это часто не
html или <!DOCTYPE


 
brother ©   (2012-03-31 05:56) [40]

мы говорим - сайт должен отвечать спецификации html!
они говорят - зачем? браузер же "кушает" наш код?!

зы. но всеж спецификация есть и ее надо придерживаться...


 
Anatoly Podgoretsky ©   (2012-03-31 08:16) [41]

Ну правильно говоришь, и большинство браузеров прощают это. Например по спецификации каждый тег <TEG> должен быть закрыт </TEG>, а в реальности не так и много хуже. Поэтому определять по сигнатуре HTML гнилое дело. При проверке нужна ветвь ELSE


 
brother ©   (2012-03-31 19:48) [42]

> по спецификации каждый тег <TEG> должен быть закрыт </TEG>

нет не каждый... например: Тег <IMG>
http://html.manual.ru/book/html/body/objects/img.php
не имеет конечного тега.


 
Anatoly Podgoretsky ©   (2012-04-01 19:20) [43]

</>


 
brother ©   (2012-04-01 20:29) [44]

> </>

это для XHTML
а для HTML закрывающий тэго не нужен...


 
Unknown user ©   (2012-04-04 17:48) [45]

Я когда-то давно писал собственную функцию для определения типа файла по сигнатуре. Если еще нужно, забирайте.

function DetermineFileType(const FileName:string; var DT:TDataType):boolean;
//елементы массива расположены в порядке
//уменьшения ошибки ложного определения типа файла
const ChkTypes:array[0..6] of TDataType=(dtRTF,dtIMG_EMF,dtIMG_BMP,
                                        dtIMG_JPG,dtIMG_WMF,dtTXT,dtIMG_ICO);
var Stream:TFileStream;
   Ind:integer;
   
function IsType(AType:TDataType):boolean;
const cRTFSignature="{\rtf1";
      cBMPSignature="BM";
      cJPGSignature="яШя";
      cEMFSignature=" EMF";
      MaxReadCnt=8192;
var Len,Cnt,TotalCnt:integer;
    Sym,OldSym:Char;
    S:string; Wrd:Word;
    DWrd:LongWord;

begin
 Result:=false;
 Stream.Position:=0;
 case AType of

  dtRTF: begin
          Len:=Length(cRTFSignature);
          SetString(S,nil,Len);
          Cnt:=Stream.Read(Pointer(S)^,Len);
          if Cnt<>Len then exit;
          Result:=S=cRTFSignature;
         end;

  dtTXT: begin
          TotalCnt:=0; OldSym:=#0;
          while TotalCnt<MaxReadCnt do
           begin
           Len:=SizeOf(Sym);
           Cnt:=Stream.Read(Sym,Len);
           if Cnt<>Len then exit;
           if Sym=#10 then begin
            Result:=OldSym=#13;
            if not Result then exit;
           end; {if}
           OldSym:=Sym;
           Inc(TotalCnt,Cnt);
          end; {while}
         end;

   dtIMG_BMP: begin
               Len:=SizeOf(Wrd);
               Cnt:=Stream.Read(Wrd,Len);
               if Cnt<>Len then exit;
               Result:=Wrd=$4D42;
              end;

   dtIMG_JPG: begin
               Len:=Length(cJPGSignature);
               SetString(S,nil,Len);
               Cnt:=Stream.Read(Pointer(S)^,Len);
               if Cnt<>Len then exit;
               Result:=S=cJPGSignature;
              end;

   dtIMG_WMF: begin
               Stream.Seek(4,0);
               Len:=SizeOf(Wrd);
               Cnt:=Stream.Read(Wrd,Len);
               if Cnt<>Len then exit;
               Result:=(Wrd=$0300) or (Wrd=$0100);
              end;

   dtIMG_EMF: begin
               Stream.Seek(40,0);
               Len:=Length(cEMFSignature);
               SetString(S,nil,Len);
               Cnt:=Stream.Read(Pointer(S)^,Len);
               if Cnt<>Len then exit;
               Result:=S=cEMFSignature;
              end;

   dtIMG_ICO: begin
               Len:=SizeOf(DWrd);
               Cnt:=Stream.Read(DWrd,Len);
               if Cnt<>Len then exit;
               Result:=DWrd=$10000;
              end;

 end; {case}
end; {function IsType}

begin
Stream:=TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
try
 Result:=false;
 for Ind:=0 to High(ChkTypes) do
  if IsType(ChkTypes[Ind]) then begin
   DT:=ChkTypes[Ind];
   Result:=true;
   exit;
  end;
finally
 Stream.Free;
end;
end;



Страницы: 1 2 вся ветка

Текущий архив: 2015.10.04;
Скачать: CL | DM;

Наверх




Память: 0.61 MB
Время: 0.006 c
2-1400138594
Walter White
2014-05-15 11:23
2015.10.04
Вопрос по работе с Move


15-1423863064
Юрий
2015-02-14 00:31
2015.10.04
С днем рождения ! 14 февраля 2015 суббота


15-1424381404
Юрий
2015-02-20 00:30
2015.10.04
С днем рождения ! 20 февраля 2015 пятница


4-1273682403
zamtmn
2010-05-12 20:40
2015.10.04
в SysTreeView32 не приходит WM_CONTEXTMENU


15-1424035886
Юрий
2015-02-16 00:31
2015.10.04
С днем рождения ! 16 февраля 2015 понедельник