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

📄 pngimage1.pas

📁 查看html文件的控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  GetMem(row_buffer, row_buffer_width);
  GetMem(filter_buffers[FILTERNONE], row_buffer_width);
  if efSub in Bitmap.Filter then
    GetMem(filter_buffers[FILTERSUB], row_buffer_width);
  if efUp in Bitmap.Filter then
    GetMem(filter_buffers[FILTERUP], row_buffer_width);
  if efAverage in Bitmap.Filter then
    GetMem(filter_buffers[FILTERAVERAGE], row_buffer_width);
  if efPaeth in Bitmap.Filter then
    GetMem(filter_buffers[FILTERPAETH], row_buffer_width);
  {Fill the filternone with zeros}
  ZeroMemory(@filter_buffers[FILTERNONE][0], row_buffer_width);

  Bitmap.Interlacing := FALSE;
  
  {Testing encoding method}
  if Bitmap.Interlacing then
  {No interlacing}
  begin
  end
  else
  {Interlacing}
  begin
    {Pass each row}
    for j := 0 to Bitmap.Height - 1 do
    begin

      {Write depending on the pixel format}
      case Bitmap.PixelFormat of
      pf1bit, pf4bit, pf8bit:
        filter := EncodeFilterRow(Bitmap.ScanLine[j], filter_buffers,
          row_buffer_width, offset);
      else
      begin
        {Copy pointer to the line bytes}
        Line := Bitmap.ScanLine[j];

        {Test the pixel format}
        case Bitmap.PixelFormat of
          {3 bytes, just swap}
          pf24bit:
          FOR i := 0 to Bitmap.Width - 1 do
          begin
            Row_Buffer^[i * 3] := AdjustValue(pRGBLine(Line)^[i].rgbtRed);
            Row_Buffer^[1 + (i * 3)] := AdjustValue(pRGBLine(Line)^[i].rgbtGreen);
            Row_Buffer^[2 + (i * 3)] := AdjustValue(pRGBLine(Line)^[i].rgbtBlue);
          end;
          {4 bytes, swap and ignore last byte unused}
          pf32bit:
          FOR i := 0 to Bitmap.Width - 1 do
          begin
            Row_Buffer^[i * 4] := AdjustValue(pRGBALine(Line)^[i].rgbRed);
            Row_Buffer^[1 + (i * 4)] := AdjustValue(pRGBALine(Line)^[i].rgbGreen);
            Row_Buffer^[2 + (i * 4)] := AdjustValue(pRGBALine(Line)^[i].rgbBlue);
          end;
        end;

        {Filter the row}
        filter := EncodeFilterRow(@Row_Buffer[0], filter_buffers,
          row_buffer_width, offset);
      end;
      end;

      (*Write to stream*)
      Encode.Write(Filter, 1);
      Encode.Write(filter_buffers[Filter]^[0], row_buffer_width);
    end;
  end;

  {Free the compression stream}
  Encode.Free;
  {Free memory from the filters}
  FreeMem(row_buffer, row_buffer_width);
  FreeMem(filter_buffers[FILTERNONE], row_buffer_width);
  if efSub in Bitmap.Filter then
    FreeMem(filter_buffers[FILTERSUB], row_buffer_width);
  if efUp in Bitmap.Filter then
    FreeMem(filter_buffers[FILTERUP], row_buffer_width);
  if efAverage in Bitmap.Filter then
    FreeMem(filter_buffers[FILTERAVERAGE], row_buffer_width);
  if efPaeth in Bitmap.Filter then
    FreeMem(filter_buffers[FILTERPAETH], row_buffer_width);

  {$IFDEF _SHAREWARE} Shareware {$ENDIF};
end;

{:Adjust image pixel format}
procedure TChunkIDAT.SetupPixelFormat;
var
  PlteIndex, i     : Integer;
  GrayscalePal     : TMaxLogPalette;
  GAMACHUNK        : TChunkGAMA;
begin
  (*{In case we need an alpha channel bitmap}
  if (IHDR.ColorType = GrayscaleALpha) or
    (IHDR.ColorType = RGBAlpha) then
  begin
    {Free the old mask}
    FreeAndNil(Bitmap.fMask);

    {Create a new bitmap}
    Bitmap.fMask := TBitmap.Create;

    {Set its properties}
    with Bitmap.fMask do
    begin
      Width := IHDR.Width;
      Height := IHDR.Height;
      PixelFormat := pf8bit;
    end;
  end; *)
  {Retrieve the chunk GAMA}
  GamaChunk := Gama;

  {Set the pixel formats}
  CASE IHDR.ColorType of
    GrayScale, Palette, GrayScaleAlpha:
    CASE IHDR.BitDepth of
      1: Bitmap.PixelFormat := pf1bit;     {1 bit, 2 colors: 2^1}
      2: Bitmap.PixelFormat := pf4bit;
      4: Bitmap.PixelFormat := pf4bit;
      8: Bitmap.PixelFormat := pf8bit;     {1 byte in each pixel, 256 colors}
     16: Bitmap.PixelFormat := pf8bit;     {2 bytes per sample}
    END;
    RGB, RGBALPHA:
    CASE IHDR.BitDepth of
      8: Bitmap.PixelFormat := pf24bit;    {R, G, B values for each pixel}
     16: Bitmap.PixelFormat := pf24bit;    {Increased range of values for RGB}
    END;
  END;

  {Create the palettes for the file formats}
  CASE IHDR.ColorType of
  Grayscale, GrayscaleAlpha:
 {Create grayscale palette}
  with GrayscalePal do
  begin
    palVersion := $300;

    {Set the number of colors in palette}
    {Since the max is 256 colors 16bit per sample pixels will be}
    {averanged to 8}
    if IHDR.BitDepth = 16 then
      palNumEntries := 256
    else
      palNumEntries := (1 shl IHDR.BitDepth);

    {Set the palette colors}
    FOR i := 0 to palNumEntries - 1 DO
      WITH palPalEntry[i] do
      begin
        {Average the colors}
        {When i is 0, the color is black}
        {When i is palNumEntries, the color is white}
        peRed := MulDiv(i, 255, palNumEntries - 1);
        {Correct using gamma}
        if Assigned(GamaChunk) then
          peRed := GamaChunk.GammaTable[peRed];
        peGreen := peRed;
        peBlue := peGreen;
        peFlags := PC_NOCOLLAPSE;
      end;

    IF (IHDR.BitDepth = 2) and (palNumEntries < 16) then
    begin
      {Note: This is really a crazy totally nonsence fix for supporting 2bit}
      palNumEntries := 16;
      copymemory(@palpalentry[4], @palpalentry[0], 21);
      copymemory(@palpalentry[8], @palpalentry[0], 21);
      copymemory(@palpalentry[12], @palpalentry[0], 21);
    end;

    {Apply the bitmap palette}
    Bitmap.Palette := CreatePalette(PLogPalette(@GrayscalePal)^);
  end;
  Palette:
  BEGIN
    {Test if there is PLTE chunk, if so apply the palette}
    PlteIndex := Owner.IndexOfClass(TChunkPLTE); { Paul }
    if PlteIndex <> -1 then
      Bitmap.Palette := TChunkPLTE(Owner[PlteIndex]).Palette
    ELSE
      CallError(PNG_ERROR_NO_PALETTE);
  END;
  END;
end;

{:Filters the row using definied types}
procedure TChunkIDAT.FilterRow(Filter: Byte; CurrentRow, LastRow: pByteArray;
  offset, row_buffer_width: Integer);
var
  Col: Integer;  {Current Column}
  Left, Above, AboveLeft: Integer;
  vv, pp: Integer;
begin

  // Filter the row based upon the filter type.
  case filter of
    {No filtering, do nothing}
    FILTERNONE: begin end;
    {Sub filter}
    FILTERSUB:
    {The value is the difference from the value to the left}
    for col := offset to row_buffer_width - 1 do
      CurrentRow[col] := (CurrentRow[col] + CurrentRow[col-offset]) AND $FF;
    FILTERUP:
    {The value is the difference from the value in the previous row.}
    for col := 0 to row_buffer_width - 1 do
      CurrentRow[col] := (CurrentRow[col] + LastRow[col]) AND $FF ;
    FILTERAVERAGE:
    for col := 0 to row_buffer_width - 1 do
    begin
      above := LastRow[col];

      if (col < offset) then
        left := 0
      else
        left := CurrentRow[col-offset] ;

      CurrentRow[col] := (CurrentRow[col] + (left + above) div 2) AND $FF ;
    end;
    FILTERPAETH:
    for col := 0 to row_buffer_width - 1 do
    begin
      above := LastRow[col] ;

      if (col < offset) then
      begin
        left := 0 ;
        aboveleft := 0 ;
      end
      else
      begin
        left := CurrentRow[col-offset] ;
        aboveleft := LastRow[col-offset] ;
      end;

      vv := CurrentRow[col] ;
      pp := PaethPredictor(left, above, aboveleft) ;
      CurrentRow[col] := (pp + vv) AND $FF ;
    end;
    else
      {In case the filter is not reconized}
      CallError(PNG_ERROR_INVALID_FILTER_TYPE);
  end; {Case}

end;

{:When the chunk is going to be saved to a stream}
procedure TChunkIDAT.SaveToStream(Stream: TStream);
begin
  {Set to encode the image to the data}
  EncodeImage;
  {Then write}
  inherited;
end;

{Assign data from one gama chunk}
procedure TChunkGAMA.Assign(Source: TChunk);
begin
  inherited; // fix 1
  GammaTable := TChunkGAMA(Source).GammaTable;
  InverseTable := TChunkGAMA(Source).InverseTable;
end;

{When the object is being created}
constructor TChunkGAMA.Create(AOwner: TChunkList);
begin
  inherited;
  {Set the size of the stream and initial value}
  fStream.SetSize(4);
  Value := 1;
end;

{:Creates a gamma table for using}
procedure TChunkGAMA.DoAction;
var
  I    : Integer;
begin
  {Create gamma table and inverse gamma table (for saving)}
  FOR I := 0 TO 255 DO
  begin
    GammaTable[I] := Round(Power((I / 255), 1 / (Value / 100000 * 2.2)) * 255);
    InverseTable[Round(Power((I / 255), 1 / (Value / 100000 * 2.2)) * 255)] := I;
  end;
end;


{Returns the Gama value}
function TChunkGAMA.GetValue: Cardinal;
begin
  Result := SwapLong(pCardinal(fStream.Memory)^);
end;

{Sets the Gama value}
procedure TChunkGAMA.SetValue(Value: Cardinal);
begin
  pCardinal(fStream.Memory)^ := SwapLong(Value);
end;

{:When the chunk is being saved}
procedure TChunkIHDR.SaveToStream(Stream: TStream);
begin
  {Set the IHDR chunk properties}
    Compression := 0; {The only compression method avaliable}
    Filter := 0;      {The only filter scheme avaliable}

    if Owner.Owner.Interlacing then  {Interlace method}
      Interlaced := 1           {ADAM 7}
    else
      Interlaced := 0;          {NONE}

    Width := Owner.Owner.Width;
    Height := Owner.Owner.Height;

    {Color type}
    case Owner.Owner.PixelFormat of
      pf1bit, pf4bit, pf8bit:
      begin
        {Palette}
        ColorType := PALETTE;
        {Bit depth}
        case Owner.Owner.PixelFormat of
          pf1bit: BitDepth := 1;
          pf4bit: BitDepth := 4;
          pf8bit: BitDepth := 8;
        end;

      end;
      else
      begin
        {R, G, B}
        Owner.Owner.PixelFormat := pf24bit;
        ColorType := RGB;
        BitDepth := 8;
      end;
    end;

  inherited;
end;

{Get values for the other properties}
function TChunkIHDR.GetValue(Index: Integer): Byte;
begin
  case Index of
    0: {Bit depth}   Result := pIHDRChunk(fStream.Memory)^.BitDepth;
    1: {Color type}  Result := pIHDRChunk(fStream.Memory)^.ColorType;
    2: {Compression} Result := pIHDRChunk(fStream.Memory)^.Compression;
    3: {Filter}      Result := pIHDRChunk(fStream.Memory)^.Filter;
    4: {Interlaced}  Result := pIHDRChunk(fStream.Memory)^.Interlaced;
    else {Avoid warning}
      Result := 0;
  end;

end;

{Set value for the other properties}
procedure TChunkIHDR.SetValue(Index: Integer; Value: Byte);
begin
  case Index of
    0: {Bit depth}   pIHDRChunk(fStream.Memory)^.BitDepth := Value;
    1: {Color type}  pIHDRChunk(fStream.Memory)^.ColorType := Value;
    2: {Compression} pIHDRChunk(fStream.Memory)^.Compression := Value;
    3: {Filter}      pIHDRChunk(fStream.Memory)^.Filter := Value;
    4: {Interlaced}  pIHDRChunk(fStream.Memory)^.Interlaced := Value;
  end;
end;

{Returns the image height}
function TChunkIHDR.GetHeight: Cardinal;
begin
  Result := SwapLong(pIHDRChunk(fStream.Memory)^.Height);
end;

{Returns the image width}
function TChunkIHDR.GetWidth: Cardinal;
begin
  Result := SwapLong(pIHDRChunk(fStream.Memory)^.Width);
end;

{Sets the image height}
procedure TChunkIHDR.SetHeight(Value: Cardinal);
begin
  pIHDRChunk(fStream.Memory)^.Height := SwapLong(Value);

  {Changes the image size}
  if Owner.Owner.Height <> Int(Value) then
    Owner.Owner.Height := Value;
end;

{Sets the image width}
procedure TChunkIHDR.SetWidth(Value: Cardinal);
begin
  pIHDRChunk(fStream.Memory)^.Width := SwapLong(Value);

  {Changes the image size}
  if Owner.Owner.Width <> Int(Value) then
    Owner.Owner.Width := Value;
end;

{:When the object is being created}
constructor TChunkIHDR.Create(AOwner: TChunkList);
begin
  inherited;
  {Resize the IHDR chunk}
  fStream.SetSize(13);
end;

{:Returns the index of the chunk class}
function TChunkClasses.IndexOfClass(Item: TChunkClass): Integer; { Paul }
var
  i: Integer;
begin
  {If none found, return -1}
  Result := -1;

  {Test each class}
  if Count > 0 then
    FOR i := 0 to Count - 1 DO
      if Self.Item[I].ChunkClass = Item then
      begin
        Result := i;
        break;
      end;
end;

{:Returns the index of the given chunk type}
function TChunkClasses.IndexOfType(Item: TChunkType): Integer; { Paul }
var
  i: Integer;
begin
  {If none found, return -1}
  Result := -1;

  {Test each class}
  if Count > 0 then
    FOR i := 0 to Count - 1 DO
      if Self.Item[I].ChunkType = Item then
      begin
        Result := i;
        break;
      end;
end;

{:When the object is being destroyed}
destructor TChunkClasses.Destroy;
var
  i: Integer;
begin
  {Free each registered chunk class}
  if Count > 0 then
  FOR i := 0 TO Count - 1 DO
    Dispose(pChunkClassInfo(fList[i]));

  {Free the list}
  if Assigned(fList) then fList.free;

  inherited;
end;

⌨️ 快捷键说明

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