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

📄 iepsd.pas

📁 ·ImageEn 2.3.0 ImageEn一组用于图像处理、查看和分析的Delphi控件。能够保存几种图像格式
💻 PAS
📖 第 1 页 / 共 4 页
字号:
        end;
        // bypass extradata (should not be present)
        Stream.Seek(ExtraDataSize, soFromCurrent);
        // fill TIELayer data
        layer:=TIELayer.Create(nil,nil,false);
        layers.Add(layer);
        layer.PosX:=LayersTemp[i].layerLeft;
        layer.PosY:=LayersTemp[i].layerTop;
        layer.Transparency:=LayersTemp[i].Opacity;
        layer.Name:=LayersTemp[i].Name;
        layer.Visible:=(LayersTemp[i].Flags and $2)=0;
        layer.Cropped:=(LayersTemp[i].Clipping=0);
      end;

      k:=0; // index inside layers[] list
      for i:=0 to layerscount-1 do
      begin
        // load layer image
        for c:=0 to LayersTemp[i].numberChannels-1 do
        begin
          if LayersTemp[i].ChannelID[c]=-2 then
          begin
            // this is the layer mask
            layer:=TIELayer.Create(nil,nil,false);
            layers.Insert(k+1,layer);
            layer.PosX:=LayersTemp[i].layermask_Left;
            layer.PosY:=LayersTemp[i].layermask_Top;
            layer.IsMask:=true;
            layer.Visible:=false;
            width:=LayersTemp[i].layermask_Right-LayersTemp[i].layermask_Left;
            height:=LayersTemp[i].layermask_Bottom-LayersTemp[i].layermask_Top;
            compression:=GetSmallint(Stream);
            getmem(sizes,sizeof(word)*height);
            if compression=1 then
              Stream.Read(sizes^,sizeof(word)*height)
            else
              for j:=0 to height-1 do
                sizes[j]:=IESwapWord(IEBitmapRowLen(width, header.Depth, 8));
            cursize:=0;
            ReadImageData(Stream,layer.Bitmap,width,height,8,1,nil,0,compression,sizes,cursize,0);
            freemem(sizes);
          end
          else
          begin
            // this is a channel or alpha channel
            if TIELayer(layers[k]).IsMask then
              inc(k);
            layer:=TIELayer(layers[k]);
            width:=LayersTemp[i].layerRight-LayersTemp[i].layerLeft;
            height:=LayersTemp[i].layerBottom-LayersTemp[i].layerTop;
            compression:=GetSmallint(Stream);
            getmem(sizes,sizeof(word)*height);
            if compression=1 then
              Stream.Read(sizes^,sizeof(word)*height)
            else
              for j:=0 to height-1 do
                sizes[j]:=IESwapWord(IEBitmapRowLen(width, header.Depth, 8));
            cursize:=0;
            ReadImageData(Stream,layer.Bitmap,width,height,header.Depth,header.mode,colormap,transpindex,compression,sizes,cursize,LayersTemp[i].ChannelID[c]);
            freemem(sizes);
          end;
        end;
        inc(k);

        if assigned(XProgress.fOnProgress) then
          XProgress.fOnProgress(XProgress.Sender, trunc(i/layerscount*100));

      end;

      // free mem
      for i:=0 to layerscount-1 do
      begin
        freemem(LayersTemp[i].ChannelID);
        freemem(LayersTemp[i].ChannelLen);
        for j:=0 to LayersTemp[i].adjustmentCount-1 do
          freemem( LayersTemp[i].adjustment[j].data );
        freemem( LayersTemp[i].adjustment );
      end;
      freemem(LayersTemp);

      // go at global layer mask info
      Stream.Position:=lpos1+layersinfolen+4;
      globalmaskLength:=GetLongint(Stream);
      if globalmaskLength>0 then
      begin
        (*globalmaskOverlayColorSpace:=*)GetSmallint(Stream);
        for i:=0 to 3 do
          globalmaskColorComponents[i]:=GetSmallint(Stream);
        (*globalmaskOpacity:=*)GetSmallint(Stream);
        (*globalmaskKind:=*)GetByte(Stream);
        GetByte(Stream);  // by pass
      end;

      // go to at end of layer and mask info
      Stream.Position:=lpos1+layerslen;
    end;

    // remove zero size layers
    if layers<>nil then
    begin
      i:=0;
      while i<layers.Count do
        if (TIELayer(layers[i]).Bitmap.Width=0) or (TIELayer(layers[i]).Bitmap.Height=0) then
        begin
          TIELayer(layers[i]).Free;
          layers.Delete(i);
          if (i<layers.Count-1) and TIELayer(layers[i]).IsMask then
          begin
            // remove also the layer mask
            TIELayer(layers[i]).Free;
            layers.Delete(i);
          end;
        end
        else
          inc(i);
    end;
  end;
end;

// blocksize: the size of block to read from Stream
// outbuf: output uncompressed buffer
procedure ReadRow(Stream:TStream; compression:word; outbuf:pbyte; sizes:pwordarray; var cursize:integer);
var
  i:integer;
  rp:byte;
  tmprow:pbyte;
  src:pbytearray;
  dst:pbyte;
  blocksize:integer;
begin
  blocksize:=IESwapWord(sizes[cursize]);
  case compression of
    0:  // RAW data
      begin
        Stream.Read(outbuf^,blocksize);
      end;
    1:  // RLE
      begin
        getmem(tmprow,blocksize);
        Stream.Read(tmprow^,blocksize);
        src:=pbytearray(tmprow);
        dst:=outbuf;
        i:=0;
        while i<blocksize do
        begin
          if (src[i] and $80)<>0 then
          begin
            // repeater
            rp:=(not src[i])+2;
            inc(i);
            while rp>0 do
            begin
              dst^:=src[i];
              inc(dst);
              dec(rp);
            end;
            inc(i);
          end
          else
          begin
            // copy
            rp:=src[i]+1;
            inc(i);
            while rp>0 do
            begin
              dst^:=src[i];
              inc(dst);
              inc(i);
              dec(rp);
            end;
          end;
        end;
        freemem(tmprow);
      end;
  end;
  {
  according to Adobe specifiations row lengths should not be odd, but this seems contract with actual files
  if (blocksize and $1)<>0 then
    Stream.Seek(1,soFromCurrent);
  }
  inc(cursize);
end;

procedure CopyRow8(bitmap:TIEBitmap; row:integer; channel:integer; channelcount:integer; width:integer; inrow:pbyte);
var
  pb1,pb2:pbyte;
  i:integer;
begin
  pb1:=Bitmap.Scanline[row]; inc(pb1,channel);
  pb2:=inrow;
  for i:=0 to width-1 do
  begin
    pb1^:=pb2^;
    inc(pb1,channelcount);
    inc(pb2);
  end;
end;

procedure CopyRow16(bitmap:TIEBitmap; row:integer; channel:integer; channelcount:integer; width:integer; inrow:pbyte);
var
  pw1,pw2:pword;
  i:integer;
begin
  pw1:=Bitmap.Scanline[row]; inc(pw1,channel);
  pw2:=pword(inrow);
  for i:=0 to width-1 do
  begin
    pw1^:=IESwapWord(pw2^);
    inc(pw1,channelcount);
    inc(pw2);
  end;
end;

procedure CopyRow16to8(bitmap:TIEBitmap; row:integer; channel:integer; channelcount:integer; width:integer; inrow:pbyte);
var
  pb1:pbyte;
  pw2:pword;
  i:integer;
begin
  pb1:=Bitmap.Scanline[row]; inc(pb1,channel);
  pw2:=pword(inrow);
  for i:=0 to width-1 do
  begin
    pb1^:=pw2^ and $FF; // it is the same of "pb1^:=IESwapWord(pw2^) shr 8"
    inc(pb1,channelcount);
    inc(pw2);
  end;
end;

procedure AdjustLab8(bitmap:TIEBitmap; row:integer; channel:integer; channelcount:integer; width:integer);
type
  pshortint=^shortint;
var
  p:pshortint;
  i:integer;
begin
  p:=Bitmap.Scanline[row]; inc(p,channel);
  for i:=0 to width-1 do
  begin
    p^:=pbyte(p)^-128;
    inc(p,channelcount);
  end;
end;

procedure AdjustPaletteTransp(Bitmap:TIEBitmap; row:integer; transpindex:integer; width:integer);
var
  i:integer;
  p,a:pbyte;
begin
  if transpindex>-1 then
  begin
    p:=Bitmap.Scanline[row];
    a:=Bitmap.AlphaChannel.Scanline[row];
    for i:=0 to width-1 do
    begin
      if p^=transpindex then
        a^:=0
      else
        a^:=255;
      inc(p);
      inc(a);
    end;
  end;
end;

procedure LoadAlpha(Stream:TStream; AlphaBitmap:TIEBitmap;width,height,depth:integer; compression:integer; sizes:pwordarray; var cursize:integer; rowbuf:pbyte);
var
  i:integer;
begin
  for i:=0 to height-1 do
  begin
    ReadRow(Stream,compression,rowbuf,sizes,cursize);
    case depth of
      8:  CopyRow8(AlphaBitmap,i,0,1,width,rowbuf);
      16: CopyRow16to8(AlphaBitmap,i,0,1,width,rowbuf);
    end;
  end;
end;


// read image data section
procedure ReadImageData(Stream:TStream; Bitmap:TIEBitmap; width,height,depth,mode:integer; colormap:PColorMap; transpindex:integer; compression:smallint; sizes:pwordarray; var cursize:integer; channel:integer);
var
  rowbuf:pbyte;
  i:integer;
begin

  getmem(rowbuf, IEBitmapRowLen(width, depth, 8));

  case depth of

    1:  // depth=1
      case mode of
        0:  // bitmap
          begin
            Bitmap.Allocate(width,height,ie1g);
            if channel=0 then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow8(Bitmap,i,0,1,width div 8,rowbuf);
                _NegativeBuffer(Bitmap.Scanline[i], width div 8);
              end;
          end;
      end;

    8:  // depth=8
      case mode of
        1,8:  // Gray Scale or duotone
          begin
            Bitmap.Allocate(width,height,ie8g);
            if channel=0 then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow8(Bitmap,i,0,1,width,rowbuf);
              end;
            if (channel=1) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
        2:  // Indexed
          begin
            Bitmap.Allocate(width,height,ie8p);
            if channel=0 then
            begin
              for i:=0 to 255 do
                Bitmap.Palette[i]:=CreateRGB(colormap^[0][i],colormap^[1][i],colormap^[2][i]);
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow8(Bitmap,i,0,1,width,rowbuf);
                AdjustPaletteTransp(Bitmap,i,transpindex,width);
              end;
            end;
          end;
        3:  // RGB
          begin
            Bitmap.Allocate(width,height,ie24RGB);
            if (channel>=0) and (channel<3) then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow8(Bitmap,i,2-channel,3,width,rowbuf);
              end;
            if (channel=3) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
        4:  // CMYK
          begin
            Bitmap.Allocate(width,height,ieCMYK);
            if (channel>=0) and (channel<4) then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow8(Bitmap,i,channel,4,width,rowbuf);
              end;
            if (channel=4) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
        9:  // Lab
          begin
            Bitmap.Allocate(width,height,ieCIELab);
            if (channel>=0) and (channel<3) then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow8(Bitmap,i,channel,3,width,rowbuf);
                if (channel=1) or (channel=2) then
                  AdjustLab8(Bitmap,i,channel,3,width);
              end;
            if (channel=3) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
      end;

    16: // depth=16
      case mode of
        1,8:  // Gray Scale or duotone
          begin
            Bitmap.Allocate(width,height,ie16g);
            if channel=0 then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow16(Bitmap,i,0,1,width,rowbuf);
              end;
            if (channel=1) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
        3:  // RGB
          begin
            Bitmap.Allocate(width,height,ie48RGB);
            if (channel>=0) and (channel<3) then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow16(Bitmap,i,channel,3,width,rowbuf);
              end;
            if (channel=3) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
        4:  // CMYK
          begin
            Bitmap.Allocate(width,height,ieCMYK);
            if (channel>=0) and (channel<4) then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow16to8(Bitmap,i,channel,4,width,rowbuf);
              end;
            if (channel=4) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
        9:  // Lab
          begin
            Bitmap.Allocate(width,height,ieCIELab);
            if (channel>=0) and (channel<3) then
              for i:=0 to height-1 do
              begin
                ReadRow(Stream,compression,rowbuf,sizes,cursize);
                CopyRow16to8(Bitmap,i,channel,3,width,rowbuf);
                if (channel=1) or (channel=2) then
                  AdjustLab8(Bitmap,i,channel,3,width);
              end;
            if (channel=3) or (channel=-1) then
              LoadAlpha(Stream,Bitmap.AlphaChannel,width,height,depth,compression,sizes,cursize,rowbuf);
          end;
      end;
  end;

  freemem(rowbuf);
end;

// output is a list of TIELayer (output must be a created list)
// note: to do "Preview" set boths LoadLayers and LoadMergedImage to False
procedure IEReadPSD(Stream:TStream; MergedBitmap:TIEBitmap; var IOParams: TIOParamsVals; var Progress: TProgressRec; LoadLayers: boolean; layers:TList);
var
  context:TPSDReaderContext;
  compression:smallint;
  cursize:integer;
  sizes:pwordarray;
  i:integer;
begin

⌨️ 快捷键说明

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