delphi 逐个读取psd图层(100)

  • 主题发起人 主题发起人 zhtiger126
  • 开始时间 开始时间
Z

zhtiger126

Unregistered / Unconfirmed
GUEST, unregistred user!
我想用delphi,将psd图层一个个地读出来,要保留透明通道...请前辈慷慨帮助,万分感谢!
 
wangdonghai...我在这里启了一个新标题,我知道你能写出来,,,帮个忙啊!!!
 
图层已经可以读出来,但是效果还是跟Photoshop的显示效果有差距程序先将PSD文件里的图层读入Combobox,然后根据选择的图层进行显示部分代码参考自http://blog.csdn.net/Xeden/archive/2005/09/25/489274.aspxunit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls;type TForm1 = class(TForm) Panel1: TPanel; btnRead: TButton; cb1: TComboBox; btnView: TButton; procedure btnReadClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure btnViewClick(Sender: TObject); procedure FormDestroy(Sender: TObject); private FLayerList:TStringList; procedure ClearLayList; public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm}type TPSDFileHeader=record Signature:array[0..3] of char; Version:Word; Reserved:array[0..5] of Byte; Channels:Word; Height:Integer; Width:Integer; BitsPerPixel:Word; ColorMode:Word;end;type PChannelNode=^TChannelNode; TChannelNode=record ID:Integer; Length:Integer; end; PLayerNode=^TLayerNode; TLayerNode=record Height:Integer; Width:Integer; Data:PByte; ChannelCount:Word; ChannelNode:array of TChannelNode;end;function Calc(c:array of Byte;nDigits:integer):integer;var n,nValue:integer;begin nValue:=0; for n:=0 to nDigits-1 do nValue:=nValue shl 8 or c[n]; result:=nValue;end;procedure TForm1.btnReadClick(Sender: TObject);var fs:TFileStream; PSDFH:TPSDFileHeader; TmpBuf:array[0..5] of Byte; i,j,k,m,iLen,iLSC,iCID,iCLen:Integer; p,pData:PByte; nPos,nBPos:Integer; RowSize:array of Word; LayerNode,pLN:PLayerNode;begin fs:=TFileStream.Create('2.psd',fmOpenRead); try //Read File Header fs.ReadBuffer(PSDFH.Signature,sizeof(PSDFH.Signature)); fs.ReadBuffer(TmpBuf,2); PSDFH.Version:=Calc(TmpBuf,2); fs.ReadBuffer(PSDFH.Reserved,sizeof(PSDFH.Reserved)); fs.ReadBuffer(TmpBuf,2); PSDFH.Channels:=Calc(TmpBuf,2); fs.ReadBuffer(TmpBuf,4); PSDFH.Height:=Calc(TmpBuf,4); fs.ReadBuffer(TmpBuf,4); PSDFH.Width:=Calc(TmpBuf,4); fs.ReadBuffer(TmpBuf,2); PSDFH.BitsPerPixel:=Calc(TmpBuf,2); fs.ReadBuffer(TmpBuf,2); PSDFH.ColorMode:=Calc(TmpBuf,2); //Read Color fs.ReadBuffer(TmpBuf,4); iLen:=Calc(TmpBuf,4); fs.Seek(iLen,soFromCurrent); //Read Image Source fs.ReadBuffer(TmpBuf,4); iLen:=Calc(TmpBuf,4); fs.Seek(iLen,soFromCurrent); //Read Layer fs.ReadBuffer(TmpBuf,4); //iLen:=Calc(TmpBuf,4); //Read Layer Info Section fs.ReadBuffer(TmpBuf,4); //iLen:=Calc(TmpBuf,4);//Layer Info Section Length //Read Layer Structures fs.ReadBuffer(TmpBuf,2); iLSC:=Calc(TmpBuf,2); //Layer Structures Count if iLSC=0 then exit; ClearLayList; for i:=0 to iLSC-1 do begin New(LayerNode); fs.ReadBuffer(TmpBuf,4); LayerNode^.Height:=Calc(TmpBuf,4); //Layer Top fs.ReadBuffer(TmpBuf,4); LayerNode^.Width:=Calc(TmpBuf,4); //Layer Left fs.ReadBuffer(TmpBuf,4); iLen:=Calc(TmpBuf,4); //Layer Bottom LayerNode^.Height:=iLen-LayerNode^.Height; fs.ReadBuffer(TmpBuf,4); iLen:=Calc(TmpBuf,4); //Layer Right LayerNode^.Width:=iLen-LayerNode^.Width; fs.ReadBuffer(TmpBuf,2); LayerNode^.ChannelCount:=Calc(TmpBuf,2); //Layer Channel Count; GetMem(LayerNode^.Data,LayerNode^.Width*LayerNode^.Height*LayerNode^.ChannelCount); SetLength(LayerNode^.ChannelNode,LayerNode^.ChannelCount); for j:=0 to LayerNode^.ChannelCount-1 do //Channel Length Info begin fs.ReadBuffer(TmpBuf,2); iCID:=Calc(TmpBuf,2); if iCID=Word(-1) then iCID:=3; LayerNode^.ChannelNode[j].ID:=iCID; fs.ReadBuffer(TmpBuf,4); iCLen:=Calc(TmpBuf,4); LayerNode^.ChannelNode[j].Length:=iCLen; end; fs.ReadBuffer(TmpBuf,4); fs.ReadBuffer(TmpBuf,4); fs.ReadBuffer(TmpBuf,4); fs.ReadBuffer(TmpBuf,4); iLen:=Calc(TmpBuf,4); fs.Seek(iLen,1); FLayerList.AddObject('Layer'+IntToStr(i+1),TObject(LayerNode)); end; //Channel Image Data cb1.Items.Clear; for i:=0 to FLayerList.Count-1 do begin cb1.Items.Add(FLayerList.Strings); pLN:=PLayerNode(FLayerList.Objects); for j:=0 to pLN.ChannelCount-1 do begin iCID:=pLN^.ChannelNode[j].ID; iCLen:=pLN^.ChannelNode[j].Length-2; fs.ReadBuffer(TmpBuf,2); iLen:=Calc(Tmpbuf,2); if iLen=1 then begin p:=PByte(Integer(pLN.Data)+iCID); GetMem(pData,iCLen); fs.ReadBuffer(pData^,iCLen); SetLength(RowSize,pLN.Height*sizeof(Word)); nPos:=0; for k:=0 to pLN.Height-1 do begin RowSize[k]:=PByte(Integer(pData)+nPos+0)^*256+ PByte(Integer(pData)+nPos+1)^; inc(nPos,2); end; for k:=0 to pLN.Height-1 do begin nBPos:=nPos; while nPos<nBPos+RowSize[k] do begin iLen:=PByte(Integer(pData)+nPos)^; inc(nPos); if iLen<128 then begin inc(iLen); for m:=0 to iLen-1 do begin p^:=PByte(Integer(pData)+nPos)^; inc(p,pLN.ChannelCount); inc(nPos); end; end else if iLen>128 then begin iLen:=255-iLen+2; for m:=0 to iLen-1 do begin p^:=PByte(Integer(pData)+nPos)^; inc(p,pLN.ChannelCount); end; inc(nPos); end; end; end; SetLength(RowSize,0); FreeMem(pData); end; end; end; finally FS.Free; end;end;procedure TForm1.FormCreate(Sender: TObject);begin FLayerList:=TStringList.Create;end;procedure TForm1.btnViewClick(Sender: TObject);var hMemDC:HDC; BmpInfo:BITMAPINFO; pp:Pointer; hBmp:HBitmap; pLN:PLayerNode; i,j:integer; p:PByte;begin if cb1.ItemIndex=-1 then exit; pLN:=PLayerNode(FLayerList.Objects[cb1.ItemIndex]); BmpInfo.bmiHeader.biSize:=sizeof(BITMAPINFOHEADER); BmpInfo.bmiHeader.biWidth:=pLN.Width; BmpInfo.bmiHeader.biHeight:=-pLN.Height; BmpInfo.bmiHeader.biPlanes:=1; BmpInfo.bmiHeader.biBitCount:=pLN.ChannelCount*8; BmpInfo.bmiHeader.biCompression:=BI_RGB; BmpInfo.bmiHeader.biSizeImage:=0; BmpInfo.bmiHeader.biXPelsPerMeter:=0; BmpInfo.bmiHeader.biYPelsPerMeter:=0; BmpInfo.bmiHeader.biClrImportant:=0; BmpInfo.bmiHeader.biClrUsed:=0; hBmp:=CreateDIBSection(GetDC(0),BmpInfo, DIB_RGB_COLORS,pp,0,0); hMemDC:=CreateCompatibleDC(0); SelectObject(hMemDC,hBmp); i:=0; j:=0; p:=pLN.Data; while i<pLN.Width*pLN.Height*pLN.ChannelCount-1 do begin PByte(Integer(pp)+i+0)^:=PByte(Integer(p)+j+2)^; PByte(Integer(pp)+i+1)^:=PByte(Integer(p)+j+1)^; PByte(Integer(pp)+i+2)^:=PByte(Integer(p)+j+0)^; if pLN.ChannelCount>3 then begin PByte(Integer(pp)+i+3)^:=PByte(Integer(p)+j+3)^; end; inc(i,pLN.ChannelCount); inc(j,pLN.ChannelCount); end; BitBlt(GetDC(Handle),0,0,pLN.Width,pLN.Height, hMemDC,0,0,SRCCOPY); DeleteDC(hMemDC);end;procedure TForm1.ClearLayList;var p:Pointer;begin while FLayerList.Count>0 do begin p:=FLayerList.Objects[0]; SetLength(pLayerNode(p)^.ChannelNode,0); Dispose(pLayerNode(p)^.Data); Dispose(p); FLayerList.Delete(0); end; FLayerList.Clear;end;procedure TForm1.FormDestroy(Sender: TObject);begin ClearLayList; FLayerList.Free;end;end.
 
wangdonghai~ 你好厉害哦!!!我想要把每层图片按原来的对应位置放好,并保持透明色...帮人帮到底了,老大!!解决了这两个问题就结束,,,真的很感谢你,让我学到了很多东西!!!
 
wangdonghai...分给你,你确实给我很大帮助再次感谢你!!如果有时间,指点希望多指点....
 
wangdonghai...大哥....if iLen=1 的情况对了,那if iLen=0的情况呢...有的图层是没有压缩的上面代码就读不出来,一片黑.呵呵...帮忙写出来啊!!!
 
// 1 压缩情况 if iLen=1 then begin p:=PByte(Integer(pLN.Data)+iCID); GetMem(pData,iCLen); fs.ReadBuffer(pData^,iCLen); SetLength(RowSize,pLN.Height*sizeof(Word)); nPos:=0; for k:=0 to pLN.Height-1 do begin RowSize[k]:=PByte(Integer(pData)+nPos+0)^*256+ PByte(Integer(pData)+nPos+1)^; inc(nPos,2); end; for k:=0 to pLN.Height-1 do begin nBPos:=nPos; while nPos<nBPos+RowSize[k] do begin iLen:=PByte(Integer(pData)+nPos)^; inc(nPos); if iLen<128 then begin inc(iLen); for m:=0 to iLen-1 do begin p^:=PByte(Integer(pData)+nPos)^; inc(p,pLN.ChannelCount); inc(nPos); end; end else if iLen>128 then begin iLen:=255-iLen+2; for m:=0 to iLen-1 do begin p^:=PByte(Integer(pData)+nPos)^; inc(p,pLN.ChannelCount); end; inc(nPos); end; end; end; SetLength(RowSize,0); FreeMem(pData); end; // 2 非压缩情况 if iLen=0 then begin showmessage('非压缩情况!'); end;
 
我没有这样的psd文件,不好写,要有这样的psd文件才可以调试
 

Similar threads

D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
875
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部