Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

Видеокурс программиста и крэкера 5D 2O17
(актуальность: декабрь 2O17)
Свежие инструменты, новые видеоуроки!

  • 400+ видеоуроков
  • 800 инструментов
  • 100+ свежих книг и статей

УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

БОЛЬШОЙ FAQ ПО DELPHI



Двоичный файл с набором изображений

Автор: Ed Jordan

Может кто-либо обеспечить меня хорошим примером как сохранить множество изображений в единственном бинарном файле?

Хорошо, вот пример. Я не могу сказать что это лучшее решение, но это работает. Я надеюсь данный совет побудит моих читателей придумать более мудрое решение, коротое я потом и опубликую.

Данный пример помещает вашу запись в объект. Хотя это и не было строго необходимым, я сконфигурировал алгоритм имеенно так, потому что рано или поздно вы это сделаете... В качестве средства для чтения и записи он использует потоки. Возможно вы уже использовали потоки, поэтому моя технология не будет для вас открытием. Одно из преимуществ использования потока в том, что для работы с графическими объектами -- bitmap, icon, metafile -- можно использовать методы SaveToStream и LoadFromStream.

У меня была проблема с использованием LoadFromStream, и она была похожей на вашу. При вызове Graphic.LoadFromStream, графика "оставляла" позицию потока с самом его конце, а не в конце записи. Другими словами, если графический объект первый раз записывал себя в поток, данные заканчивались в позиции 247. Но когда графический объект "читал себя", он не останавливался в позиции 247, а читал себя из всего потока. Поэтому мог быть прочитан только один объект.

Мое решение проблемы заключается в установке позиции, на которой действительно заканчивается запись. Затем, после того как графический объект прочтет себя из потока, я снова перемещаю позицию, готовля тем самым поток для чтения следующего объекта. Эти детали делают реализацию объекта чуть сложнее. Вот и вот, код смотрите ниже.

Кое-то еще: я сделал объект, способным обрабатывать иконки, метафайлы, а также простые изображения. Не знаю, понадобиться ли вам это, и может быть я выбрал не самое элегантное решение...


 unit Unit2;
 
 interface
 uses Graphics, Classes;
 
 type
   TAlbumRec = class
   private
     FGraphic: TGraphic;
     FDescription: string; { ...Просто пример поля }
     FItemType: ShortInt;  { ...Просто пример поля }
     procedure SetGraphic(AGraphic: TGraphic);
   public
     constructor Create;
     destructor Destroy; override;
     procedure LoadFromStream(Stream: TStream);
     procedure SaveToStream(Stream: TStream);
     property Graphic: TGraphic read FGraphic write SetGraphic;
     property Description: string read FDescription write FDescription;
     property ItemType: ShortInt read FItemType write FItemType;
   end;
 
 implementation
 
 constructor TAlbumRec.Create;
 begin
   inherited Create;
 end;
 
 destructor TAlbumRec.Destroy;
 begin
   FGraphic.Free;
   inherited Destroy;
 end;
 
 procedure TAlbumRec.LoadFromStream(Stream: TStream);
 var
   GraphicTypeCode: Char;
   EndPosition: LongInt;
 begin
   { Считываем в потоке позицию где заканчивается запись... }
   Stream.Read(EndPosition, SizeOf(EndPosition));
 
   { Считываем в Delphi 1.0 строку... }
   Stream.Read(FDescription[0], SizeOf(Byte));
   Stream.Read(FDescription[1], Byte(FDescription[0]));
 
   { Читаем целое... }
   Stream.Read(FItemType, SizeOf(FItemType));
 
   { Считываем код, сообщающий тип графического объекта,
   который необходимо создать... }
   Stream.Read(GraphicTypeCode, SizeOf(GraphicTypeCode));
 
   { Освобождаем текущий графический объект и пересоздаем его.. }
   FGraphic.Free;
   FGraphic := nil;
   case GraphicTypeCode of
     'B': FGraphic := TBitmap.Create;
     'I': FGraphic := TIcon.Create;
     'M': FGraphic := TMetafile.Create;
   end;
 
   { Загружаем из потока графику... }
   if FGraphic <> nil then
     FGraphic.LoadFromStream(Stream);
 
   { Ищем в потоке конечную позицию для данной записи. Почему мы это делаем?
   Я обнаружил это, когда графический объект читал себя из потока, и при этом
   "оставлял" позицию потока с самом его конце, а не в конце записи. Поэтому
   мог быть прочитан только один объект... }
   Stream.Seek(EndPosition, 0);
 end;
 
 procedure TAlbumRec.SaveToStream(Stream: TStream);
 var
   GraphicTypeCode: Char;
   StartPosition,
     EndPosition: LongInt;
 begin
   { Запоминаем позицию потока для дальнейшей записи наших объектов... }
   StartPosition := Stream.Position;
 
   { Здесь мы собираемся записать позицию где заканчиваются данные записи.
   Мы пока не знаем как это позиционируется, поэтому пока записываем ноль
   чтобы сохранить место... }
   EndPosition := 0;
   Stream.Write(EndPosition, SizeOf(EndPosition));
 
   { Записываем строку Delphi 1.0... }
   Stream.Write(FDescription[0], SizeOf(Byte));
   Stream.Write(FDescription[1], Byte(FDescription[0]));
 
   { Записываем целое... }
   Stream.Write(FItemType, SizeOf(FItemType));
 
   { Записываем код, сообщающий тип графического объекта,
   который мы собираемся писать... }
   if (FGraphic = nil) or (FGraphic.Empty) then
     GraphicTypeCode := 'Z'
   else if FGraphic is TBitmap then
     GraphicTypeCode := 'B'
   else if FGraphic is TIcon then
     GraphicTypeCode := 'I'
   else if FGraphic is TMetaFile then
     GraphicTypeCode := 'M';
   Stream.Write(GraphicTypeCode, SizeOf(GraphicTypeCode));
 
   { Записываем графику... }
   if (GraphicTypeCode <> 'Z') then
     FGraphic.SaveToStream(Stream);
 
   { Возвращаемся к месту откуда мы начинали и записываем
   конечную позицию, которую мы сохранили... }
   EndPosition := Stream.Position;
   Stream.Seek(StartPosition, 0);
   Stream.Write(EndPosition, SizeOf(EndPosition));
 
   { Возвращаем конечную позицию, после этого поток готов
   для следующей записи... }
   Stream.Seek(EndPosition, 0);
 end;
 
 procedure TAlbumRec.SetGraphic(AGraphic: TGraphic);
 begin
   FGraphic.Free;
   FGraphic := nil;
   if AGraphic <> nil then
   begin
     FGraphic := TGraphic(AGraphic.ClassType.Create);
     FGraphic.Assign(AGraphic);
   end;
 end;
 
 end.
 




<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ



Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS