unit JPegEncoder;

interface

uses
  Windows, Classes, SysUtils, Graphics;

type
  TBoundRect = packed record
    Left, Top, Width, Height : integer;
  end;

  TJPegEncoder = class (TComponent)
  private
    FBitmap : TBitmap;
  private
    FDataOut: TMemoryStream;
    FQuality: integer;
    function GetBoundRect: TBoundRect;
    procedure SetBoundRect(const Value: TBoundRect);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    
    procedure Execute(Data:pointer; Size:integer);
  published
    property Quality : integer read FQuality write FQuality;
    property BoundRect : TBoundRect read GetBoundRect write SetBoundRect;
    property DataOut : TMemoryStream read FDataOut;
  end;

procedure JPegEncode(Src,Dst:TStream; Quality:integer=100);
procedure JPegDecode(Src,Dst:TStream); 
procedure BitmapToJpeg(Bitmap:TBitmap; Dst:TStream; Quality:integer=100);
procedure JpegToBitmap(Src:TStream; Bitmap:TBitmap);

function ToBoundRect(Left,Top,Width,Height:integer):TBoundRect;

implementation

uses
  JPeg;

type
  TRyuJpegImage = class(TJPEGImage)
  private
  public
    procedure SaveToBitmap(Bitmap:TBitmap);
  end;

function ToBoundRect(Left,Top,Width,Height:integer):TBoundRect;
begin
  Result.Left   := Left;
  Result.Top    := Top;
  Result.Width  := Width;
  Result.Height := Height;
end;

{ TRyuJpegImage }

procedure TRyuJpegImage.SaveToBitmap(Bitmap: TBitmap);
begin
  Bitmap.Width:=  Width;
  Bitmap.Height:= Height;
  Bitmap.Canvas.Draw(0, 0, Self);
end;

procedure JPegEncode(Src,Dst:TStream; Quality:integer=100);
var
  Bitmap : TBitmap;
  JPEGImage : TJPEGImage;
begin
  Bitmap := TBitmap.Create;
  JPEGImage := TJPEGImage.Create;
  try
    Src.Position := 0;
    Bitmap.LoadFromStream(Src);

    JPEGImage.Assign(Bitmap);
    JPEGImage.CompressionQuality := Quality;
    JPEGImage.Compress;
    JPEGImage.SaveToStream(Dst);

    Dst.Position := 0;
  finally
    Bitmap.Free;
    JPEGImage.Free;
  end;
end;
 
procedure JPegDecode(Src,Dst:TStream);
var
  Bitmap : TBitmap;
  JPEGImage : TJPEGImage;
begin
  Bitmap := TBitmap.Create;
  JPEGImage := TJPEGImage.Create;
  try
    Src.Position := 0;
    JPEGImage.LoadFromStream(Src);

    Bitmap.PixelFormat := pf24bit;
    Bitmap.Width := JPEGImage.Width;
    Bitmap.Height := JPEGImage.Height;
    Bitmap.Canvas.Draw(0, 0, JPEGImage);

    Dst.Write(Bitmap.ScanLine[Bitmap.Height-1]^, Bitmap.Width*Bitmap.Height*3);
    Dst.Position := 0;
  finally
    Bitmap.Free;
    JPEGImage.Free;
  end;
end;
 
procedure BitmapToJpeg(Bitmap:TBitmap; Dst:TStream; Quality:integer=100);
var
  JPEGImage : TJPEGImage;
begin
  JPEGImage := TJPEGImage.Create;
  try
    JPEGImage.Assign(Bitmap);
    JPEGImage.CompressionQuality := Quality;
    JPEGImage.Compress;
    JPEGImage.SaveToStream(Dst);
    Dst.Position := 0;
  finally
    JPEGImage.Free;
  end;
end;

procedure JpegToBitmap(Src:TStream; Bitmap:TBitmap);
var
  JPEGImage : TJPEGImage;
begin
  JPEGImage := TJPEGImage.Create;
  try
    JPEGImage.LoadFromStream(Src);

    Bitmap.Width := JPEGImage.Width;
    Bitmap.Height := JPEGImage.Height;
    Bitmap.Canvas.Draw(0, 0, JPEGImage);
  finally
    JPEGImage.Free;
  end;
end;
 
{ TJPegEncoder }

constructor TJPegEncoder.Create(AOwner: TComponent);
begin
  inherited;

  FDataOut := TMemoryStream.Create;

  FBitmap := TBitmap.Create;
  FBitmap.PixelFormat := pf24bit;
  FBitmap.Width := 1024;
  FBitmap.Height := 768;
end;

destructor TJPegEncoder.Destroy;
begin
  FBitmap.Free;
  FDataOut.Free;

  inherited;
end;

procedure TJPegEncoder.Execute(Data: pointer; Size: integer);
begin
  Move(Data^, FBitmap.ScanLine[FBitmap.Height-1]^, Size);

  FDataOut.Clear;
  BitmapToJpeg(FBitmap, FDataOut, FQuality);
end;

function TJPegEncoder.GetBoundRect: TBoundRect;
begin
  Result := ToBoundRect(0, 0, FBitmap.Width, FBitmap.Height);
end;

procedure TJPegEncoder.SetBoundRect(const Value: TBoundRect);
begin
  FBitmap.Width := Value.Width;
  FBitmap.Height := Value.Height;
end;

end.
