Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.09.24;
Скачать: [xml.tar.bz2];

Вниз

Сохранение произвольных данных с BitMap ом   Найти похожие ветки 

 
RASkov   (2006-08-29 00:51) [0]

Здраствуйте. Подскажите как осуществить сохранение и потом (самое главное) загрузку такой вот структуры. Проблема с PICT. TData могу а PICT туда еще вписать не могу. Т.е. должно все в один файл записаться сначала данные Data а потом картинку из PICT. Что выделил жирным ясен пень неправильно - это я так для ясности написал.
Код ниже это только для примера у меня немного подругому но это неважно мне нужна суть как туда засунуть битмап и потом считать его. Можно даже както по байтам, что бы сохранить исходный формат. Картинка в основном маленького размера но может быть и приличная... но... думаю не более 200 кил. это если в *.bmp формате. При подключенном модуле JPEG, можно в переменную TBitMap загрузить jpg? Он наверное преобразовывается в формат bmp? Это не важно...

type TData = record
     Name: String[20];
     DInt: Integer;
     DBt: Byte;
     .....
    end;  
var Data: TData;
   PICT: TBitMap;

procedure TForm1.bbSaveClick(Sender: TObject);
var F: File;
begin
  if SvDlg.Execute then begin
   PICT:=TBitMap.Create;
   PICT.LoadFromFile("namefile");
   AssignFile(F, SvDlg.FileName);
   Rewrite(F,1);
   BlockWrite(F, Data.Name, SizeOf(Data.Name));
   BlockWrite(F, Data.DInt, SizeOf(Data.DInt));
   BlockWrite(F, Data.DBt, SizeOf(Data.DBt));
   BlockWrite(F, PICT, SizeOf(PICT));
  end;
end;

Собственно, приведите пожалуйста, пример сохранения а загрузку я думаю сам допру.


 
Pavia ©   (2006-08-29 00:55) [1]

CloseFile(f);
Or Flush(f);


 
Zeqfreed ©   (2006-08-29 00:57) [2]

Самое простое сохранять битмап в стрим и стрим писать в файл.
См. TStream, TBitmap.SaveToStream.


 
RASkov   (2006-08-29 00:59) [3]

> [2] Zeqfreed ©   (29.08.06 00:57)

Можно поподробней. Со Стримами так мало работал...
Как Стрим с Битмапом дописать в мой файл и... потом его оттуда загрузить..ну это потом.


 
Pavia ©   (2006-08-29 01:01) [4]

Зачем TBitmap сохронять.
Открой файл и запиши его через
AssignFile(f1,"name");
reset(f1);
GetMem(buf,SizeOf(f1));
BlockRead(f1,buf^,SizeOf(f1));
BlockWrite(f,buf^,SizeOf(f1));
FreeMem(buf);
CloseFile(f1)


 
Ketmar ©   (2006-08-29 01:03) [5]

> [4] Pavia ©   (29.08.06 01:01)
это что такое???


 
Ketmar ©   (2006-08-29 01:04) [6]

fs := TFileStream.Create("outfile", fmCreate);
fs.WriteBuffer(data, SizeOf(data)); // или ещё как
pict.SaveToStream(fs);
fs.Free();


как упражнение -- расставить в нужных местах try/finally. %-)


 
RASkov   (2006-08-29 01:06) [7]

> [4] Pavia ©   (29.08.06 01:01)

Блин, хитро... f1 - это файл с картинкой, а f мой, так?
Попробую,... а Reset(f1) не надо так делать Reset(f1,1);?
И наверное перед BlockWrite(f,buf^,SizeOf(f1)); надо записать сам размер SizeOf(f1) ну для того что бы считать потом из моего файла. Правильно мыслю?


 
RASkov   (2006-08-29 01:09) [8]

> [6] Ketmar ©   (29.08.06 01:04)

Блин... еще хитрей да и проще вроде.
pict.SaveToStream(fs); оно допишется после моих данных?
И ... щед... здесь неуказываються размеры, а как потом читать?


 
RASkov   (2006-08-29 01:10) [9]

> [6] Ketmar ©   (29.08.06 01:04)

Ну с Data я, грубо, разберусь...


 
RASkov   (2006-08-29 01:12) [10]

> [9] RASkov   (29.08.06 01:10)

А Pict как помом вычитать, отделить от моих данных, или.. если данные пишутся первыми то считав их, останеться Pict... так? что ли...


 
Ketmar ©   (2006-08-29 01:13) [11]

> [8] RASkov   (29.08.06 01:09)
а так и читать: ReadFromStream(). проверять реализацию лень, но не вижу, отчего бы ему не работать. %-)


 
Ketmar ©   (2006-08-29 01:13) [12]

> [10] RASkov   (29.08.06 01:12)
да.


 
Pavia ©   (2006-08-29 01:13) [13]


> RASkov   (29.08.06 01:06) [7]

Да все верно.
Reset(f1,1) - не обязательно.
Я потоки не люблю больно криво сделанны. По этому предпочитаю, по старинки.


 
RASkov   (2006-08-29 01:16) [14]

> [6] Ketmar ©   (29.08.06 01:04)

try finally то я расставлю...
Спасибо. Остается только попробывать...


 
RASkov   (2006-08-29 01:17) [15]

> [13] Pavia ©   (29.08.06 01:13)

Спасибо.
Криво так криво, я и так попробую и так, а там... может че и получится.
Спасибо Pavia и Ketmar.


 
Ketmar ©   (2006-08-29 01:29) [16]

> [13] Pavia ©   (29.08.06 01:13)
> Я потоки не люблю больно криво сделанны
обосновать. или не врать.


 
Ketmar ©   (2006-08-29 01:30) [17]

> [15] RASkov   (29.08.06 01:17)
используй потоки и не занимайся ерундой. %-)


 
Gydvin ©   (2006-08-29 11:08) [18]


> RASkov   (29.08.06 01:12) [10]

писать размеры области, метки


 
RASkov   (2006-08-29 23:53) [19]

В первую очередь попробовал по совету Кетмара... ну понятней как то у него.. и... получилось, довольно не плохо для моей проги (прога собственно относится к безделушкам, я на ней просто пытаюсь кое в чем разобраться) и вот как сделал:

procedure TForm1.bbSaveClick(Sender: TObject);
var FS: TStream; PICT: TBitMap; S: String[20]; Int: Integer; F: Boolean;
begin
 if SaveDialog1.Execute then begin
  PICT:=TBitMap.Create;
  try FS:=TFileStream.Create(SaveDialog1.FileName, fmCreate);
  try PICT.LoadFromFile(OpenPictureDialog1.FileName);   //здесь это нормально
  S:=Edit1.Text;                     FS.WriteBuffer(S, SizeOf(S));
  S:=Edit2.Text;                     FS.WriteBuffer(S, SizeOf(S));
  S:=Edit3.Text;                     FS.WriteBuffer(S, SizeOf(S));
  Int:=StrToIntDef(Edit4.Text, 100); FS.WriteBuffer(Int, SizeOf(Integer));
  F:=CheckBox1.Checked;              FS.WriteBuffer(F, SizeOf(F));
  PICT.SaveToStream(FS);
  finally FS.Free; end; finally PICT.Free; end;
 end;
end;

procedure TForm1.bbLoadClick(Sender: TObject);
var FS: TStream; PICT: TBitMap; S: String[20]; Int: Integer; F: Boolean;
begin
 if OpenDialog1.Execute then begin
  PICT:=TBitMap.Create;
  try FS:=TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
  try
  FS.ReadBuffer(S, SizeOf(S));         Edit1.Text:=S;
  FS.ReadBuffer(S, SizeOf(S));         Edit2.Text:=S;
  FS.ReadBuffer(S, SizeOf(S));         Edit3.Text:=S;
  FS.ReadBuffer(Int, SizeOf(Integer)); Edit4.Text:=IntToStr(Int);
  FS.ReadBuffer(F, SizeOf(F));         CheckBox1.Checked:=F;
  PICT.LoadFromStream(FS);
  Image1.Picture.Assign(PICT);
  finally FS.Free; end; finally PICT.Free; end;
 end;
end;

Это просто обучающий для меня пример, мною проверенный - работает. Может блоки try раставлены не оптимально... не в этом суть.

Суть.. т.е. вопрос вот в чем переменная S в обоих методах описана как String[20]; а если мне понадобиться просто String - как быть? или тут уже нужно код от Pavia применять? Я пытался так:
запись
procedure TForm1.bbSaveClick(Sender: TObject);
var FS: TStream; PICT: TBitMap; S: String; Int: Integer; F: Boolean;
begin
 if SaveDialog1.Execute then begin
.........
 S:=Edit1.Text; Int:=Length(S);
 FS.WriteBuffer(Int, SizeOf(Int)); FS.WriteBuffer(S, Int);
 S:=Edit2.Text; Int:=Length(S);
 FS.WriteBuffer(Int, SizeOf(Int)); FS.WriteBuffer(S, Int);
.........
end;

чтение
var FS: TStream; PICT: TBitMap; S: String; Int: Integer; F: Boolean;
begin
 if OpenDialog1.Execute then begin
.........
 FS.ReadBuffer(Int, SizeOf(Integer)); FS.ReadBuffer(S, Int);
 Edit1.Text:=S;
.........
end;
Не работает. Почему?
Много слышал про "косяки" String"ов... это он самый?
СПАСИБО.


 
RASkov   (2006-08-29 23:54) [20]

Блин... код выделить неуспел...


 
kami ©   (2006-08-30 00:17) [21]

а если мне понадобиться просто String
FS.Read(int, SizeOf(integer));
SetLength(s,int);// если с string, а не string[xx]
if i>0 then
 FS.Read(s[1], int);


P.S. Если после битмапа должны быть записаны (и считаны впоследствии) еще данные, то учти, что после PICT.LoadFromStream(FS)  fs.position будет указывать на конец потока.


 
kami ©   (2006-08-30 00:25) [22]

RASkov   (29.08.06 0:51)
При подключенном модуле JPEG, можно в переменную TBitMap загрузить jpg?


//сохраняем
if SaveDialog1.Execute then begin
.........
jpg.Assign(PICT);
jpg.SaveToStream(fs);
.........
end;

// загружаем
if OpenDialog1.Execute then begin
.......
jpg.LoadFromStream(FS);
PICT.Assign(jpg);
.......
end;


Само собой, не забыть своевременно уничтожить jpg и PICT :)


 
RASkov   (2006-08-30 13:34) [23]

> [22] kami ©   (30.08.06 00:25)

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


 
RASkov   (2006-08-30 13:36) [24]

т.е. это было для [21] к части P.S.


 
RASkov   (2006-08-30 14:11) [25]

> [21] kami ©   (30.08.06 00:17)

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

S:=Edit1.Text; Int:=Length(S);
FS.WriteBuffer(Int, SizeOf(Int)); FS.WriteBuffer(S, Int);

P.S. var S: String;


 
kami ©   (2006-08-30 15:05) [26]

Запись - такая же, как и чтение :

int:=Length(Edit1.text);
FS.Write(int, SizeOf(integer));
if int>0 then
 FS.Write(Edit1.Text[1], int);


К p.s. [21] :

Алгоритм записи без указанной особенности:
1. Создаем временный поток (например, TempStream : TMemoryStream)
2. Записываем в него битмап
3. Записываем в основной поток размер TempStream
4. Копируем в основной поток сам TempStream
5. Освобождаем TempStream.

Загрузка:
1. Читаем размер записанного битмапа (BmpSize)
2. Создаем временный поток
3. Копируем в него из основного потока BmpSize байт
4. Устанавливаем позицию временного потока в 0
5. Загружаем битмап из временного потока
6. Освобождаем TempStream


 
RASkov   (2006-08-30 22:11) [27]

Вот еще такой трабл есть. У меня картинка сохраняется после данных. И состоит из кучи мелких присутствующих или нет в элементах массива Т.е. при сохранении файла пробегаемся по массиву и соответственно пишем данные элемента и если содержит рисунок то добавляем его в общую картину и после того как записали данные и сгенерили картинку собственно ее и дописываем в файл. Вот... а при чтении нужно заполнять массив данными из начала файла и на их основе резать картинку на мелкие куски...но она (картинка) находится в конце как лучше поступить: У меня появились некоторые соображения типа:
1 - открыть файл пробежаться до картинки считав все необходимые данные в массив, затем считали картику и опять с начала, только уже по массиву, брать данные и на их основе резать картинку и добавлять в соот. элемент
2 - (можно ли так) при сохранении данных делать в принципе тоже самое как и в 1 только когда дело дойдет до записи собственно картинки, запомнить N:=FS.Position в переменной, сместить FS.Position:=0; записать эту переменную
FS.WriteBuffer(N, SizeOf(Int64)); сместить назад FS.Position:=N+SizeOf(Int64); и записать саму картинку... ну и при чтении первым делом считываем позицию картинки грузим ее возвращаем FS.Position:=SizeOf(Int64); ну и с этого места за один проход все читаем и режем картинку.
3 - при сохранении данных массива после очередного элемента писать мелкую картинку затем следующий элемент. И при чтении вопрос - как?... но тут еще и сомнения вызваны [21] kami ©   (30.08.06 00:17) P.S. где он говорил что при PICT.LoadFromStream(FS) FS.Position будет указывать на конец потока. Т.е. каким то другим способом читать такой файл где вперемешку идут данные и картинки?

P.S. У элемента массива может присутствовать а может и нет мелкая картинка. Массив описан так:

type TData = record
     BMP: TBitMap;
     IsBmp: Boolean;
     Name: String;
     Color: TColor;
     BmpWidth, BmpHeight: Integer;
  ........
    end;

var Dts: array of TData;


 
RASkov   (2006-08-30 22:14) [28]

Третий способ похоже описан  [26] kami ©   (30.08.06 15:05) но его я оставил как вариант.... И наверное так и надо или...


 
RASkov   (2006-08-30 22:15) [29]

Но мне интересен второй... можно ли так?


 
Ketmar ©   (2006-08-31 00:07) [30]

если переведёшь на русский, то, может, и ответят.


 
kami ©   (2006-08-31 00:48) [31]

Используй 3.

Получится что-то типа следующего :

procedure SaveBitmapToStream(Bitmap:TBitMap; Stream:TStream);
begin
 // алгоритм записи из [26]
end;

procedure LoadBitmapFromStream(Bitmap:TBitMap; Stream:TStream);
begin
 // алгоритм чтения из [26]
end;

procedure SaveData(Data:TData; Stream:TStream);
begin
 // тут сохраняем все поля, кроме BMP
 // к стати, зачем хранить BmpWidth и BmpHeight - разве свойств TData.BMP не хватит?
 SaveBitmapToStream(Data.BMP, Stream);
end;

procedure LoadData(var Data:TData; Stream:TStream);
begin
 // читаем поля, кроме BMP
 LoadBitmapFromStream(Data.BMP, Stream);
end;

ну и, само применение :

var
 Dts:array of TData;
 DataCount, i:integer;
 FS:TFileStream;
begin
 FS:=TFileStream.Create(...);
 FS.Read(DataCount, SizeOf(integer));
 SetLength(Dts, DataCount);
 for i:=0 to DataCount-1 do
   begin
     Dts[i].BMP:=TBitMap.Create;
     LoadData(Dts[i], FS);
   end;
 FS.Free;
 // делаем с DataArray что нужно
end;


 
kami ©   (2006-08-31 01:18) [32]

2 - извращения, но все же :

запись:
var
 TempPos:integer; {или если надо - int64}
begin
 // создаем FS, подготавливаем что-то еще
 // каким-то боком синтезируем общую картинку в PICT:TBitMap, вот только - зачем, ведь потом ее опять разрезать...
 FS.Write(TempPos, SizeOf(integer));// зарезервировали место под позицию, с которой начнется "глобальный" битмап
 // записываем DTS в FS :), в этом случае Wudth и Height поля будут нужны, иначе как потом разрезать?
 TempPos:=FS.Position;// запомнили позицию после записи всех полей из DTS. Именно отсюда в потоке начинаются
                      // данные PICT.
 Pict.SaveToStream(FS);
 FS.Position:=0;// предполагаем, что записывать данные мы начали с начала потока, а не где-то с середины
                // то есть изначально FS был пустой
 FS.Write(TempPos, SizeOf(integer));// и записали в начало потока указатель на начало данных для PICT
 FS.Free;
end;


Чтение:
 FS.Read(TempPos, SizeOf(integer));// прочитали, откуда начинаются данные для PICT
 FS.Position:=TempPos;// сместились туда
 PICT.LoadFromStream(FS);//прочитали картинку
 FS.Position:=SizeOf(integer);// опять на начало, пропуская указатель на данные PICT
 // читаем данные DTS
 FS.Free;  


 
RASkov   (2006-08-31 03:05) [33]

> [31] kami ©   (31.08.06 00:48)

Спасибо. Будем пробывать.


 
RASkov   (2006-09-02 00:39) [34]

Часть метода сохранения, использую 3 способ предложенный [31] kami
procedure SaveDate(...
var FS, BmpFS: TStream; SzBmp: Integer;
............
  FS:=TFileStream.Create(SvDlg.FileName, fmCreate);
............
     BmpFS:=TMemoryStream.Create;
     try
     Dts[i].Bmp.SaveToStream(BmpFS);
     SzBmp:=BmpFS.Size;
     FS.WriteBuffer(SzBmp, SizeOf(SzBmp));
     FS.CopyFrom(BmpFS, SzBmp);
     finally
      BmpFS.Free;
     end;
.............

И вот на строке FS.CopyFrom(BmpFS, SzBmp); вылетает ошибка. Размер записываеться и следом ошибка "Stream read error" с выделением в редакторе кода этой строки. Что я не так делаю?


 
RASkov   (2006-09-02 01:02) [35]

Кажись просек только что.

 SzBmp:=TBmpFS.Size;
 BmpFS.Position:=0;
 FS.WriteBuffer(SzBmp, SizeOf(SzBmp));
 FS.CopyFrom(BmpFS, SzBmp);


Там в [26] в алгоритме записи это было упущено...


 
kami ©   (2006-09-02 10:50) [36]

RASkov   (02.09.06 1:02) [35]
Там в [26] в алгоритме записи это было упущено

Нет, это не упущено.
Я имел ввиду конструкцию типа FS.CopyFrom(BmpFS, 0);. См.справку по TStream.CopyFrom.


 
RASkov   (2006-09-03 15:02) [37]

> [36] kami ©   (02.09.06 10:50)

Да... Спасибо:)



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

Форум: "Начинающим";
Текущий архив: 2006.09.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.043 c
11-1132935688
Pety
2005-11-25 19:21
2006.09.24
Нарисовать иконку на канве


1-1155123140
Stanislav
2006-08-09 15:32
2006.09.24
Нажата ли клавиша Shift


1-1155392466
!_SM_!
2006-08-12 18:21
2006.09.24
OnCreate, OnDestroy


3-1153331464
HNN
2006-07-19 21:51
2006.09.24
Поиск текста в таблице


15-1156932901
AntiKur
2006-08-30 14:15
2006.09.24
Курение вредно для здаровья





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский