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

📄 pngfiltw.pas

📁 ·ImageEn 2.3.0 ImageEn一组用于图像处理、查看和分析的Delphi控件。能够保存几种图像格式
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  if (IOParams.BitsPerSample = 1) then
  begin
    // required to save to b/w
    if Bitmap.pixelformat = ie1g then
      WBitmap := Bitmap
    else
    begin
      // convert to 1 bit
      WBitmap := _ConvertTo1bitEx(Bitmap, BackCol, ForeCol);
      if WBitmap = nil then
      begin
        // impossible to convert to 1 bit, convert to ordered dither
        WBitmap := TIEBitmap.Create;
        WBitmap.Assign(Bitmap);
        WBitmap.PixelFormat := ie1g;
      end;
      FreeW := true;
    end;
  end
  else
  begin
    // required to save in true color
    if Bitmap.pixelformat = ie1g then
    begin
      // convert to 24 bit
      WBitmap := TIEBitmap.Create;
      WBitmap.Assign(Bitmap);
      WBitmap.PixelFormat := ie24RGB;
      FreeW := true;
    end
    else
      WBitmap := Bitmap;
  end;
  // assign interlace_type
  if ioparams.PNG_Interlaced then
    interlace_type := PNG_INTERLACE_ADAM7
  else
    interlace_type := PNG_INTERLACE_NONE;
  // assign bit_depth and color_type
  if ioparams.SamplesPerPixel = 1 then
  begin
    // B/W or palette
    if wbitmap.pixelformat = ie1g then
    begin
      // B/W
      color_type := PNG_COLOR_TYPE_GRAY;
      bit_depth := 1;
    end
    else
    begin
      // palette
      color_type := PNG_COLOR_TYPE_PALETTE;
      bit_depth := ioparams.BitsPerSample;
    end;
  end
  else
  begin
    // true color
    color_type := PNG_COLOR_TYPE_RGB;
    bit_depth := 8;
  end;
  hasalpha := assigned(AlphaChannel) and (not AlphaChannel.Full);
  if hasalpha and (color_type = PNG_COLOR_TYPE_RGB) then
    color_type := color_type or PNG_COLOR_MASK_ALPHA;

  // Create palette if needed
  if (ioparams.SamplesPerPixel = 1) and (ioparams.BitsPerSample > 1) and (wbitmap.pixelformat <> ie1g) then
  begin
    if hasalpha then
    begin
      // save alpha channel as an entry in the color map (here 16 bit gray isn't supported)
      bit_depth := 8;
      bps := 1 shl ioparams.BitsPerSample;
      qt := TIEQuantizer.Create(wBitmap, palette, imin(bps, 255), -1, 0); // entry 0 reserved for transparent layer
      getmem(ppalette, 256 * sizeof(TRGB));
      copymemory(@(ppalette[1]), @(palette[0]), 255 * sizeof(TRGB));
      with ppalette[0] do
      begin
        r := ioparams.PNG_Background.r;
        g := ioparams.PNG_Background.g;
        b := ioparams.PNG_Background.b;
      end;
      for x := 0 to 255 do
        bswap(ppalette^[x].r, ppalette^[x].b);
      png_set_PLTE(png_ptr, info_ptr, png_colorp(ppalette), imin(bps + 1, 256));
      if hasalpha then
      begin
        bb := 0;
        png_set_tRNS(png_ptr, info_ptr, @bb, 1, nil);
      end;
    end
    else
    begin
      // do not save alpha. Full gray and 16 bit gray supported
      qt := TIEQuantizer.Create(wBitmap, palette, 256, -1, 0);
      getmem(ppalette, 256 * sizeof(TRGB));
      copymemory(@(ppalette[0]), @(palette[0]), 256 * sizeof(TRGB));
      for x := 0 to 255 do
        bswap(ppalette^[x].r, ppalette^[x].b);
      if not qt.GrayScale then
        png_set_PLTE(png_ptr, info_ptr, png_colorp(ppalette), 256)
      else
        color_type := PNG_COLOR_TYPE_GRAY;
    end;
  end
  else
  begin
    qt := nil;
    ppalette := nil;
  end;
  png_set_IHDR(png_ptr, info_ptr, bitmap.width, bitmap.height, bit_depth, color_type,
    interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  // DPI
  png_set_pHYs(png_ptr, info_ptr, round(ioparams.DPIX * 100 / 2.54), round(ioparams.DPIY * 100 / 2.54), PNG_RESOLUTION_METER);
  //
  case ioparams.PNG_Filter of
    ioPNG_FILTER_NONE: png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
    ioPNG_FILTER_SUB: png_set_filter(png_ptr, 0, PNG_FILTER_SUB);
    ioPNG_FILTER_PAETH: png_set_filter(png_ptr, 0, PNG_FILTER_PAETH);
  end;
  // set background
  zeromemory(@background, sizeof(background));
  if assigned(qt) then
    background.index := qt.RGBIndex[ioparams.PNG_Background]
  else
  begin
    background.red := ioparams.PNG_Background.r *257;
    background.green := ioparams.PNG_Background.g *257;
    background.blue := ioparams.PNG_Background.b *257;
  end;
  png_set_bKGD(png_ptr, info_ptr, @background);
  //
  png_set_compression_level(png_ptr, ioparams.PNG_Compression);
  //
  png_set_bgr(png_ptr);

  // write text
  num_text:=imin(IOParams.PNG_TextKeys.Count, IOParams.PNG_TextValues.Count);
  getmem(png_text_mem, sizeof(tpng_text)*num_text);
  png_text_idx:=png_text_mem;
  for i:=0 to num_text-1 do
  begin
    png_text_idx^.compression:=-1;
    png_text_idx^.key:=pchar(IOParams.PNG_TextKeys[i]);
    png_text_idx^.text:=pchar(IOParams.PNG_TextValues[i]);
    png_text_idx^.text_length:=length( IOParams.PNG_TextValues[i] );
    inc(png_text_idx);
  end;
  png_set_text(png_ptr,info_ptr, png_text_mem, num_text);

  png_write_info(png_ptr, info_ptr);
  // write rows
  number_passes := png_set_interlace_handling(png_ptr);
  height := wbitmap.height;
  width := wbitmap.width;
  xProgress.per1 := 100 / (height * number_passes);
  xProgress.val := 0;
  px2 := nil;
  if (color_type = PNG_COLOR_TYPE_PALETTE) or (color_type = PNG_COLOR_TYPE_GRAY) then
    getmem(px, wbitmap.width * imax(1, bit_depth div 8));
  if (color_type and PNG_COLOR_MASK_ALPHA) <> 0 then
    getmem(px2, wbitmap.width * sizeof(TRGBA));
  for pass := 0 to number_passes - 1 do
  begin
    for y := 0 to height - 1 do
    begin
      if (color_type and PNG_COLOR_MASK_PALETTE) <> 0 then
      begin
        // palette
        brow := px;
        pp := wbitmap.scanline[y];
        px_byte := pbyte(pp);
        bitmapwidth1 := wbitmap.width - 1;
        if assigned(AlphaChannel) and (not AlphaChannel.Full) then
        begin
          // alpha channel
          case wbitmap.PixelFormat of
            ie24RGB:
              begin
                px3 := alphachannel.scanline[y];
                for x := 0 to bitmapwidth1 do
                begin
                  if px3^ < 255 then
                    brow^ := 0
                  else
                    brow^ := qt.RGBIndex[pp^] + 1;
                  inc(brow);
                  inc(pp);
                  inc(px3);
                end;
              end;
            ie8p:
              begin
                // search an alternate color for indexes with transparent index
                d:=100000;
                tcl:=wbitmap.Palette[0];
                altindex:=0;
                for i:=1 to wbitmap.PaletteLength-1 do
                begin
                  with wbitmap.Palette[i] do
                  begin
                    dt := sqr(r-tcl.r)+sqr(g-tcl.g)+sqr(b-tcl.b);
                    if dt<d then
                    begin
                      d:=dt;
                      altindex:=i;
                    end;
                  end;
                end;

                for x := 0 to bitmapwidth1 do
                begin
                  brow^ := px_byte^;
                  if brow^=0 then
                    brow^:=altindex;
                  inc(brow);
                  inc(px_byte);
                end;
              end;
          end
        end
        else
        begin
          // simple palette
          case wbitmap.pixelformat of
            ie24RGB:
              for x := 0 to bitmapwidth1 do
              begin
                brow^ := qt.RGBIndex[pp^];
                inc(brow);
                inc(pp);
              end;
            ie8p:
              for x := 0 to bitmapwidth1 do
              begin
                brow^ := px_byte^;
                inc(brow);
                inc(px_byte);
              end;
          end;
        end;
        png_write_rows(png_ptr, @px, 1);
      end
      else if (color_type and PNG_COLOR_MASK_COLOR) <> 0 then
      begin
        // truecolor
        if (color_type and PNG_COLOR_MASK_ALPHA) <> 0 then
        begin
          // alpha channel
          pp := wbitmap.scanline[y];
          px3 := alphachannel.scanline[y];
          px4 := px2;
          for x := 0 to width - 1 do
          begin
            with px4^ do
            begin
              r := pp^.r;
              g := pp^.g;
              b := pp^.b;
              a := px3^;
            end;
            inc(pp);
            inc(px3);
            inc(px4);
          end;
          png_write_rows(png_ptr, @px2, 1);
        end
        else
        begin
          ppx := wbitmap.scanline[y];
          png_write_rows(png_ptr, @ppx, 1);
        end;
      end
      else if (color_type = PNG_COLOR_TYPE_GRAY) then
      begin
        // gray scale
        if bit_depth = 16 then
        begin
          case wbitmap.pixelformat of
            ie24RGB:
              begin
                pp := wbitmap.scanline[y];
                pw := px;
                for x := 0 to width - 1 do
                begin
                  pw^ := qt.RGBIndex[pp^];
                  inc(pw);
                  inc(pp);
                end;
              end;
            ie16g:
              begin
                px_word := wbitmap.scanline[y];
                pw := px;
                for x := 0 to width - 1 do
                begin
                  pw^ := px_word^ shr 8;
                  inc(pw);
                  inc(px_word);
                end;
              end;
          end;
          png_write_rows(png_ptr, @px, 1);
        end
        else if bit_depth = 8 then
        begin
          case wbitmap.pixelformat of
            ie24RGB:
              begin
                pp := wbitmap.scanline[y];
                brow := px;
                for x := 0 to width - 1 do
                begin
                  brow^ := qt.RGBIndex[pp^];
                  inc(brow);
                  inc(pp);
                end;
              end;
            ie8g:
              begin
                px_byte := wbitmap.scanline[y];
                brow := px;
                for x := 0 to width - 1 do
                begin
                  brow^ := px_byte^;
                  inc(brow);
                  inc(px_byte);
                end;
              end;
          end;
          png_write_rows(png_ptr, @px, 1);
        end
        else
        begin
          ppx := wbitmap.scanline[y];
          png_write_rows(png_ptr, @ppx, 1);
        end;
      end;
      // OnProgress
      with xProgress do
      begin
        inc(val);
        if assigned(fOnProgress) then
          fOnProgress(Sender, trunc(per1 * val));
      end;
      if xProgress.Aborting^ then
        break;
    end;
    if xProgress.Aborting^ then
      break;
  end;
  if (color_type and PNG_COLOR_MASK_ALPHA) <> 0 then
    freemem(px2);
  if (color_type = PNG_COLOR_TYPE_PALETTE) or (color_type = PNG_COLOR_TYPE_GRAY) then
    freemem(px);
  // fine
  if not xProgress.Aborting^ then
    png_write_end(png_ptr, info_ptr);
  if ppalette <> nil then
    freemem(ppalette);
  png_destroy_write_struct(@png_ptr, @info_ptr);
  if FreeW then
    FreeAndNil(WBitmap);
  if assigned(qt) then
    FreeAndNil(qt);
end;

{$ELSE} // IEINCLUDEPNG

interface
implementation

{$ENDIF}

end.

⌨️ 快捷键说明

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