Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.10.2007, 19:20   #1
andrey4623
Форумчанин
 
Аватар для andrey4623
 
Регистрация: 31.05.2007
Сообщений: 266
Вопрос сохранение изображения с TFileStream

Здравствуйте!

Я записываю в файл разные данные (с помощью TFileStream). Так легко записывать текст или структурные данные. Но сохранить таким образом изображение в файл не получается. Если изначальная картинка весит 170 Кб, то полученный файл - всего 4 байта! Посмотрите, что здесь не так:

Цитата:
var
fs:TFileStream;
b:Tbitmap;
ms:TMemoryStream;
n:integer;
begin
fs:=TFileStream.Create('C:\123.abc' ,fmCreate);
b:=TBitmap.Create;
b:=Form1.Image1.Picture.Bitmap;

fs.Write(b, sizeof(b));


fs.Free;
b.Free;
ShowMessage('The picture was saved');
end;
andrey4623 вне форума Ответить с цитированием
Старый 16.10.2007, 20:21   #2
Virtson
Владимир М.
Участник клуба
 
Аватар для Virtson
 
Регистрация: 30.10.2006
Сообщений: 1,289
Лампочка файл GRAPHICS.pas :

Код:
procedure TBitmap.WriteStream(Stream: TStream; WriteSize: Boolean);
const
  PalSize: array [Boolean] of Byte = (sizeof(TRGBQuad), sizeof(TRGBTriple));
var
  Size, ColorCount: DWORD;
  HeaderSize: DWORD;
  BMF: TBitmapFileHeader;
  Save: THandle;
  BC: TBitmapCoreHeader;
  Colors: array [Byte] of TRGBQuad;
begin
  FillChar(BMF, sizeof(BMF), 0);
  BMF.bfType := $4D42;
  if FImage.FSaveStream <> nil then
  begin
    Size := FImage.FSaveStream.Size;
    if WriteSize then
      Stream.WriteBuffer(Size, sizeof(Size));
    Stream.Write(FImage.FSaveStream.Memory^, FImage.FSaveStream.Size);
    Exit;
  end;
  DIBNeeded;
  with FImage do
  begin
    Size := 0;
    if FDIBHandle <> 0 then
    begin
      InternalGetDIBSizes(FDIBHandle, HeaderSize, Size, FDIB.dsbmih.biClrUsed);
      if FOS2Format then
      begin // OS2 format cannot have partial palette
        HeaderSize := sizeof(BC);
        if FDIB.dsbmih.biBitCount <= 8 then
          Inc(HeaderSize, sizeof(TRGBTriple) * (1 shl FDIB.dsbmih.biBitCount));
      end;
      Inc(Size, HeaderSize + sizeof(BMF));

      FillChar(BMF, sizeof(BMF), 0);
      BMF.bfType := $4D42;

      Canvas.RequiredState([csHandleValid]);
      Save := GDICheck(SelectObject(FCanvas.FHandle, FDIBHandle));
      ColorCount := GetDIBColorTable(FCanvas.FHandle, 0, 256, Colors);
      SelectObject(FCanvas.FHandle, Save);
      // GetDIBColorTable always reports the full palette; trim it back for partial palettes
      if (0 < FDIB.dsbmih.biClrUsed) and (FDIB.dsbmih.biClrUsed < ColorCount) then
        ColorCount := FDIB.dsbmih.biClrUsed;
      if (not FOS2Format) and (ColorCount = 0) and (FPalette <> 0) and not FHalftone then
      begin
        ColorCount := PaletteToDIBColorTable(FPalette, Colors);
        if FDIB.dsbmih.biBitCount > 8 then
        begin  // optional color palette for hicolor images (non OS2)
          Inc(Size, ColorCount * sizeof(TRGBQuad));
          Inc(HeaderSize, ColorCount * sizeof(TRGBQuad));
        end;
      end;

      BMF.bfSize := Size;
      BMF.bfOffBits := sizeof(BMF) + HeaderSize;
    end;

    if WriteSize then Stream.WriteBuffer(Size, SizeOf(Size));

    if Size <> 0 then
    begin
      FixupBitFields(FDIB);
      if (ColorCount <> 0) then
      begin
        if (FDIB.dsbmih.biClrUsed = 0) or (FDIB.dsbmih.biClrUsed <> ColorCount) then
          FDIB.dsbmih.biClrUsed := ColorCount;
        if FOS2Format then RGBQuadToTriple(Colors, Integer(ColorCount));
      end;
      if FOS2Format then
      begin
        with BC, FDIB.dsbmih do
        begin
          bcSize := sizeof(BC);
          bcWidth := biWidth;
          bcHeight := biHeight;
          bcPlanes := 1;
          bcBitCount := biBitCount;
        end;
        Stream.WriteBuffer(BMF, sizeof(BMF));
        Stream.WriteBuffer(BC, sizeof(BC));
      end
      else
      begin
        Stream.WriteBuffer(BMF, Sizeof(BMF));
        Stream.WriteBuffer(FDIB.dsbmih, Sizeof(FDIB.dsbmih));
        if (FDIB.dsbmih.biBitCount > 8) and
          ((FDIB.dsbmih.biCompression and BI_BITFIELDS) <> 0) then
          Stream.WriteBuffer(FDIB.dsBitfields, 12);
      end;
      Stream.WriteBuffer(Colors, ColorCount * PalSize[FOS2Format]);
      Stream.WriteBuffer(FDIB.dsbm.bmBits^, FDIB.dsbmih.biSizeImage);
    end;
  end;
end;
это все должно идти вместо fs.Write )
Берегите друг друга!

Последний раз редактировалось Virtson; 16.10.2007 в 20:23.
Virtson вне форума Ответить с цитированием
Старый 16.10.2007, 21:36   #3
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Что-то очень уж сложно, по-моему.
У меня вот что получилось:
Код:
var
fs1: TMemoryStream;
fs2:TFileStream;
b: TBitmap;
begin
fs1:= TMemoryStream.Create;
Image1.Picture.Graphic.SaveToStream(fs1);
fs2 := TFileStream.Create('c:\123.abc', fmCreate);
fs2.CopyFrom(fs1,0);
fs1.FreeInstance;
fs2.FreeInstance;
ShowMessage('The picture was saved');
end;
Сменил на диске С:\ расширение у 123.abc на 123.jpg - увидел исходную картинку.

Последний раз редактировалось mihali4; 17.10.2007 в 17:01.
mihali4 вне форума Ответить с цитированием
Старый 17.10.2007, 19:55   #4
andrey4623
Форумчанин
 
Аватар для andrey4623
 
Регистрация: 31.05.2007
Сообщений: 266
По умолчанию

А как ее потом из этого файла извлечь?
andrey4623 вне форума Ответить с цитированием
Старый 18.10.2007, 10:48   #5
devi409
Пользователь
 
Регистрация: 28.12.2006
Сообщений: 75
По умолчанию

Лично я делал так

potok := TMemoryStream.Create;
FileStream := TFileStream.Create(ChangeFileExt(ad ,'.tmp'), fmCreate);
Writer := TWriter.Create (FileStream, $1000);
BitMap.SaveToStream(potok)
Buffer := potok.Memory;
Size := potok.Size;
Writer.WriteInteger (Size);
Writer.Write (Buffer^, Size);

Writer.Free;
FileStream.Free;
potok1.Free;

только извлечение из файла должно быть в томже порядке как записывали

Последний раз редактировалось devi409; 18.10.2007 в 10:53.
devi409 вне форума Ответить с цитированием
Старый 18.10.2007, 19:47   #6
andrey4623
Форумчанин
 
Аватар для andrey4623
 
Регистрация: 31.05.2007
Сообщений: 266
По умолчанию

а извлечь эту картинку из файла не получается...
Кстати, а так можно любой файл сохранять?
andrey4623 вне форума Ответить с цитированием
Старый 18.10.2007, 20:47   #7
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Цитата:
а извлечь эту картинку из файла не получается...
В каком смысле? Я же сказал - если у сохраненной моим методом картинки просто установить подобающее расширение, то ее можно открывать хоть в графическом редакторе, хоть у себя в программе.
Но это так, просто для проверки.
А извлечь - если самое простое:
if OpenDialog1.Execute then
Image1.Picture.Graphic.LoadFromFile (OpenDialog1.FileName);
И тут по барабану, какое у файла расширение, лишь бы он был картинкой...
А если нужно опять с использованием потоков... Ну, заставьте себя хоть чуть-чуть потрудиться и переделайте мой вариант в обратный, для чтения, САМОСТОЯТЕЛЬНО.

Последний раз редактировалось mihali4; 18.10.2007 в 20:55.
mihali4 вне форума Ответить с цитированием
Старый 19.10.2007, 18:33   #8
andrey4623
Форумчанин
 
Аватар для andrey4623
 
Регистрация: 31.05.2007
Сообщений: 266
По умолчанию

Что-то не получается... Что тут не так:

var
fs1: TMemoryStream;
fs2:TFileStream;
b: TBitmap;
begin


fs2 := TFileStream.Create('c:\123.abc', fmOpenRead);
fs1:= TMemoryStream.Create;

fs1.CopyFrom(fs2,0);

Image1.Picture.Graphic.LoadFromStre am(fs1);
fs1.FreeInstance;
fs2.FreeInstance;
andrey4623 вне форума Ответить с цитированием
Старый 20.10.2007, 08:29   #9
andrey4623
Форумчанин
 
Аватар для andrey4623
 
Регистрация: 31.05.2007
Сообщений: 266
По умолчанию

Подскажите, пожайлуста. Я с этими потоками вообще не врубаюсь, и что такое CopyFrom - темный лес.

Я читал литературу, что TFileStream имеет методы Write, Read, но с ними сам файл в файл не записать...
andrey4623 вне форума Ответить с цитированием
Старый 20.10.2007, 08:39   #10
Virtson
Владимир М.
Участник клуба
 
Аватар для Virtson
 
Регистрация: 30.10.2006
Сообщений: 1,289
Сообщение

Цитата:
Сообщение от mihali4 Посмотреть сообщение
Что-то очень уж сложно, по-моему.
мой пример был бы такой :
Код:
var fs: TFileStream;
begin
 fs:= TFileStream.Create('C:\123.abc',fmCreate); 
 with Form1.Image1.Picture do
   Bitmap.WriteStream(fs, sizeof(Bitmap));
 fs.Free;
 ShowMessage('The picture was saved');
end;
я просто привел к сведению, что получается в месте Bitmap.WriteStream()
а Ваш код тоже использует этот метод, только скрыто )
Берегите друг друга!

Последний раз редактировалось Virtson; 20.10.2007 в 08:41.
Virtson вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Чтение изображения из базы данных, Вместо изображения - "System.Byte[]" ruelCrow Общие вопросы .NET 3 10.07.2008 23:29
Проблема с record,string,TFileStream AngelOfDeath Общие вопросы Delphi 6 31.05.2008 11:24
Передача функции TServerSocket и TFileStream dns-s Работа с сетью в Delphi 2 26.03.2008 21:15
проблемы с TFileStream andrey4623 Общие вопросы Delphi 9 01.11.2007 20:44
TFilestream UnD)eaD)Snake Win Api 1 27.09.2007 21:22