MSSQL и картинки в нём

Вопросы программирования и использования среды Lazarus.

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

Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

MSSQL и картинки в нём

Сообщение Vadim »

Есть БД MSSQL и в ней, в поле типа image, хранятся небольшие GIF-картинки.
Проблема вот в чём. Хранятся они там не просто так, а каким-то непонятным образом. Вот для примера:
http://files.kraslib.ru/pic/01.jpg
Первые семь байт в этом поле - это нечто, потом идут байты, очень похожие на нормальный GIF, а последние 4 байта - это опять нечто непонятное. Соответственно, если загрузить этот набор байтов себе в программу, никакой картинки не будет.
Если удалить первые 7 байт и последние 4, опять же картинка не получается, вместо реальной картинки выходит какая-то билибирда, т.к. в сравнении с настоящей картинкой там ряд байтов заменены по непонятному мне алгоритму.
Рытьё в интернете понимания мне не принесло. Подскажите кто-нибудь, в чём может быть проблема...
Аватара пользователя
alexs
долгожитель
Сообщения: 4069
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

а чем картинку сохраняешь в БД?
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

alexs
Я не сохраняю. БД досталась уже готовая. К ней была программа, которую писали на Дельфи ещё в 2001 году. С тех пор нет ни исходников, ни программиста, который это писал. Осталась только база, а вот прога на Windows 7 глючит иногда. Причину почему мы так и не выяснили. Хотел прогу переписать на Lazarus.
Аватара пользователя
Vapaamies
постоялец
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург
Контактная информация:

Сообщение Vapaamies »

Да, у MS SQL есть какой-то свой особый формат для картинок, возможно связанный с OLE. Как с ним бороться, не знаю.
Padre_Mortius
энтузиаст
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Сообщение Padre_Mortius »

Vadim, формат поля в базе какой?
Ism
энтузиаст
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Сообщение Ism »

Чтоб наверняка , поставьте MS Access и через ODBC подрубитесь к базе, Акцесс понимает формат Микрософта
Сам с таким сталкивался, для Lazarus для отображения OLE нужен костыль, гдето была процедура
Padre_Mortius
энтузиаст
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Сообщение Padre_Mortius »

Не увидел тип поля... попробуйте преобразовать данное поле в тип binary с помощью convert(binary, FieldName)
По идее этого должно хватить.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Padre_Mortius
Спасибо, сегодня попробую.

Добавлено спустя 8 часов 25 минут 24 секунды:
Padre_Mortius
К сожалению Ваш совет не помог. По всей видимости тип image и тип binary - в mssql одно и то же. На выходе при конвертировании тоже самое, что и без.
pupsik
энтузиаст
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13
Контактная информация:

Сообщение pupsik »

возможно не по теме:

1. судя по гуглению то gif хранятся как отдельные картинки: картинка + № (http://msdn.microsoft.com/en-us/library/aa275080%28SQL.80%29.aspx)

2. http://stackoverflow.com/questions/959160/load-jpg-gif-bitmap-and-convert-to-bitmap х.з. может чет даст.

Хотя, по куску "хекса" судить о ситуации. Барабан нужен боольщщщой... т.е. "мацальный" рефлекс := нет. Осталось гадание.
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

В архиве два файла:
- 3.gif - то, что должно быть на рисунке;
- 3.out - то, что хранится в БД в поле рисунка.
http://files.kraslib.ru/pic/out.zip

Рисунок самый обычный, "одиночный".

Добавлено спустя 3 минуты 17 секунд:
Вопрос вдогонку: кто-нибудь занимался вытаскиванием OLE-объектов из БД? Вполне возможно, что рисунок там хранится в виде OLE-объекта.
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 839
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

Тебе не это случаем нужно?
http://www.codeproject.com/Articles/909 ... ype-in-SQL


Вообще, если в лоб пойти...
у тебя, если посмотришь, оригинал занимает 17 041 байт, а итоговый файл после обработки 17 057 байт. Если откроешь файл в hex редакторе или блокноте, то увидишь что по сравнению с начальным итог отличается наличием в начале и конце приписанных байтов. Судя по статье выше, это маркеры. Если убрать в начале и конце байты то получится размер 17 046.. т.е. еще 5 байт где то сидят(я блокнотом редактировал, может он просто не отображает как символы какие то байты). Если пройдешься сравнением байт, между двумя образцами, то сможешь найти где что не совпадает.

Добавлено спустя 38 минут 32 секунды:
pupsik писал(а):судя по гуглению то gif хранятся как отдельные картинки: картинка

Это как автор БД захочет. К примеру при установке форума на сервак, у админа есть возможность выбирать, как хранить картинки в отдельной папке или же в самой БД.
Padre_Mortius
энтузиаст
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Сообщение Padre_Mortius »

Судя по всему, используется какой-то алгоритм замены байт местами. Очень познавательную разницу выдает команда fc если убрать первые несколько байт до заголовка GIF-файла и после символа двоеточия в конце. Как раз видно, что определенные байты поменяны местами.

Начало очень интересное. (x-1)93 байт меняется местами с (x)93 байтом. И это продолжается достаточно долго (158 повторов). Если нужно, то могу попробовать вскрыть алгоритм данного шифрования. Думаю, что эти "лишние" байты совсем не лишние.
Ism
энтузиаст
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Сообщение Ism »

Vadim писал(а):Вопрос вдогонку: кто-нибудь занимался вытаскиванием OLE-объектов из БД? Вполне возможно, что рисунок там хранится в виде OLE-объекта.

Я делал загон в Access bmp картинок
Так вот OLE поле в картинке добавляет свои заголовки, и если обращаться к OLE полю как просто к набору байтов будет ошибка, нужно извечь из OLE само содержимое картинки, для этого надо знать как убрать заголовки

Как пример с bmp, обратите внимание на head
http://www.c-faq.narod.ru/faq/pic2bmp.html

Код: Выделить всё

procedure SavePictureToDB(p:TPicture);
var str,strb:TMemoryStream;
    h:longint;
    hb:array [1..4] of byte;
    i:integer;
const
head1=#21#28#51#0#2#0#0#0#17#0#14#0#20#0#37#0;
head2='яяяяТочечный рисунок'#0'Paint.Picture';
head3=#0#1#5#0#0#2#0#0#0#7#0#0#0;
head4='PBrush'#0#0#0#0#0#0#0#0#0;
tail1=#0#0#0#0#0#0#0#0;
tail2=#0#0#1#5#0#0#0#0#0#0#0#173#5#254;
begin
   str:=TMemoryStream.Create;
   strb:=TMemoryStream.Create;
   p.Bitmap.SaveToStream(strb);
   str.Write(head1,16);
   str.Write(head2,34);
   str.Write(head3,13);
   str.Write(head4,15);
   h:=strb.Size+26;
   for i:=1 to 4 do begin
     hb[i]:=h mod 256;
     h:=h div 256;
   end;
   str.Write(hb,4);
   strb.Seek(0,soFromBeginning);
   str.CopyFrom(strb,strb.Size);
   str.Write(tail1,8);
   str.Write(tail1,8);
   str.Write(tail1,8);
   str.Write(tail2,14);
   strb.Seek(0,soFromBeginning);
   ADOTablepicture.LoadFromStream(str);
   strb.Free;
   str.Free;
end;


То же самое с Gif и jpg , они пакуются в контейнер со спецзаголовками, чтоб программы на OLE понимали что в контейнере

Добавлено спустя 38 минут 38 секунд:
Посмотрел в HEX редакторе 3,out , не очень похоже на OLE, многие байты в теле изменены, судя по всему побиты окончания строк рисунка и это както связано с заголовком блоба
Вот здесь описание как выдрать файл из OLE http://blogs.msdn.com/b/pranab/archive/ ... bject.aspx

Добавлено спустя 16 минут 27 секунд:
Здесь экспорт из блоба на диск средствами самого MSSQL http://saveadba.blogspot.com/2012/02/ex ... abase.html
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Без вашей помощи никак не обойтись. :-)
Вот что удалось выяснить после обсуждения здесь и дополнительных исследований:
- В поле для картинки хранится именно зашифрованный файл (не OLE :-) );
- Если удалить из файла 1.out (см. прилагаемый архив) 7 первых байт и 4 последних (начало должно быть GIF, конец - точка с запятой), то:
- В 93-ий байт нужно подставлять 1-ый байт из исходного (где первые 7 байт не удалены) файла 1.out;
- начиная с 193 байта нужно менять местами байты с этого места с байтом из 293 места. Т.е. получается файл разделён на блоки по 200 байт (от 0 до 199 включительно) и в этих блоках меняются местами нулевой и сотый байты;
- Выяснилось так же, что такие замены могут быть и не до конца файла, а только до какого-то определённого места.
Как тут уже высказывался Padre_Mortius, последний нюанс может быть скрыт в первых 7-ми байтах (точнее с 1 по 7-ой) или в последних четырёх. Но я сколько в них не пялился, так и не смог понять каким образом. :(
Может кто-нибудь, кто собаку съел на шифровках, сможет помочь?
http://files.kraslib.ru/pic/files.zip
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 839
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

Сделай себе статистику по десятку картинок. Какой байт был, на что поменялся. И посмотри что получается.
Ответить