Текущий архив: 2006.09.24;
Скачать: CL | DM;
ВнизСохранение произвольных данных с 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;
Скачать: CL | DM;
Память: 0.55 MB
Время: 0.052 c