Browse Source

+ Removed for copyright reasons

michael 20 years ago
parent
commit
30c1f2afac
1 changed files with 0 additions and 944 deletions
  1. 0 944
      packages/base/pasjpeg/jpeg.pas

+ 0 - 944
packages/base/pasjpeg/jpeg.pas

@@ -1,944 +0,0 @@
-{*******************************************************}
-{                                                       }
-{       Delphi Runtime Library                          }
-{       JPEG Image Compression/Decompression Unit       }
-{                                                       }
-{       Copyright (c) 1997 Borland International        }
-{       Copyright (c) 1998 Jacques Nomssi Nzali         }
-{                                                       }
-{*******************************************************}
-
-unit jpeg;
-
-interface
-
-{$I jconfig.inc}
-
-{$ifndef Delphi_Stream}
-  Define "Delphi_Stream" in jconfig.inc - deliberate syntax error.
-{$endif}
-
-uses Windows, SysUtils, Classes, Graphics;
-
-type
-  TJPEGData = class(TSharedImage)
-  private
-    FData: TCustomMemoryStream;
-    FHeight: Integer;
-    FWidth: Integer;
-    FGrayscale: Boolean;
-  protected
-    procedure FreeHandle; override;
-  public
-    destructor Destroy; override;
-  end;
-
-  TJPEGQualityRange = 1..100;   { 100 = best quality, 25 = pretty awful }
-  TJPEGPerformance = (jpBestQuality, jpBestSpeed);
-  TJPEGScale = (jsFullSize, jsHalf, jsQuarter, jsEighth);
-  TJPEGPixelFormat = (jf24Bit, jf8Bit);
-
-  TJPEGImage = class(TGraphic)
-  private
-    FImage: TJPEGData;
-    FBitmap: TBitmap;
-    FScaledWidth: Integer;
-    FScaledHeight: Integer;
-    FTempPal: HPalette;
-    FSmoothing: Boolean;
-    FGrayScale: Boolean;
-    FPixelFormat: TJPEGPixelFormat;
-    FQuality: TJPEGQualityRange;
-    FProgressiveDisplay: Boolean;
-    FProgressiveEncoding: Boolean;
-    FPerformance: TJPEGPerformance;
-    FScale: TJPEGScale;
-    FNeedRecalc: Boolean;
-    procedure CalcOutputDimensions;
-    function GetBitmap: TBitmap;
-    function GetGrayscale: Boolean;
-    procedure SetGrayscale(Value: Boolean);
-    procedure SetPerformance(Value: TJPEGPerformance);
-    procedure SetPixelFormat(Value: TJPEGPixelFormat);
-    procedure SetScale(Value: TJPEGScale);
-    procedure SetSmoothing(Value: Boolean);
-  protected
-    procedure AssignTo(Dest: TPersistent); override;
-    procedure Changed(Sender: TObject); override;
-    procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;
-    function Equals(Graphic: TGraphic): Boolean; override;
-    procedure FreeBitmap;
-    function GetEmpty: Boolean; override;
-    function GetHeight: Integer; override;
-    function GetPalette: HPALETTE; override;
-    function GetWidth: Integer; override;
-    procedure NewBitmap;
-    procedure NewImage;
-    procedure ReadData(Stream: TStream); override;
-    procedure ReadStream(Size: Longint; Stream: TStream);
-    procedure SetHeight(Value: Integer); override;
-    procedure SetPalette(Value: HPalette); override;
-    procedure SetWidth(Value: Integer); override;
-    procedure WriteData(Stream: TStream); override;
-    property Bitmap: TBitmap read GetBitmap;  { volatile }
-  public
-    constructor Create; override;
-    destructor Destroy; override;
-    procedure Compress;
-    procedure DIBNeeded;
-    procedure JPEGNeeded;
-    procedure Assign(Source: TPersistent); override;
-    procedure LoadFromStream(Stream: TStream); override;
-    procedure SaveToStream(Stream: TStream); override;
-    procedure LoadFromClipboardFormat(AFormat: Word; AData: THandle;
-      APalette: HPALETTE); override;
-    procedure SaveToClipboardFormat(var AFormat: Word; var AData: THandle;
-      var APalette: HPALETTE); override;
-
-    { Options affecting / reflecting compression and decompression behavior }
-    property Grayscale: Boolean read GetGrayscale write SetGrayscale;
-    property ProgressiveEncoding: Boolean read FProgressiveEncoding write FProgressiveEncoding;
-
-    { Compression options }
-    property CompressionQuality: TJPEGQualityRange read FQuality write FQuality;
-
-    { Decompression options }
-    property PixelFormat: TJPEGPixelFormat read FPixelFormat write SetPixelFormat;
-    property ProgressiveDisplay: Boolean read FProgressiveDisplay write FProgressiveDisplay;
-    property Performance: TJPEGPerformance read FPerformance write SetPerformance;
-    property Scale: TJPEGScale read FScale write SetScale;
-    property Smoothing: Boolean read FSmoothing write SetSmoothing;
-  end;
-
-  TJPEGDefaults = record
-    CompressionQuality: TJPEGQualityRange;
-    Grayscale: Boolean;
-    Performance: TJPEGPerformance;
-    PixelFormat: TJPEGPixelFormat;
-    ProgressiveDisplay: Boolean;
-    ProgressiveEncoding: Boolean;
-    Scale: TJPEGScale;
-    Smoothing: Boolean;
-  end;
-
-var   { Default settings for all new TJPEGImage instances }
-  JPEGDefaults: TJPEGDefaults = (
-    CompressionQuality: 90;
-    Grayscale: False;
-    Performance: jpBestQuality;
-    PixelFormat: jf24Bit;         { initialized to match video mode }
-    ProgressiveDisplay: False;
-    ProgressiveEncoding: False;
-    Scale: jsFullSize;
-    Smoothing: True;
-  );
-
-implementation
-
-uses jconsts,
-  jmorecfg, jerror, jpeglib, jcomapi, jdmaster, jdapistd,
-  jdatadst, jcparam, jcapimin, jcapistd, jdapimin, jdatasrc;
-
-
-{ The following types and external function declarations are used to
-  call into functions of the Independent JPEG Group's (IJG) implementation
-  of the JPEG image compression/decompression public standard.  The IJG
-  library's C source code is compiled into OBJ files and linked into
-  the Delphi application. Only types and functions needed by this unit
-  are declared; all IJG internal structures are stubbed out with
-  generic pointers to reduce internal source code congestion.
-
-  IJG source code copyright (C) 1991-1996, Thomas G. Lane. }
-
-
-{ Error handler }
-
-
-{ Progress monitor object }
-type
-  new_progress_mgr_ptr = ^new_progress_mgr;
-  new_progress_mgr = record
-    pub : jpeg_progress_mgr;
-    { extra Delphi info }
-    instance: TJPEGImage;       { ptr to current TJPEGImage object }
-    last_pass: Integer;
-    last_pct: Integer;
-    last_time: Integer;
-    last_scanline: Integer;
-  end;
-
-  TJPEGContext = record
-    err: jpeg_error_mgr;
-    progress: new_progress_mgr;
-    FinalDCT: J_DCT_METHOD;
-    FinalTwoPassQuant: Boolean;
-    FinalDitherMode: J_DITHER_MODE;
-    case byte of
-      0: (common: jpeg_common_struct);
-      1: (d: jpeg_decompress_struct);
-      2: (c: jpeg_compress_struct);
-  end;
-
-
-type
-  EJPEG = class(EInvalidGraphic);
-
-procedure InvalidOperation(const Msg: string); near;
-begin
-  raise EInvalidGraphicOperation.Create(Msg);
-end;
-
-procedure JpegError(cinfo: j_common_ptr);
-begin
-  raise EJPEG.CreateFmt(sJPEGError,[cinfo^.err^.msg_code]);
-end;
-
-procedure EmitMessage(cinfo: j_common_ptr; msg_level: Integer); far;
-begin
-  { -- !! }
-end;
-
-procedure OutputMessage(cinfo: j_common_ptr); far;
-begin
-  { -- !! }
-end;
-
-procedure FormatMessage(cinfo: j_common_ptr; var buffer: string); far;
-begin
-  { -- !! }
-end;
-
-procedure ResetErrorMgr(cinfo: j_common_ptr);
-begin
-  cinfo^.err^.num_warnings := 0;
-  cinfo^.err^.msg_code := 0;
-end;
-
-
-const
-  jpeg_std_error: jpeg_error_mgr = (
-    error_exit: JpegError;
-    emit_message: EmitMessage;
-    output_message: OutputMessage;
-    format_message: FormatMessage;
-    reset_error_mgr: ResetErrorMgr);
-
-
-{ TJPEGData }
-
-destructor TJPEGData.Destroy;
-begin
-  FData.Free;
-  inherited Destroy;
-end;
-
-procedure TJPEGData.FreeHandle;
-begin
-end;
-
-{ TJPEGImage }
-
-constructor TJPEGImage.Create;
-begin
-  inherited Create;
-  NewImage;
-  FQuality := JPEGDefaults.CompressionQuality;
-  FGrayscale := JPEGDefaults.Grayscale;
-  FPerformance := JPEGDefaults.Performance;
-  FPixelFormat := JPEGDefaults.PixelFormat;
-  FProgressiveDisplay := JPEGDefaults.ProgressiveDisplay;
-  FProgressiveEncoding := JPEGDefaults.ProgressiveEncoding;
-  FScale := JPEGDefaults.Scale;
-  FSmoothing := JPEGDefaults.Smoothing;
-end;
-
-destructor TJPEGImage.Destroy;
-begin
-  if FTempPal <> 0 then DeleteObject(FTempPal);
-  FBitmap.Free;
-  FImage.Release;
-  inherited Destroy;
-end;
-
-procedure TJPEGImage.Assign(Source: TPersistent);
-begin
-  if Source is TJPEGImage then
-  begin
-    FImage.Release;
-    FImage := TJPEGImage(Source).FImage;
-    FImage.Reference;
-    if TJPEGImage(Source).FBitmap <> nil then
-    begin
-      NewBitmap;
-      FBitmap.Assign(TJPEGImage(Source).FBitmap);
-    end;
-  end
-  else if Source is TBitmap then
-  begin
-    NewImage;
-    NewBitmap;
-    FBitmap.Assign(Source);
-  end
-  else
-    inherited Assign(Source);
-end;
-
-procedure TJPEGImage.AssignTo(Dest: TPersistent);
-begin
-  if Dest is TBitmap then
-    Dest.Assign(Bitmap)
-  else
-    inherited AssignTo(Dest);
-end;
-
-procedure ProgressCallback(const cinfo: jpeg_common_struct);
-var
-  Ticks: Integer;
-  R: TRect;
-  temp: Integer;
-  progress : new_progress_mgr_ptr;
-begin
-  progress := new_progress_mgr_ptr(cinfo.progress);
-  if (progress = nil) or (progress.instance = nil) then Exit;
-  with progress^,pub do
-  begin
-    Ticks := GetTickCount;
-    if (Ticks - last_time) < 500 then Exit;
-    temp := last_time;
-    last_time := Ticks;
-    if temp = 0 then Exit;
-    if cinfo.is_decompressor then
-      with j_decompress_ptr(@cinfo)^ do
-      begin
-        R := Rect(0, last_scanline, output_width, output_scanline);
-        if R.Bottom < last_scanline then
-          R.Bottom := output_height;
-      end
-    else
-      R := Rect(0,0,0,0);
-    temp := Trunc(100.0*(completed_passes + (pass_counter/pass_limit))/total_passes);
-    if temp = last_pct then Exit;
-    last_pct := temp;
-    if cinfo.is_decompressor then
-      last_scanline := j_decompress_ptr(@cinfo)^.output_scanline;
-    instance.Progress(instance, psRunning, temp, (R.Bottom - R.Top) >= 4, R, '');
-  end;
-end;
-
-procedure ReleaseContext(var jc: TJPEGContext);
-begin
-  if jc.common.err = nil then Exit;
-  jpeg_destroy(@jc.common);
-  jc.common.err := nil;
-end;
-
-procedure InitDecompressor(Obj: TJPEGImage; var jc: TJPEGContext);
-begin
-  FillChar(jc, sizeof(jc), 0);
-  jc.err := jpeg_std_error;
-  jc.common.err := @jc.err;
-
-  jpeg_CreateDecompress(@jc.d, JPEG_LIB_VERSION, sizeof(jc.d));
-  with Obj do
-  try
-    jc.progress.pub.progress_monitor := @ProgressCallback;
-    jc.progress.instance := Obj;
-    jc.common.progress := @jc.progress;
-
-    Obj.FImage.FData.Position := 0;
-    jpeg_stdio_src(@jc.d, @FImage.FData);
-    jpeg_read_header(@jc.d, TRUE);
-
-    jc.d.scale_num := 1;
-    jc.d.scale_denom := 1 shl Byte(FScale);
-    jc.d.do_block_smoothing := FSmoothing;
-
-    if FGrayscale then jc.d.out_color_space := JCS_GRAYSCALE;
-    if (PixelFormat = jf8Bit) or (jc.d.out_color_space = JCS_GRAYSCALE) then
-    begin
-      jc.d.quantize_colors := True;
-      jc.d.desired_number_of_colors := 236;
-    end;
-
-    if FPerformance = jpBestSpeed then
-    begin
-      jc.d.dct_method := JDCT_IFAST;
-      jc.d.two_pass_quantize := False;
-      { jc.d.do_fancy_upsampling := False;    !! AV inside jpeglib   }
-      jc.d.dither_mode := JDITHER_ORDERED;
-    end;
-
-    jc.FinalDCT := jc.d.dct_method;
-    jc.FinalTwoPassQuant := jc.d.two_pass_quantize;
-    jc.FinalDitherMode := jc.d.dither_mode;
-    if FProgressiveDisplay and jpeg_has_multiple_scans(@jc.d) then
-    begin  { save requested settings, reset for fastest on all but last scan }
-      jc.d.enable_2pass_quant := jc.d.two_pass_quantize;
-      jc.d.dct_method := JDCT_IFAST;
-      jc.d.two_pass_quantize := False;
-      jc.d.dither_mode := JDITHER_ORDERED;
-      jc.d.buffered_image := True;
-    end;
-  except
-    ReleaseContext(jc);
-    raise;
-  end;
-end;
-
-procedure TJPEGImage.CalcOutputDimensions;
-var
-  jc: TJPEGContext;
-begin
-  if not FNeedRecalc then Exit;
-  InitDecompressor(Self, jc);
-  try
-    jc.common.progress := nil;
-    jpeg_calc_output_dimensions(@jc.d);
-    { read output dimensions }
-    FScaledWidth := jc.d.output_width;
-    FScaledHeight := jc.d.output_height;
-    FProgressiveEncoding := jpeg_has_multiple_scans(@jc.d);
-  finally
-    ReleaseContext(jc);
-  end;
-end;
-
-procedure TJPEGImage.Changed(Sender: TObject);
-begin
-  inherited Changed(Sender);
-end;
-
-procedure TJPEGImage.Compress;
-var
-  LinesWritten, LinesPerCall: Integer;
-  SrcScanLine: Pointer;
-  PtrInc: Integer;
-  jc: TJPEGContext;
-  Src: TBitmap;
-begin
-  FillChar(jc, sizeof(jc), 0);
-  jc.err := jpeg_std_error;
-  jc.common.err := @jc.err;
-
-  jpeg_CreateCompress(@jc.c, JPEG_LIB_VERSION, sizeof(jc.c));
-  try
-    try
-      jc.progress.pub.progress_monitor := @ProgressCallback;
-      jc.progress.instance := Self;
-      jc.common.progress := @jc.progress;
-
-      if FImage.FData <> nil then NewImage;
-      FImage.FData := TMemoryStream.Create;
-      FImage.FData.Position := 0;
-      jpeg_stdio_dest(@jc.c, @FImage.FData);
-
-      if (FBitmap = nil) or (FBitmap.Width = 0) or (FBitmap.Height = 0) then Exit;
-      jc.c.image_width := FBitmap.Width;
-      FImage.FWidth := FBitmap.Width;
-      jc.c.image_height := FBitmap.Height;
-      FImage.FHeight := FBitmap.Height;
-      jc.c.input_components := 3;           { JPEG requires 24bit RGB input }
-      jc.c.in_color_space := JCS_RGB;
-
-      Src := TBitmap.Create;
-      try
-        Src.Assign(FBitmap);
-        Src.PixelFormat := pf24bit;
-
-        jpeg_set_defaults(@jc.c);
-        jpeg_set_quality(@jc.c, FQuality, True);
-
-        if FGrayscale then
-        begin
-          FImage.FGrayscale := True;
-          jpeg_set_colorspace(@jc.c, JCS_GRAYSCALE);
-        end;
-
-        if ProgressiveEncoding then
-          jpeg_simple_progression(@jc.c);
-
-        SrcScanline := Src.ScanLine[0];
-        PtrInc := Integer(Src.ScanLine[1]) - Integer(SrcScanline);
-
-          { if no dword padding required and source bitmap is top-down }
-        if (PtrInc > 0) and ((PtrInc and 3) = 0) then
-          LinesPerCall := jc.c.image_height  { do whole bitmap in one call }
-        else
-          LinesPerCall := 1;      { otherwise spoonfeed one row at a time }
-
-        Progress(Self, psStarting, 0, False, Rect(0,0,0,0), '');
-        try
-          jpeg_start_compress(@jc.c, True);
-
-          while (jc.c.next_scanline < jc.c.image_height) do
-          begin
-            LinesWritten := jpeg_write_scanlines(@jc.c, @SrcScanline, LinesPerCall);
-            Inc(Integer(SrcScanline), PtrInc * LinesWritten);
-          end;
-
-          jpeg_finish_compress(@jc.c);
-        finally
-          if ExceptObject = nil then
-            PtrInc := 100
-          else
-            PtrInc := 0;
-          Progress(Self, psEnding, PtrInc, False, Rect(0,0,0,0), '');
-        end;
-      finally
-        Src.Free;
-      end;
-    except
-      on EAbort do    { OnProgress can raise EAbort to cancel image save }
-        NewImage;     { Throw away any partial jpg data }
-    end;
-  finally
-    ReleaseContext(jc);
-  end;
-end;
-
-procedure TJPEGImage.DIBNeeded;
-begin
-  GetBitmap;
-end;
-
-procedure TJPEGImage.Draw(ACanvas: TCanvas; const Rect: TRect);
-begin
-  ACanvas.StretchDraw(Rect, Bitmap);
-end;
-
-function TJPEGImage.Equals(Graphic: TGraphic): Boolean;
-begin
-  Result := (Graphic is TJPEGImage) and
-    (FImage = TJPEGImage(Graphic).FImage); { ---!! }
-end;
-
-procedure TJPEGImage.FreeBitmap;
-begin
-  FBitmap.Free;
-  FBitmap := nil;
-end;
-
-function BuildPalette(const cinfo: jpeg_decompress_struct): HPalette;
-var
-  Pal: TMaxLogPalette;
-  I: Integer;
-  C: Byte;
-begin
-  Pal.palVersion := $300;
-  Pal.palNumEntries := cinfo.actual_number_of_colors;
-  if cinfo.out_color_space = JCS_GRAYSCALE then
-    for I := 0 to Pal.palNumEntries-1 do
-    begin
-      C := cinfo.colormap^[0]^[I];
-      Pal.palPalEntry[I].peRed := C;
-      Pal.palPalEntry[I].peGreen := C;
-      Pal.palPalEntry[I].peBlue := C;
-      Pal.palPalEntry[I].peFlags := 0;
-    end
-  else
-    for I := 0 to Pal.palNumEntries-1 do
-    begin
-      Pal.palPalEntry[I].peRed := cinfo.colormap^[2]^[I];
-      Pal.palPalEntry[I].peGreen := cinfo.colormap^[1]^[I];
-      Pal.palPalEntry[I].peBlue := cinfo.colormap^[0]^[I];
-      Pal.palPalEntry[I].peFlags := 0;
-    end;
-  Result := CreatePalette(PLogPalette(@Pal)^);
-end;
-
-procedure BuildColorMap(var cinfo: jpeg_decompress_struct; P: HPalette);
-var
-  Pal: TMaxLogPalette;
-  Count, I: Integer;
-begin
-  Count := GetPaletteEntries(P, 0, 256, Pal.palPalEntry);
-  if Count = 0 then Exit;       { jpeg_destroy will free colormap }
-  cinfo.colormap := cinfo.mem.alloc_sarray(j_common_ptr(@cinfo), JPOOL_IMAGE, Count, 3);
-  cinfo.actual_number_of_colors := Count;
-  for I := 0 to Count-1 do
-  begin
-    Byte(cinfo.colormap^[2]^[I]) := Pal.palPalEntry[I].peRed;
-    Byte(cinfo.colormap^[1]^[I]) := Pal.palPalEntry[I].peGreen;
-    Byte(cinfo.colormap^[0]^[I]) := Pal.palPalEntry[I].peBlue;
-  end;
-end;
-
-function TJPEGImage.GetBitmap: TBitmap;
-var
-  LinesPerCall, LinesRead: Integer;
-  DestScanLine: Pointer;
-  PtrInc: Integer;
-  jc: TJPEGContext;
-  GeneratePalette: Boolean;
-begin
-  Result := FBitmap;
-  if Result <> nil then Exit;
-  if (FBitmap = nil) then FBitmap := TBitmap.Create;
-  Result := FBitmap;
-  GeneratePalette := True;
-
-  InitDecompressor(Self, jc);
-  try
-    try
-      { Set the bitmap pixel format }
-      FBitmap.Handle := 0;
-      if (PixelFormat = jf8Bit) or (jc.d.out_color_space = JCS_GRAYSCALE) then
-        FBitmap.PixelFormat := pf8bit
-      else
-        FBitmap.PixelFormat := pf24bit;
-
-      Progress(Self, psStarting, 0, False, Rect(0,0,0,0), '');
-      try
-        if (FTempPal <> 0) then
-        begin
-          if (FPixelFormat = jf8Bit) then
-          begin                        { Generate DIB using assigned palette }
-            BuildColorMap(jc.d, FTempPal);
-            FBitmap.Palette := CopyPalette(FTempPal);  { Keep FTempPal around }
-            GeneratePalette := False;
-          end
-          else
-          begin
-            DeleteObject(FTempPal);
-            FTempPal := 0;
-          end;
-        end;
-
-        jpeg_start_decompress(@jc.d);
-
-        { Set bitmap width and height }
-        with FBitmap do
-        begin
-          Handle := 0;
-          Width := jc.d.output_width;
-          Height := jc.d.output_height;
-          DestScanline := ScanLine[0];
-          PtrInc := Integer(ScanLine[1]) - Integer(DestScanline);
-          if (PtrInc > 0) and ((PtrInc and 3) = 0) then
-             { if no dword padding is required and output bitmap is top-down }
-            LinesPerCall := jc.d.rec_outbuf_height { read multiple rows per call }
-          else
-            LinesPerCall := 1;            { otherwise read one row at a time }
-        end;
-
-        if jc.d.buffered_image then
-        begin  { decode progressive scans at low quality, high speed }
-          while jpeg_consume_input(@jc.d) <> JPEG_REACHED_EOI do
-          begin
-            jpeg_start_output(@jc.d, jc.d.input_scan_number);
-            { extract color palette }
-            if (jc.common.progress^.completed_passes = 0) and (jc.d.colormap <> nil)
-              and (FBitmap.PixelFormat = pf8bit) and GeneratePalette then
-            begin
-              FBitmap.Palette := BuildPalette(jc.d);
-              PaletteModified := True;
-            end;
-            DestScanLine := FBitmap.ScanLine[0];
-            while (jc.d.output_scanline < jc.d.output_height) do
-            begin
-              LinesRead := jpeg_read_scanlines(@jc.d, @DestScanline, LinesPerCall);
-              Inc(Integer(DestScanline), PtrInc * LinesRead);
-            end;
-            jpeg_finish_output(@jc.d);
-          end;
-          { reset options for final pass at requested quality }
-          jc.d.dct_method := jc.FinalDCT;
-          jc.d.dither_mode := jc.FinalDitherMode;
-          if jc.FinalTwoPassQuant then
-          begin
-            jc.d.two_pass_quantize := True;
-            jc.d.colormap := nil;
-          end;
-          jpeg_start_output(@jc.d, jc.d.input_scan_number);
-          DestScanLine := FBitmap.ScanLine[0];
-        end;
-
-        { build final color palette }
-        if (not jc.d.buffered_image or jc.FinalTwoPassQuant) and
-          (jc.d.colormap <> nil) and GeneratePalette then
-        begin
-          FBitmap.Palette := BuildPalette(jc.d);
-          PaletteModified := True;
-          DestScanLine := FBitmap.ScanLine[0];
-        end;
-        { final image pass for progressive, first and only pass for baseline }
-        while (jc.d.output_scanline < jc.d.output_height) do
-        begin
-          LinesRead := jpeg_read_scanlines(@jc.d, @DestScanline, LinesPerCall);
-          Inc(Integer(DestScanline), PtrInc * LinesRead);
-        end;
-
-        if jc.d.buffered_image then jpeg_finish_output(@jc.d);
-        jpeg_finish_decompress(@jc.d);
-      finally
-        if ExceptObject = nil then
-          PtrInc := 100
-        else
-          PtrInc := 0;
-        Progress(Self, psEnding, PtrInc, PaletteModified, Rect(0,0,0,0), '');
-        { Make sure new palette gets realized, in case OnProgress event didn't. }
-        if PaletteModified then
-          Changed(Self);
-      end;
-    except
-      on EAbort do ;   { OnProgress can raise EAbort to cancel image load }
-    end;
-  finally
-    ReleaseContext(jc);
-  end;
-end;
-
-function TJPEGImage.GetEmpty: Boolean;
-begin
-  Result := (FImage.FData = nil) and FBitmap.Empty;
-end;
-
-function TJPEGImage.GetGrayscale: Boolean;
-begin
-  Result := FGrayscale or FImage.FGrayscale;
-end;
-
-function TJPEGImage.GetPalette: HPalette;
-var
-  DC: HDC;
-begin
-  Result := 0;
-  if FBitmap <> nil then
-    Result := FBitmap.Palette
-  else if FTempPal <> 0 then
-    Result := FTempPal
-  else if FPixelFormat = jf24Bit then   { check for 8 bit screen }
-  begin
-    DC := GetDC(0);
-    if (GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES)) <= 8 then
-    begin
-      if FTempPal <> 0 then DeleteObject(FTempPal);  { Memory leak -- fix }
-      FTempPal := CreateHalftonePalette(DC);
-      Result := FTempPal;
-    end;
-    ReleaseDC(0, DC);
-  end;
-end;
-
-function TJPEGImage.GetHeight: Integer;
-begin
-  if FBitmap <> nil then
-    Result := FBitmap.Height
-  else if FScale = jsFullSize then
-    Result := FImage.FHeight
-  else
-  begin
-    CalcOutputDimensions;
-    Result := FScaledHeight;
-  end;
-end;
-
-function TJPEGImage.GetWidth: Integer;
-begin
-  if FBitmap <> nil then
-    Result := FBitmap.Width
-  else if FScale = jsFullSize then
-    Result := FImage.FWidth
-  else
-  begin
-    CalcOutputDimensions;
-    Result := FScaledWidth;
-  end;
-end;
-
-procedure TJPEGImage.JPEGNeeded;
-begin
-  if FImage.FData = nil then
-    Compress;
-end;
-
-procedure TJPEGImage.LoadFromClipboardFormat(AFormat: Word; AData: THandle;
-  APalette: HPALETTE);
-begin
-  { --!! check for jpeg clipboard data, mime type image/jpeg }
-  FBitmap.LoadFromClipboardFormat(AFormat, AData, APalette);
-end;
-
-procedure TJPEGImage.LoadFromStream(Stream: TStream);
-begin
-  ReadStream(Stream.Size - Stream.Position, Stream);
-end;
-
-procedure TJPEGImage.NewBitmap;
-begin
-  FBitmap.Free;
-  FBitmap := TBitmap.Create;
-end;
-
-procedure TJPEGImage.NewImage;
-begin
-  if FImage <> nil then FImage.Release;
-  FImage := TJPEGData.Create;
-  FImage.Reference;
-end;
-
-procedure TJPEGImage.ReadData(Stream: TStream);
-var
-  Size: Longint;
-begin
-  Stream.Read(Size, SizeOf(Size));
-  ReadStream(Size, Stream);
-end;
-
-procedure TJPEGImage.ReadStream(Size: Longint; Stream: TStream);
-var
-  jerr: jpeg_error_mgr;
-  cinfo: jpeg_decompress_struct;
-begin
-  NewImage;
-  with FImage do
-  begin
-    FData := TMemoryStream.Create;
-    FData.Size := Size;
-    Stream.ReadBuffer(FData.Memory^, Size);
-    if Size > 0 then
-    begin
-      jerr := jpeg_std_error;  { use local var for thread isolation }
-      cinfo.err := @jerr;
-      jpeg_CreateDecompress(@cinfo, JPEG_LIB_VERSION, sizeof(cinfo));
-      try
-        FData.Position := 0;
-        jpeg_stdio_src(@cinfo, @FData);
-        jpeg_read_header(@cinfo, TRUE);
-        FWidth := cinfo.image_width;
-        FHeight := cinfo.image_height;
-        FGrayscale := cinfo.jpeg_color_space = JCS_GRAYSCALE;
-        FProgressiveEncoding := jpeg_has_multiple_scans(@cinfo);
-      finally
-        jpeg_destroy_decompress(@cinfo);
-      end;
-    end;
-  end;
-  PaletteModified := True;
-  Changed(Self);
-end;
-
-procedure TJPEGImage.SaveToClipboardFormat(var AFormat: Word; var AData: THandle;
-  var APalette: HPALETTE);
-begin
-{ --!!  check for jpeg clipboard format, mime type image/jpeg }
-  Bitmap.SaveToClipboardFormat(AFormat, AData, APalette);
-end;
-
-procedure TJPEGImage.SaveToStream(Stream: TStream);
-begin
-  JPEGNeeded;
-  with FImage.FData do
-    Stream.Write(Memory^, Size);
-end;
-
-procedure TJPEGImage.SetGrayscale(Value: Boolean);
-begin
-  if FGrayscale <> Value then
-  begin
-    FreeBitmap;
-    FGrayscale := Value;
-    PaletteModified := True;
-    Changed(Self);
-  end;
-end;
-
-procedure TJPEGImage.SetHeight(Value: Integer);
-begin
-  InvalidOperation(SChangeJPGSize);
-end;
-
-procedure TJPEGImage.SetPalette(Value: HPalette);
-var
-  SignalChange: Boolean;
-begin
-  if Value <> FTempPal then
-  begin
-    SignalChange := (FBitmap <> nil) and (Value <> FBitmap.Palette);
-    if SignalChange then FreeBitmap;
-    FTempPal := Value;
-    if SignalChange then
-    begin
-      PaletteModified := True;
-      Changed(Self);
-    end;
-  end;
-end;
-
-procedure TJPEGImage.SetPerformance(Value: TJPEGPerformance);
-begin
-  if FPerformance <> Value then
-  begin
-    FreeBitmap;
-    FPerformance := Value;
-    PaletteModified := True;
-    Changed(Self);
-  end;
-end;
-
-procedure TJPEGImage.SetPixelFormat(Value: TJPEGPixelFormat);
-begin
-  if FPixelFormat <> Value then
-  begin
-    FreeBitmap;
-    FPixelFormat := Value;
-    PaletteModified := True;
-    Changed(Self);
-  end;
-end;
-
-procedure TJPEGImage.SetScale(Value: TJPEGScale);
-begin
-  if FScale <> Value then
-  begin
-    FreeBitmap;
-    FScale := Value;
-    FNeedRecalc := True;
-    Changed(Self);
-  end;
-end;
-
-procedure TJPEGImage.SetSmoothing(Value: Boolean);
-begin
-  if FSmoothing <> Value then
-  begin
-    FreeBitmap;
-    FSmoothing := Value;
-    Changed(Self);
-  end;
-end;
-
-procedure TJPEGImage.SetWidth(Value: Integer);
-begin
-  InvalidOperation(SChangeJPGSize);
-end;
-
-procedure TJPEGImage.WriteData(Stream: TStream);
-var
-  Size: Longint;
-begin
-  Size := 0;
-  if Assigned(FImage.FData) then Size := FImage.FData.Size;
-  Stream.Write(Size, Sizeof(Size));
-  if Size > 0 then Stream.Write(FImage.FData.Memory^, Size);
-end;
-
-procedure InitDefaults;
-var
-  DC: HDC;
-begin
-  DC := GetDC(0);
-  if (GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES)) <= 8 then
-    JPEGDefaults.PixelFormat := jf8Bit
-  else
-    JPEGDefaults.PixelFormat := jf24Bit;
-  ReleaseDC(0, DC);
-end;
-
-initialization
-  InitDefaults;
-  TPicture.RegisterFileFormat('jpg', 'JPEG Image File', TJPEGImage);
-  TPicture.RegisterFileFormat('jpeg', 'JPEG Image File', TJPEGImage);
-finalization
-  TPicture.UnregisterGraphicClass(TJPEGImage);
-end.