⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpegfilt.pas

📁 ·ImageEn 2.3.0 ImageEn一组用于图像处理、查看和分析的Delphi控件。能够保存几种图像格式
💻 PAS
📖 第 1 页 / 共 5 页
字号:
    IOParams.JPEG_Progressive := cinfo.progressive_mode;
    IOParams.JPEG_OriginalWidth := cinfo.image_width;
    IOParams.JPEG_OriginalHeight := cinfo.image_height;
    cinfo.scale_num := 1;
    case IOParams.JPEG_Scale of
      ioJPEG_FULLSIZE: cinfo.scale_denom := 1;
      ioJPEG_HALF: cinfo.scale_denom := 2;
      ioJPEG_QUARTER: cinfo.scale_denom := 4;
      ioJPEG_EIGHTH: cinfo.scale_denom := 8;
      ioJPEG_AUTOCALC:
        begin
          // Calc from IOParams.Width and IOParmas.Height
          if (IOParams.Width > 0) and (IOParams.Height > 0) then
          begin
            bst := 0;
            for xx := 3 downto 0 do
            begin
              dv := 1 shl xx;
              if ((integer(cinfo.image_width) div dv) >= IOParams.Width) and ((integer(cinfo.image_height) div dv) >= IOParams.Height) then
              begin
                bst := xx;
                break;
              end;
            end;
            cinfo.scale_denom := 1 shl bst;
          end
          else
            cinfo.scale_denom := 1;
        end;
    end;
    IOParams.JPEG_Scale_Used := cinfo.scale_denom;

    if Preview then
    begin
      IOParams.Width := cinfo.image_width;
      IOParams.Height := cinfo.image_height;
      exit;
    end;

    //
    try
      jpeg_start_decompress(cinfo);
    except
      xProgress.Aborting^ := true;
      exit;
    end;
    if xProgress.Aborting^ then
      exit;
    IOParams.Width := cinfo.output_width;
    IOParams.Height := cinfo.output_height;

    getmem(buff, cinfo.output_width * 4);

    if IOParams.IsNativePixelFormat then
    begin
      case cinfo.out_color_space of
        JCS_GRAYSCALE: Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie8g);
        JCS_RGB:       Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
        JCS_YCbCr:     Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
        JCS_CMYK:      Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ieCMYK);
        JCS_YCCK:      Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);
      end;
    end
    else
      Bitmap.Allocate(cinfo.output_width, cinfo.output_height, ie24RGB);

    if MaxRows<0 then
      MaxRows:=Bitmap.Height;

    xProgress.per1 := 100 / cinfo.output_height;
    xProgress.val := 0;
    try
      tlr := 0;
      LinesRead := 1;
      while (cinfo.output_scanline < cinfo.output_height) and (tlr<MaxRows) do
      begin
        DestScanline := Bitmap.Scanline[tlr];

        case cinfo.out_color_space of
          JCS_GRAYSCALE:
            begin
              if Bitmap.PixelFormat=ie8g then
                LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1)
              else
              begin
                LinesRead := jpeg_read_scanlines(cinfo, @buff, 1);
                xrgb:=DestScanline;
                pb:=buff;
                for xx:=0 to cinfo.output_width-1 do
                begin
                  with xrgb^ do
                  begin
                    r:=pb^;
                    g:=pb^;
                    b:=pb^;
                  end;
                  inc(pb);
                  inc(xrgb);
                end;
              end;
            end;

          JCS_YCCK:
            begin
              // this should be never happens because YCCK is converted to CMYK
            end;

          JCS_YCbCr:
            begin
              if Raw then
              begin
                LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1);
                if cinfo.jpeg_color_space=JCS_RGB then
                  _BGR2RGB(PRGB(DestScanline), Bitmap.Width);
              end;
            end;

          JCS_CMYK:
            begin
              if Bitmap.PixelFormat=ie24RGB then
              begin
                // convert CMYK->RGB
                LinesRead := jpeg_read_scanlines(cinfo, @buff, 1);
                if xProgress.Aborting^ then
                  break;
                if invertCMYK then
                begin
                  pb:=buff;
                  for xx:=0 to (cinfo.output_width-1)*4 do
                  begin
                    pb^:=255-pb^;
                    inc(pb);
                  end;
                end;
                IEConvertColorFunction(buff, iecmsCMYK, DestScanline, iecmsBGR, cinfo.output_width, IOParams);
              end
              else
              begin
                // native CMYK format
                LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1);
                if xProgress.Aborting^ then
                  break;
              end;
            end;

          JCS_RGB:
            begin
              if HasICC then
              begin
                LinesRead := jpeg_read_scanlines(cinfo, @buff, 1);
                // 2.2.8
                if cinfo.jpeg_color_space=JCS_RGB then
                  IEConvertColorFunction(buff, iecmsRGB, DestScanline, iecmsBGR, cinfo.output_width, IOParams)
                else
                  IEConvertColorFunction(buff, iecmsBGR, DestScanline, iecmsBGR, cinfo.output_width, IOParams);
              end
              else
              begin
                LinesRead := jpeg_read_scanlines(cinfo, @DestScanline, 1);
                if cinfo.jpeg_color_space=JCS_RGB then
                  _BGR2RGB(PRGB(DestScanline), Bitmap.Width);
              end;
            end;

        end;

        inc(tlr, LinesRead);
        // OnProgress
        with xProgress do
        begin
          inc(val, LinesRead);
          if assigned(fOnProgress) then
            fOnProgress(Sender, trunc(per1 * val));
        end;
        if xProgress.Aborting^ then
          break;
      end;
    except
      xProgress.Aborting^ := true;
      exit;
    end;
    if tlr < MaxRows then
    begin
      xProgress.Aborting^ := true;
      exit;
    end;
  finally

    // save markers to IOParams.JPEG_MarkerList
    IOParams.JPEG_MarkerList.Clear;
    markers := cinfo.marker_list;
    bo := false;
    while markers <> nil do
    begin
      if (markers.marker <> JPEG_APP0) or bo then // this remove first APP0 (the header + RGB thumbnail)
        IOParams.JPEG_MarkerList.AddMarker(markers.marker, pchar(markers.data), markers.data_length);
      if markers.marker = JPEG_APP0 then
        bo:=true;
      markers := markers^.next;
    end;

    // ICC profile applied: free CMS transform and remove jpeg ICC markers
    if freeICC and HasICC and (IOParams.InputICCProfile.IsTransforming) then
    begin
      IOParams.InputICCProfile.FreeTransform;
      while true do
      begin
        i:=IOParams.JPEG_MarkerList.IndexOf( M_APP2 );
        if i=-1 then
          break;
        IOParams.JPEG_MarkerList.DeleteMarker( i );
      end;
    end;

    //
    if (not xProgress.Aborting^) and not Preview then
    begin
      jerr.aborting := nil; // from this point decoder can't generate aborting
      try
        jpeg_finish_decompress(cinfo);
      except
      end;
    end;
    jpeg_destroy_decompress(cinfo);
    if buff <> nil then
      freemem(buff);
    //
    if cinfo.common.err.num_warnings <> 0 then
    begin
      IOParams.JPEG_WarningTot := cinfo.common.err.num_warnings;
      IOParams.JPEG_WarningCode := cinfo.common.err.msg_code;
    end;
    jpeg_ie_src_free(@cinfo);

    if ReadMetaTags then
    begin
      with IOParams.JPEG_MarkerList do
      begin
        // IPTC
        mi := IndexOf(JPEG_APP13);
        if mi >= 0 then
          IOParams.IPTC_Info.LoadFromStandardBuffer(MarkerData[mi], MarkerLength[mi]);
        // EXIF
        mi := IndexOf(JPEG_APP1);
        if mi >= 0 then
        begin
          // we saves current DPI because LoadEXIFFromStandardBuffer will change them
          xdpi:=IOParams.DpiX;
          ydpi:=IOParams.DpiY;
          if LoadEXIFFromStandardBuffer(MarkerData[mi], MarkerLength[mi], IOParams) then
          begin
            // exif found
            if (xdpi = 1) and (ydpi = 1) then
            begin
              // use dpi of the Exif
              if IOParams.EXIF_ResolutionUnit = 3 then
                dd := 2.54
              else
                dd := 1;
              IOParams.DpiX := trunc(IOParams.EXIF_XResolution * dd);
              IOParams.DpiY := trunc(IOParams.EXIF_YResolution * dd);
            end
            else
            begin
              IOParams.DpiX:=xdpi;
              IOParams.DpiY:=ydpi;
            end;
            //IEChangeYCbCrCoefficients(Bitmap, 0.299,0.587,0.114, IOParams.EXIF_YCbCrCoefficients[0],IOParams.EXIF_YCbCrCoefficients[1],IOParams.EXIF_YCbCrCoefficients[2]);
            if IOParams.JPEG_EnableAdjustOrientation then
              IEAdjustEXIFOrientation(Bitmap,IOParams.EXIF_Orientation);
          end;
        end;
        // XMP
        for mi:=0 to Count-1 do
          if (MarkerType[mi]=JPEG_APP1) and (IEFindXMPFromJpegTag(MarkerData[mi], MarkerLength[mi])<>nil) then
          begin
            IELoadXMPFromJpegTag(MarkerData[mi], MarkerLength[mi], IOParams);
            break;
          end;
      end;
    end;

  end;
  {$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;

// write jpeg stream

procedure WriteJPegStream(Stream: TStream; bitmap: TIEBitmap; var IOParams: TIOParamsVals; var xProgress: TProgressRec);
var
  cinfo: jpeg_compress_struct;
  jerr: jpeg_error_mgr;
  SrcScanLine: pbyte;
  buff, xbuff: PRGB;
  xrgb, yrgb: PRGB;
  xx: integer;
  LinesPerCall, LinesWritten: integer;
  FreeW: boolean;
  WBitmap: TIEBitmap;
  colspc: J_COLOR_SPACE;
  nullpr: TProgressRec;
  tlr: integer;
begin
  {$ifdef IEPROFILE} try IEProfileBegin('WriteJPegStream'); {$endif}
  with nullpr do
  begin
    Aborting := xProgress.Aborting;
    fOnProgress := nil;
    Sender := nil;
  end;
  // adjust Bitmap
  if Bitmap.PixelFormat <> ie24RGB then
  begin
    WBitmap := TIEBitmap.Create;
    WBitmap.Assign(Bitmap);
    WBitmap.PixelFormat := ie24RGB; // converts to 24bit
    FreeW := true;
  end
  else
  begin
    WBitmap := Bitmap;
    FreeW := false;
  end;
  //
  buff := nil;
  if (bitmap.Width = 0) or (bitmap.Height = 0) then
  begin
    xProgress.Aborting^ := true;
    exit;
  end;
  jerr.aborting := xProgress.Aborting;
  jerr := jpeg_std_error;
  cinfo.common.err := @jerr;
  jpeg_Create

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -