Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как прочитать WMF-файл из BLOB-поля MDB-файла?  (Прочитано 18447 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Igel
Опытный

ru
Offline Offline
Пол: Мужской

« : 14-11-2005 03:36 » 

Проблема собственно в том, что напрямую я не могу получить изображение из поля таблицы, а приходится сначала сохранять ее на диск.
При чтении напрямую, данные определяются некорректно и говорится, что это не объект TMetaFile.
Записан

Ёжики, это не только ценные шкурки...
Oldy
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 14-11-2005 07:20 » 

Правильно ли указан подтип BLOB поля?
Записан

С уважением, Oldy.
Igel
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 14-11-2005 08:10 » 

А что за подтип? В Access-e как-то не видел подтипов в этом поле.
« Последнее редактирование: 14-11-2005 08:14 от Igel » Записан

Ёжики, это не только ценные шкурки...
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #3 : 14-11-2005 11:23 » 

Не знаком с Дельфей, но на шарпе с этим боролся так: создавал поток к памяти, кидал туда данные из базы и создавать картинку на основе потока. Вот только не знаю, есть ли у вас что-то вроде MemoryStream и можно ли создать картинку из потока данных.
Записан
Igel
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 14-11-2005 12:33 » 

Mouse, можно. Только я не знаю как создать картинку на основе потока. Если можно пример, хоть на чем... буду думать.
Записан

Ёжики, это не только ценные шкурки...
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #5 : 14-11-2005 14:25 » 

На шарпе писать не буду, все равно ничем не поможет. Насколько я смог прочитать, в Дельфе есть класс TMemoryStream. Создаем его, потом пихаем туда массив байтов унаследованным от TStream методом Write(). После этого создаем объект Bitmap, у которого есть метод LoadFromStream(Stream: TStream). Им и пользуемся. Попробуй, если не получится, тогда пиши на каком этапе пробемы возникают.
Кстати тут прозвучало мнение, что можно воспользоваться компонентом dbimage, просто указав ему какое-то свойство. Точнее не знаю, я не узнавал, да и ты наверное уже такую вещь попробовал Ага Да и мне все-таки ближе версия без готовых компонентов Улыбаюсь
Записан
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #6 : 14-11-2005 20:11 » 

Эх, давненько я не брал в руки шашек...  Улыбаюсь  Отвык совсем от Дельфей, но результат все-таки получился.  Улыбаюсь  Ниже привожу пример, читающий данные из файла в поток MemoryStream, а затем создающий и отображающий картинку на основе TJPEGImage. Enjoy Ага

Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  MemoryStream: TMemoryStream;
  FileStream: TFileStream;
  buffer: array [1..65536] of byte;
  jpegImage: TJPEGImage;
  picture: TPicture;
  blockSize: integer;
begin
  FileStream := TFileStream.Create('c:\road.jpg', fmOpenRead);
  MemoryStream := TMemoryStream.Create();
  while (FileStream.Position <> FileStream.Size) do begin
    if (FileStream.Size - FileStream.Position >= 65536) then
      blockSize := 65536
    else
      blockSize := FileStream.Size - FileStream.Position;
    FileStream.ReadBuffer(buffer, blockSize);
    MemoryStream.WriteBuffer(buffer, blockSize);
  end;
  FileStream.Destroy();

  MemoryStream.Position := 0;
  jpegImage := TJPEGImage.Create();
  jpegImage.LoadFromStream(MemoryStream);
  picture := TPicture.Create();
  picture.Graphic := jpegImage;
  Image1.Picture := picture;
end;
« Последнее редактирование: 20-12-2007 17:15 от Алексей1153++ » Записан
Igel
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 15-11-2005 03:38 » 

Тэкс, нечто похожее я делал, но тут существенное отличие:
1. Картинка берется из БД, а не из файла. Из поля BLOB.
2. Используется не BMP и не JPEG, а WMF-файл. С чтением BMP из БД проблем не было.
Записан

Ёжики, это не только ценные шкурки...
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #8 : 15-11-2005 13:30 » 

Разобрался  Улыбаюсь  Дело в том, что в Access'e плюс ко всему храниться какой-то заголовок, который надо отсекать. Вероятно, там указывается путь, откуда была загружена картинка или что-то подобное. Полное описание не привожу, пример все скажет за меня. Все как просили, и Access, и WMF  Ага

* wmf.rar (24.66 Кб - загружено 971 раз.)
« Последнее редактирование: 20-12-2007 17:20 от Алексей1153++ » Записан
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #9 : 15-11-2005 13:45 » 

Еще на ум пришло: в сделанном варианте начало данных картинки определяется по жестко вбитой последовательности байт, что IMHO не совсем правильно. Например, на файлах EMF прога по идее должна накрыться, хотя это и не проверено. В общем сделанное решение далеко от идеала, но общую технику иллюстрирует Ага Если еще будут вопросы - обращайся Улыбаюсь
Записан
Igel
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 16-11-2005 16:59 » 

Разобрался Улыбаюсь Дело в том, что в Access'e плюс ко всему храниться какой-то заголовок, который надо отсекать. Вероятно, там указывается путь, откуда была загружена картинка или что-то подобное. Полное описание не привожу, пример все скажет за меня. Все как просили, и Access, и WMF Ага
Методом тыка у меня получалось следующее: если программно заносить файл в поле (bmp.LoadFromFile('MyWmfFile.wmf')), то потом можно было сохранить из поля и получался полноценный файл. Если же пользоваться свойствами Акцес, то никакими средствами не удавалось получить файл и в зависимости от вставляемых объектов, содержимое поля идентифицировалось по разному.
Если открыть в Акцесе твой пример БД, то видно что значение поля BMP - "Пакет". Если в поле вставить файл BMP, то значение поля будет "Точечный рисунок". Если заносить данные программно, то значение получается "Двоичные данные". Из всего этого сделан был вывод: Когда объект вставляется штатными средствами, то определяется тип ОЛЕ-объекта и заносится идентификатор этого объекта.

Поэтому у меня вопросы:
1. Двоичные данные, определяются по 4-м байтам и только для WMF? Но в поле дописывается еще что-то и в конце. Не помешает это прочитать данные?
2. А  откуда взялись эти константы?
  buff_size = 1024;
  seed_size = 4;
  seed :array [0..3] of byte = ($d7,$cd,$c6,$9a); - это первые 4 байта файла WMf, которые его идентифицируют?

А вообще, СПАСИБО!! На многое открылись глаза. Улыбаюсь)
« Последнее редактирование: 20-12-2007 17:22 от Алексей1153++ » Записан

Ёжики, это не только ценные шкурки...
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #11 : 16-11-2005 22:10 » 

Igel, сам я не пробовал заносить WMFы программно, но что-то мне подсказывает, что при программной записи картинки как потока байт проблем возникать не должно. Если это так, то твой вывод абсолютно верен. При вставке картинки через Access в поле вставляется дополнительная информация. Самое веселое, что информация (назовем ее служебной информацией) дописывается как в начало, так и в конец данных поля. Длина блока служебной информации в начале поля непостоянна и различается для разных файлов. Поле OLE в принципе может хранить любые данные, однако при программной вставке мы пихаем туда массив байтов, а при вставке из Access - обьъект OLE. Что Access подразумевает под объектом OLE - известно только ему (ну и дяде Биллу естественно Ага ), но это понятие явно шире, чем просто двоичное содержимое файла. Из переменной длины информационной части можно предположить, например, что туда пишется путь к файлу, на основе которого создан OLE объект, но это опять же только предположения.

По твоим вопросам:
1. Предполагается, что в поле храняться данные WMF, программа заточена под распознавание только таких файлов. Хвост никак не влияет на отображение картинки. Можно в принципе покопаться в формате объекта OLE  в понимании Access и вычленить также и "эпилог", но уже на откуп постановщику задачи Ага Повторюсь, если нужно только отображать картинки, то на хвост можно забить.
2. Про константы:
   buff_size = 1024 - ну нравяться мне степени двойки, как и любому программисту Улыбаюсь 65536 вроде многовато, 256 показалось мало, для данного примера конечно бы сработало (данные WMF начинаются на 153-м, кажется, по счету байте). В принципе возможна такая ситуация, что размер заголовка больше размера буфера, и это обязательно нужно предусмотреть в рабочем варианте. Если не получится, могу подсказать как Ага
   seed_size = 4 - размер заголовка файла WMF, по которому можно идентифицировать начало данных картинки. Естественно заголовок WMF по размеры явно больше 4 байт, но в данной задаче для идентификации нужных данных 4 байт вполне достаточно.
   seed :array [0..3] of byte = ($d7,$cd,$c6,$9a) - тут ты сам все сказал Ага
Записан
Igel
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 17-11-2005 05:48 » 

Самое интересное, что я почти так уже делал.
Я просто программно запихивал последовательность байтов (файл), и пробовал считать их объектом TMetaFile. Он, гаденыш, ругался. Говорил, что типа данные не мои. С помощью твоей проги, по большому счету ничего не меняется, ведь поток-то получется неизменный( смещение =0), а срабатывает.

И еще интересно, может быть такое, что где-то описан формат вставок в поле ОЛЕ Акцесса или записан первыми байтами размер этой области, или спец - кодами отражается конец?
Кстати, если сбрасывать весь поток в файл, то видно, что он действительно сохраняет путь к файлу аж 2 раза, имя файла и тип видать.
Записан

Ёжики, это не только ценные шкурки...
Mouse
Молодой специалист

ru
Offline Offline

« Ответ #13 : 17-11-2005 07:24 » 

Цитата
Я просто программно запихивал последовательность байтов (файл), и пробовал считать их объектом TMetaFile. Он, гаденыш, ругался
Вот тебе, бабушка, и поле OLE  Отлично
Насчет формата можно сделать просто: запихнуть в поле объект, потом сделать дамп того что получилось (т.е. вместе с информационной частью) на диск. В информационной части наверняка лежит смещение как самой картинки, так и начало данных хвоста. Ну или смещение картинки и ее размер (что вероятнее), хотя на самом деле это считай одно и то же. Исходя из этого делаем следующее: находим во вновь сделанном дампе нашу картинку, смотрим ее смещение. Поскольку ее размер нам известен, считаем смещение хвоста. Получим 3 числа: смещение картинки, ее размер и смещение хвоста. А теперь ищем эти числа в шапке информационной части Улыбаюсь Наверняка хотя бы первые два там будут. Прогнать этот эксперимент для нескольких картинок, и получим номер байта, где лежат нужные нам данные Улыбаюсь Я бы и сам сделал, но у меня Дельфей на работе нет... Попробуй сам, тут проблем возникнуть не должно
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines