Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Изображение из БД


Автор: Anark1 9.9.2007, 16:04
Необходимо вытащить из BLOB поля текущей записи изображение и загрузить его на форму.
Вот фрагмент кода, который работает для JPEG

Код

#include "Jpeg.hpp"
…
TStream *MyStream;
TJPEGImage *jpg = new TJPEGImage();
…
MyStream = Main->IBLogin->CreateBlobStream(Main->IBLogin->FieldByName("PHOTO"), bmRead);
jpg->LoadFromStream(MyStream);
Photo->Picture->Assign(jpg);
MyStream->Free();


необходимо добиться универсальности. То есть, чтобы изображение могло быть типов .ico, .emf, .bmp, .wmf.
Есть код

Код

TStream *MyStream;
TPicture *Picture;
…
MyStream = Main->IBLogin->CreateBlobStream(Main->IBLogin->FieldByName("PHOTO"), bmRead);
Picture->Graphic->LoadFromStream(MyStream);
Photo->Picture->Graphic->Assign(Picture);
MyStream->Free();

который должен работать универсально для всех типов файлов (используется свойство Picture->Graphic), но вылезает ошибка Access Violation на строке 5.



Автор: Vyacheslav 10.9.2007, 10:55
A Picture создано?

Автор: Anark1 10.9.2007, 19:39
Цитата(Vyacheslav @ 10.9.2007,  10:55)
A Picture создано?

Я так понимаю, не создано. Смотрел на DelphiKingdom, но в BCB Picture = TPicture->Create не существует.
Можно этот оператор на C?
И пользуясь случаем хочу спросить, существуют ли принципиальные отличия в использовании TStream, TFileStream, TMemoryStream?
Фатальна ли ошибка, вызванная использованием неверного класса под конкретную задачу?

Автор: Pori 10.9.2007, 20:09
Отличие в ФС и МС существуют

К примеру для клиента приемлемо использовать TFileStream, на сервере же он совсем ни к чему (используется TMemoryStream),
хотя все будет работать при реализации клиента и сервера на ФС

Автор: Anark1 10.9.2007, 20:59
Цитата(Pori @ 10.9.2007,  20:09)
Отличие в ФС и МС существуют

К примеру для клиента приемлемо использовать TFileStream, на сервере же он совсем ни к чему (используется TMemoryStream),
хотя все будет работать при реализации клиента и сервера на ФС

Хотелось бы услышать более подробное объяснение. В чем отличия классов, их применение.

Автор: Pori 10.9.2007, 21:20
Класс  TFileStream позволяет создать поток для работы с файлами. При этом поток работает с файлом без учета типа хранящихся в нем данных

Класс  TMemoryStream обеспечивает сохранение данных в адресном пространстве. При этом методы доступа к этим данным остаются теми же, что и при работе с файловыми потоками. Это позволяет использовать адресное пространство для хранения промежуточных результатов работы приложения, а также при помощи стандартных методов осуществлять обмен данными между памятью и другими физическими носителями.

Автор: Vyacheslav 11.9.2007, 10:10
Цитата(Anark1 @  10.9.2007,  19:39 Найти цитируемый пост)
Я так понимаю, не создано. Смотрел на DelphiKingdom, но в BCB Picture = TPicture->Create не существует.
Можно этот оператор на C?
И пользуясь случаем хочу спросить, существуют ли принципиальные отличия в использовании TStream, TFileStream, TMemoryStream?

TPicture->Create   это круто smile , тем более, что перед этим Вы без проблем написали
Код

TJPEGImage *jpg = new TJPEGImage();

Кто мешает вам это же проделать с TPicture?
Код

TPicture *Picture = new TPicture()
 
Тем более что в хелпе ясно по английски smile написано
Цитата

Creates a TPicture object.
__fastcall TPicture(void);
Description

Call TPicture indirectly, using the new keyword, to create an instance of TPicture at runtime. TPicture allocates the memory for the picture object and initializes its internal formats. After creating the TPicture object, use the LoadFromClipboardFormat or LoadFromFile method to assign a graphical image to the picture, so that it is available to the application.

Автор: Anark1 11.9.2007, 14:39
Vyacheslav, ступил, но тем не менее с созданным Picture ошибка все та же, на том же месте.

Автор: Vyacheslav 12.9.2007, 10:43
Судя по хелпу все правильно. Исключение вполне ожидаемо
Вы не получите таким образом универсальный код, по-скольку Graphic - это указатель  на один   из объектов дублирующий в конкретном случае один из аналогичные указателей в пропертях Bitmap, Icon , Metafile, только приведенный к абстрактному  классу предку.
Вы правильно поняли, что он необходим для создания универсалного кода, но к сожалению, может использоваться тогда, когда требуемый тип изображения загружен с помощью метода TPicture
LoadFromFile, который по зарегистрированному расширению файла может заренее узнать , что загружается, либо с помощью метода LoadFromClipboardFormat, либо Вы заранее указали что  будете загружать.Из Stream заранее прочитать тип нельзя
Я вижу только один выход: хранить наряду с картинкой в БД в отдельном поде признак типа этой картинки и делать что-то вроде этого
Код

TGraphic* Graphic;
switch(pictureType)
{
     //bitmap
     case 0: Graphic = new TBitmap(); break;
     case 1: Graphic = new TJPEGImage(); break;
     case 2: Graphic = new  TIcon(); break;
     case 3: Graphic = new TMetafile();
     default : throw Exception( "Unknown image type");     
}
Photo->Picture->Graphic->Assign(Graphic);
delete Graphic;
Photo->Picture->Graphic->LoadFromStream(MyStream);

Автор: Anark1 12.9.2007, 21:14
Vyacheslav, меня не очень вдохновляет идея забивать в БД еще и тип файла. Нельзя ли создать временный файл, в который загружать изображение, а потом читать из него функцией LoadFromFile ?

Автор: Anark1 13.9.2007, 22:00
Второй подряд, поднятый мной вопрос, остается без четкого ответа. Это напрягает. При этом я вроде бы четко и понятно формулирую задачу.

Автор: Vyacheslav 14.9.2007, 13:10
Цитата(Anark1 @  12.9.2007,  21:14 Найти цитируемый пост)
Vyacheslav, меня не очень вдохновляет идея забивать в БД еще и тип файла. Нельзя ли создать временный файл, в который загружать изображение, а потом читать из него функцией LoadFromFile ? 

Попробуйте. Но врядли пройдет, поскольку скорее всего тип определяется по  расширению файла. Вы должны создать файл с определенным расширением, а следовательно заранее знать что записано в БД. Можно конечно непосредственно покопаться в хидерах изображений и по ним определить, что записано. А дальше ... дальше тот же switch, потому как создавать файлы с нужным расширением выглядит еще дубовее. Самый простой способ  хранить тип отдельно в БД: реализция проста и понятна.

Добавлено @ 13:14
Цитата(Anark1 @  13.9.2007,  22:00 Найти цитируемый пост)
Второй подряд, поднятый мной вопрос, остается без четкого ответа. Это напрягает. При этом я вроде бы четко и понятно формулирую задачу. 

Вам не кажется, что фраза звучит несколько грубовато. Здесь никто никому не обязан, все функционирует на добровольной основе. А Вы получили вполне четкий ответ, который Вам просто не понравился smile

Добавлено @ 13:22
Могу посоветовать обратиться к пользователю под ником Lena. Кажется, она занималась вопросами хранения и обработки в БД избражений типа bmp и jpg. Может у нее есть более красивое решение.   

Автор: Anark1 14.9.2007, 21:05
Цитата

Вам не кажется, что фраза звучит несколько грубовато. Здесь никто никому не обязан, все функционирует на добровольной основе. А Вы получили вполне четкий ответ, который Вам просто не понравился smile

Vyacheslav, я извиняюсь, если выразился грубо, но по-моему на форуме достаточно людей, свободно в этом разбирающихся. Я реалист и ответ не может мне "нравиться" или "не нравиться". Просто добавлять в и без того "широкую" таблицу еще одно поле - далеко не лучший вариант.
Цитата

Могу посоветовать обратиться к пользователю под ником Lena. Кажется, она занималась вопросами хранения и обработки в БД избражений типа bmp и jpg. Может у нее есть более красивое решение.
      
А со стороны БД я сам могу давать советы  smile 

Лично Вам большое спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)