2008. november 2., vasárnap

How to save / load a ScanLine to / from a stream


Problem/Question/Abstract:

How to save / load a ScanLine to / from a stream

Answer:

I won't claim this is fastest in any way, but it shows how to write scanlines to a stream and then read the stream to fill in the scanlines.

Example of flipping a bitmap by writing to MemoryStream and loading second bitmap in flipped order.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    Image2: TImage;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
  j: Integer;
  Bitmap1: TBitmap;
  Bitmap2: TBitmap;
  row: pByteArray;
  ScanlineBytes: Integer;
  Stream: TMemoryStream;
begin
  Bitmap1 := TBitmap.Create;
  try
    {Assume Image1 and Image2 are the same size}
    Bitmap1.Width := Image1.Width;
    Bitmap1.Height := Image1.Height;
    Bitmap1.PixelFormat := pf24bit;
    {Make something assymmetric in picture}
    Bitmap1.Canvas.Pen.Color := clRed;
    Bitmap1.Canvas.MoveTo(0, 0);
    Bitmap1.Canvas.LineTo(Bitmap1.Width, Bitmap1.Height);
    Bitmap1.Canvas.MoveTo(Bitmap1.Width div 2, 0);
    Bitmap1.Canvas.LineTo(0, Bitmap1.Height div 2);
    Image1.Picture.Graphic := Bitmap1;
    Stream := TMemoryStream.Create;
    try
      ScanlineBytes := ABS(Integer(Bitmap1.Scanline[1]) - Integer(Bitmap1.Scanline[0]));
      for j := 0 to Bitmap1.Height - 1 do
      begin
        row := Bitmap1.Scanline[j];
        Stream.Write(row[0], ScanlineBytes);
      end;
      Bitmap2 := TBitmap.Create;
      try
        Bitmap2.Width := Bitmap1.Width;
        Bitmap2.Height := Bitmap1.Height;
        Bitmap2.PixelFormat := pf24bit;
        {position stream pointer at beginning}
        Stream.Position := 0;
        {Flip bitmap by reading scanlines from stream and placing them in flipped row}
        for j := Bitmap2.Height - 1 downto 0 do
        begin
          row := Bitmap2.Scanline[j];
          Stream.Read(row[0], ScanlineBytes)
        end;
        Image2.Picture.Graphic := Bitmap2
      finally
        Bitmap2.Free
      end
    finally
      Stream.Free
    end
  finally
    Bitmap1.Free
  end;
end;

end.

Nincsenek megjegyzések:

Megjegyzés küldése