public void ReadPixels(BinaryPSDReader reader) { int numChannelsToRead = this._channels.Count; if (this._channels.ContainsKey(-2)) { numChannelsToRead--; } PixelData px = new PixelData(this.Width, this.Height, this.BitsPerPixel, numChannelsToRead, this._isMerged); px.Read(reader); int i = 0; foreach (Channel ch in this._channels.Values) { if (ch.Usage != -2) { ch.Data = px.GetChannelData(i++); } //ch.ReadPixels(reader); } if (this._mask != null) { px = new PixelData(this.Width, this.Height, this.BitsPerPixel, 1, false); px.Read(reader); this._mask.Data = px.GetChannelData(0); //this._mask.ReadPixels(reader); } }
public Mask(BinaryPSDReader reader, Layer layer) : base(layer) { this._layer = layer; int nLength = (int)reader.ReadUInt32(); if (nLength == 0) return; long nStart = reader.BaseStream.Position; this.Rectangle = reader.ReadPSDRectangle(); //new Rectangle(reader).ToERectangle(); this._color = reader.ReadByte(); this._flags = reader.ReadByte(); if (nLength == 20) reader.ReadUInt16(); //padding else if (nLength == 36) { this._flags2 = reader.ReadByte();//same flags as above according to docs!?!? this._maskBg = reader.ReadByte(); //Real user mask background. Only 0 or 255 - ie bool?!? this._otherRectangle = reader.ReadPSDRectangle(); //new Rectangle(reader).ToERectangle(); //same as above rectangle according to docs?!?! } reader.BaseStream.Position = nStart + nLength; }
public Mask(BinaryPSDReader reader, Layer layer) : base(layer) { this._layer = layer; int nLength = (int)reader.ReadUInt32(); if (nLength == 0) { return; } long nStart = reader.BaseStream.Position; this.Rectangle = reader.ReadPSDRectangle(); //new Rectangle(reader).ToERectangle(); this._color = reader.ReadByte(); this._flags = reader.ReadByte(); if (nLength == 20) { reader.ReadUInt16(); //padding } else if (nLength == 36) { this._flags2 = reader.ReadByte(); //same flags as above according to docs!?!? this._maskBg = reader.ReadByte(); //Real user mask background. Only 0 or 255 - ie bool?!? this._otherRectangle = reader.ReadPSDRectangle(); //new Rectangle(reader).ToERectangle(); //same as above rectangle according to docs?!?! } reader.BaseStream.Position = nStart + nLength; }
public Channel(BinaryPSDReader reader, Layer layer) { this._usage = reader.ReadInt16(); long length = (long)reader.ReadUInt32(); this._layer = layer; }
public ImageResource(BinaryPSDReader reader) { this.ID = reader.ReadUInt16(); this.Name = reader.ReadPascalString(); uint settingLength = reader.ReadUInt32(); this.Data = reader.ReadBytes((int)settingLength); if (reader.BaseStream.Position % 2 == 1) reader.ReadByte(); }
public static string ReadSpecialString(BinaryPSDReader r) { uint length = r.ReadUInt32(); if (length == 0) { length = 4; } return(new string(r.ReadPSDChars((int)length))); }
public DynVal(BinaryPSDReader r, bool asDescriptor) { if (asDescriptor) { uint version = r.ReadUInt32(); string unknown = Endogine.Serialization.ReadableBinary.CreateHexEditorString(r.ReadBytes(6)); } this.ObjectType = GetMeaningOfFourCC(ReadSpecialString(r)); this.Children = DynVal.ReadValues(r); }
//public LayerResource(LayerResource res) //{ // Prepare(); // this.Tag = res.Tag; //} public LayerResource(BinaryPSDReader reader) { //this.Tag = new string(reader.ReadPSDChars(4)); uint settingLength = reader.ReadUInt32(); this.Data = reader.ReadBytes((int)settingLength); if (!(this is EffectBase)) { reader.JumpToEvenNthByte(2); } }
public Header(BinaryPSDReader reader) { this.Version = reader.ReadUInt16(); if (Version != 1) throw new Exception("Can not read .psd version " + Version); byte[] buf = new byte[256]; reader.Read(buf, (int)reader.BaseStream.Position, 6); //6 bytes reserved this.Channels = reader.ReadInt16(); this.Rows = reader.ReadUInt32(); this.Columns = reader.ReadUInt32(); this.BitsPerPixel = reader.ReadUInt16(); this.ColorMode = (ColorModes)reader.ReadInt16(); }
public byte[] PreReadPixels(BinaryPSDReader reader, Compression compression) { switch (compression) { case Compression.Rle: //ignore rle "header" with bytes per row... reader.BaseStream.Position += this._height * 2; //ushort[] rowLenghtList = new ushort[height]; //for (int i = 0; i < height; i++) // rowLenghtList[i] = reader.ReadUInt16(); break; } return(null); }
public Header(BinaryPSDReader reader) { this.Version = reader.ReadUInt16(); if (Version != 1) { throw new Exception("Can not read .psd version " + Version); } byte[] buf = new byte[256]; reader.Read(buf, (int)reader.BaseStream.Position, 6); //6 bytes reserved this.Channels = reader.ReadInt16(); this.Rows = reader.ReadUInt32(); this.Columns = reader.ReadUInt32(); this.BitsPerPixel = reader.ReadUInt16(); this.ColorMode = (ColorModes)reader.ReadInt16(); }
public static List <DynVal> ReadValues(BinaryPSDReader r) { int numValues = (int)r.ReadUInt32(); List <DynVal> values = new List <DynVal>(); for (int i = 0; i < numValues; i++) { DynVal vt = ReadValue(r, false); if (vt != null) { values.Add(vt); } } return(values); }
public static Dictionary <string, LayerResource> ReadLayerResources(BinaryPSDReader reader, Type inheritsType) { Prepare(); Dictionary <string, LayerResource> result = new Dictionary <string, LayerResource>(); while (true) { LayerResource res = ReadLayerResource(reader, inheritsType); if (res == null) { break; } result.Add(res.Tag, res); } return(result); }
public byte[] ReadPixels(BinaryPSDReader reader, Compression compression) { int bytesPerPixelPerChannel = this._bitsPerPixel / 8; // psd.Header.Depth / 8; if (bytesPerPixelPerChannel < 1) { bytesPerPixelPerChannel = 1; } int bytesPerRow = this._width * bytesPerPixelPerChannel; int totalBytes = bytesPerRow * this._height; byte[] pData = new byte[totalBytes]; switch (compression) { case Compression.None: reader.Read(pData, 0, totalBytes); break; case Compression.Rle: for (int i = 0; i < this._height; i++) { int offset = i * this._width; int numDecodedBytes = 0; int numChunks = 0; while (numDecodedBytes < this._width) { numDecodedBytes += Endogine.Serialization.RleCodec.DecodeChunk(reader.BaseStream, pData, offset + numDecodedBytes); numChunks++; } } break; case Compression.ZipNoPrediction: throw (new Exception("ZIP without prediction, no specification")); case Compression.ZipPrediction: throw (new Exception("ZIP with prediction, no specification")); default: throw (new Exception("Compression not defined: " + compression)); } return(pData); }
public static LayerResource ReadLayerResource(BinaryPSDReader reader, Type inheritsType) { long posBefore = reader.BaseStream.Position; string sHeader = new string(reader.ReadPSDChars(4)); if (sHeader != "8BIM") { reader.BaseStream.Position = posBefore; //back it up return(null); } string tag = new string(reader.ReadPSDChars(4)); Type type = null; bool usingDefault = false; if (!ResourceTypes.ContainsKey(tag)) { if (inheritsType == null) { inheritsType = typeof(LayerResource); } //throw new Exception("LayerResource tag unknown: " + tag); type = inheritsType; usingDefault = true; //LayerResource temp = new LayerResource(reader); //temp.Tag = tag; //return temp; } else { type = ResourceTypes[tag]; } System.Reflection.ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(BinaryPSDReader) }); LayerResource res = (LayerResource)ci.Invoke(new object[] { reader }); res.Tag = tag; return(res); }
public void Read(BinaryPSDReader reader) { Compression compression = Compression.None; if (this._isMerged) { compression = (Compression)reader.ReadUInt16(); for (int i = 0; i < this._numChannels; i++) { this.PreReadPixels(reader, compression); } } for (int i = 0; i < this._numChannels; i++) { if (!this._isMerged) { compression = (Compression)reader.ReadUInt16(); this.PreReadPixels(reader, compression); } this._channelData.Add(this.ReadPixels(reader, compression)); } }
public static List <ImageResource> ReadImageResources(BinaryPSDReader reader) { List <ImageResource> result = new List <ImageResource>(); while (true) { long nBefore = reader.BaseStream.Position; string settingSignature = new string(reader.ReadPSDChars(4)); if (settingSignature != "8BIM") { reader.BaseStream.Position = nBefore; //reader.BaseStream.Position-=4; break; } ImageResource imgRes = new ImageResource(reader); ResourceIDs resID = (ResourceIDs)imgRes.ID; if (!Enum.IsDefined(typeof(ResourceIDs), (int)imgRes.ID)) { if (imgRes.ID > 2000 && imgRes.ID <= 2999) { //Stupid Adobe engineers... This is SO not using the same pattern as everything else!!! resID = ResourceIDs.PathInfo; } } if (ResourceTypes.ContainsKey(resID)) { Type type = ResourceTypes[resID]; System.Reflection.ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(ImageResource) }); imgRes = (ImageResource)ci.Invoke(new object[] { imgRes }); } //if (resID != ResourceIDs.Undefined) result.Add(imgRes); } return(result); }
public static DynVal ReadValue(BinaryPSDReader r, bool ignoreName) { DynVal vt = new DynVal(); if (!ignoreName) { vt.Name = GetMeaningOfFourCC(ReadSpecialString(r)); // r.ReadPascalString(); } //else //TODO: should be assigned a sequential number? string type = new string(r.ReadPSDChars(4)); switch (type) { case "tdta": vt.Value = Endogine.Serialization.ReadableBinary.CreateHexEditorString(r.ReadBytes(9)); vt.Children = new List <DynVal>(); while (true) { DynVal child = new DynVal(); vt.Children.Add(child); if (child.ReadTdtaItem(r) == false) { break; } } //r.BaseStream.Position += 9; break; case "Objc": //Decriptor case "GlbO": //GlobalObject (same) string uniName = r.ReadPSDUnicodeString(); //uint numSub = r.ReadUInt32(); //if (numSub > 1) //{ // //A unicode text here!? What does this have to do with numSub?? // r.BaseStream.Position -= 4; // r.ReadPSDUnicodeString(); // r.BaseStream.Position -= 2; //Ehh... What?! //} ////TODO: ah: 1 = 1 short = unknown... //ushort unknown = r.ReadUInt16(); //vt.Children = ReadValues(r); vt = new DynVal(r, false); if (uniName.Length > 0) { vt.UnicodeName = uniName; } break; case "VlLs": //List vt.Children = new List <DynVal>(); int numValues = (int)r.ReadUInt32(); for (int i = 0; i < numValues; i++) { DynVal ob = ReadValue(r, true); if (ob != null) { vt.Children.Add(ob); } } break; case "doub": vt.Value = r.ReadPSDDouble(); break; case "UntF": //Unif float //TODO: need a specific type for this, with a double and a type (percent/pixel)? string tst = GetMeaningOfFourCC(new string(r.ReadPSDChars(4))); //#Prc #Pxl #Ang = percent / pixels / angle? double d = r.ReadPSDDouble(); tst += ": " + d; vt.Value = tst; break; case "enum": string namesp = ReadSpecialString(r); string item = ReadSpecialString(r); //vt.Value = namesp + "." + item; //TODO: cast to real enum vt.Value = GetMeaningOfFourCC(namesp) + "." + GetMeaningOfFourCC(item); break; case "long": vt.Value = r.ReadInt32(); //64? break; case "bool": vt.Value = r.ReadBoolean(); break; //case "obj ": //reference // break; case "TEXT": vt.Value = r.ReadPSDUnicodeString(); break; //case "Enmr": //Enumerated // break; //case "Clss": //Class // break; //case "GlbC": //GlobalClass // break; //case "alis": //Alias // break; default: throw new Exception("Unknown type: " + type); } if (vt.Value == null && vt.Children == null) { return(null); } return(vt); }
public bool ReadTdtaItem(BinaryPSDReader r) { this.Name = ""; while (r.BytesToEnd > 0) { char c = r.ReadChar(); if (c == 0x0a) { break; } this.Name += c; } byte[] buffer = new byte[255]; int bufPos = 0; int nearEndCnt = 0; //Read until a slash or several 0x00 comes along while (r.BytesToEnd > 0) { byte b = r.ReadByte(); buffer[bufPos++] = b; if (b == 0x2f) // slash "/" seems to be the field delimiter { break; } if (b <= 0x00) { nearEndCnt++; if (nearEndCnt == 12) { break; } } else { nearEndCnt = 0; } } if (this.Name.Contains(" ")) { int index = this.Name.IndexOf(" "); string val = this.Name.Substring(index + 1); //Sometimes it's a unicode string (how do I know..? seems to always have parenthesis) Ugly shortcut: if (val[0] == '(' && val[val.Length - 1] == ')') { bool unicode = true; for (int i = 0; i < val.Length; i++) { if (val[i] != 0 && val[i] <= 31) { unicode = false; break; } } if (unicode) { string uniVal = ""; for (int i = 2; i < val.Length; i += 2) { uniVal += val[i]; } val = uniVal; } else { byte[] tmp = new byte[val.Length]; int i = 0; foreach (char ch in val) { tmp[i++] = (byte)ch; } val = Endogine.Serialization.ReadableBinary.CreateHexEditorString(tmp).Replace("\r\n", " "); } } this.Value = val; this.Name = this.Name.Remove(index); } int endPos = bufPos - nearEndCnt - 1; //See if it's only 0x09's: for (int i = 0; i < endPos; i++) { if (buffer[i] != 0x09) { //TODO: this.Data = Endogine.Serialization.ReadableBinary.CreateHexEditorString(buffer, 0, endPos); break; } } return(nearEndCnt == 0 && r.BytesToEnd > 0); //OK to continue reading values? }
public void Read(BinaryPSDReader reader) { Compression compression = Compression.None; if (this._isMerged) { compression = (Compression)reader.ReadUInt16(); for (int i = 0; i < this._numChannels; i++) this.PreReadPixels(reader, compression); } for (int i = 0; i < this._numChannels; i++) { if (!this._isMerged) { compression = (Compression)reader.ReadUInt16(); this.PreReadPixels(reader, compression); } this._channelData.Add(this.ReadPixels(reader, compression)); } }
public string ReadBlendKey(BinaryPSDReader r) { string blendModeSignature = new string(r.ReadPSDChars(4)); return(new string(r.ReadPSDChars(4))); }
public static List<DynVal> ReadValues(BinaryPSDReader r) { int numValues = (int)r.ReadUInt32(); List<DynVal> values = new List<DynVal>(); for (int i = 0; i < numValues; i++) { DynVal vt = ReadValue(r, false); if (vt != null) values.Add(vt); } return values; }
public static string ReadSpecialString(BinaryPSDReader r) { uint length = r.ReadUInt32(); if (length == 0) length = 4; return new string(r.ReadPSDChars((int)length)); }
//public void AddChannel(Channel ch) //{ // this._channels.Add(ch.Usage, ch); //} public Layer(BinaryPSDReader reader, Document document) { this._document = document; this._rect = reader.ReadPSDRectangle(); ushort numChannels = reader.ReadUInt16(); this._channels = new Dictionary <int, Channel>(); for (int channelNum = 0; channelNum < numChannels; channelNum++) { Channel ch = new Channel(reader, this); if (this._channels.ContainsKey(ch.Usage)) { continue; //TODO: !! } this._channels.Add(ch.Usage, ch); } string sHeader = new string(reader.ReadPSDChars(4)); if (sHeader != "8BIM") { throw(new Exception("Layer Channelheader error!")); } //'levl'=Levels 'curv'=Curves 'brit'=Brightness/contrast 'blnc'=Color balance 'hue '=Old Hue/saturation, Photoshop 4.0 'hue2'=New Hue/saturation, Photoshop 5.0 'selc'=Selective color 'thrs'=Threshold 'nvrt'=Invert 'post'=Posterize this.BlendKey = new string(reader.ReadPSDChars(4)); int nBlend = -1; try { nBlend = (int)Enum.Parse(typeof(_blendKeysPsd), this.BlendKey); } catch { throw new Exception("Unknown blend key: " + this.BlendKey); } if (nBlend >= 0) { BlendKeys key = (BlendKeys)nBlend; this.BlendKey = Enum.GetName(typeof(BlendKeys), key); } this.Opacity = reader.ReadByte(); this.Clipping = reader.ReadByte(); this.Flags = reader.ReadByte(); reader.ReadByte(); //padding uint extraDataSize = reader.ReadUInt32(); long nChannelEndPos = reader.BaseStream.Position + (long)extraDataSize; if (extraDataSize > 0) { uint nLength; this._mask = new Mask(reader, this); if (this._mask.Rectangle == null) { this._mask = null; } //blending ranges this._blendRanges = new List <System.Drawing.Color>(); nLength = reader.ReadUInt32(); //First come Composite gray blend source / destination; Contains 2 black values followed by 2 white values. Present but irrelevant for Lab & Grayscale. //Then 4+4 for each channel (source + destination colors) for (uint i = 0; i < nLength / 8; i++) { this._blendRanges.Add(System.Drawing.Color.FromArgb((int)reader.ReadUInt32())); this._blendRanges.Add(System.Drawing.Color.FromArgb((int)reader.ReadUInt32())); } //Name //nLength = (uint)reader.ReadByte(); //reader.BaseStream.Position -= 1; //TODO: wtf did I do here? this.Name = reader.ReadPascalString(); //TODO: sometimes there's a 2-byte padding here, but it's not 4-aligned... What is it? long posBefore = reader.BaseStream.Position; sHeader = new string(reader.ReadPSDChars(4)); if (sHeader != "8BIM") { reader.BaseStream.Position -= 2; sHeader = new string(reader.ReadPSDChars(4)); } if (sHeader != "8BIM") { reader.BaseStream.Position = posBefore; } else { reader.BaseStream.Position -= 4; this._resources = LayerResource.ReadLayerResources(reader, null); } if (reader.BaseStream.Position != nChannelEndPos) { reader.BaseStream.Position = nChannelEndPos; } } }
public EffectBase(BinaryPSDReader reader) : base(reader) { }
public Document(string a_sFilename) { this.Init(); FileStream stream = new FileStream(a_sFilename, FileMode.Open, FileAccess.Read); //stream. BinaryPSDReader reader = new BinaryPSDReader(stream); string signature = new string(reader.ReadPSDChars(4)); if (signature != "8BPS") return; this._header = new Header(reader); //this.Version = reader.ReadUInt16(); //if (Version != 1) // throw new Exception("Can not read .psd version " + Version); //byte[] buf = new byte[256]; //reader.Read(buf, (int)reader.BaseStream.Position, 6); //6 bytes reserved //this.Channels = reader.ReadInt16(); //this.Rows = reader.ReadUInt32(); //this.Columns = reader.ReadUInt32(); //this.BitsPerPixel = (int)reader.ReadUInt16(); //this.ColorMode = (ColorModes)reader.ReadInt16(); #region Palette uint nPaletteLength = reader.ReadUInt32(); if (nPaletteLength > 0) { this.ColorTable = new List<Color>(); for (int i = 0; i < nPaletteLength; i+=3) { this.ColorTable.Add(Color.FromArgb((int)reader.ReadByte(), (int)reader.ReadByte(), (int)reader.ReadByte())); } //this.ColorTable.Add(Color.FromArgb(255, 10, 20)); if (this.ColorMode == ColorModes.Duotone) { } else { } } #endregion uint nResLength = reader.ReadUInt32(); //? Number of bytes, or number of entries?? if (nResLength > 0) { //read settings this._imageResources = ImageResource.ReadImageResources(reader); } //reader.JumpToEvenNthByte(4); uint nTotalLayersBytes = reader.ReadUInt32(); long nAfterLayersDefinitions = reader.BaseStream.Position + nTotalLayersBytes; if (nTotalLayersBytes == 8) { stream.Position += nTotalLayersBytes; //this.Unknown = Endogine.Serialization.ReadableBinary.CreateHexEditorString(reader.ReadBytes((int)reader.BytesToEnd)); } else { uint nSize = reader.ReadUInt32(); //What's the difference between nTotalLayersBytes and nSize really? long nLayersEndPos = reader.BaseStream.Position + nSize; short nNumLayers = reader.ReadInt16(); bool bSkipFirstAlpha = false; if (nNumLayers < 0) { bSkipFirstAlpha = true; nNumLayers = (short)-nNumLayers; } List<Layer> loadOrderLayers = new List<Layer>(); this._layers = new List<Layer>(); // new Dictionary<int, Layer>(); for (int nLayerNum = 0; nLayerNum < nNumLayers; nLayerNum++) { Layer layerInfo = new Layer(reader, this); layerInfo.DebugLayerLoadOrdinal = nLayerNum; //if (layerInfo.LayerID < 0) // layerInfo.LayerID = nLayerNum; //if (this._layers.ContainsKey(layerInfo.LayerID)) // throw(new Exception("Duplicate layer IDs! " + layerInfo.LayerID.ToString())); //else // this._layers.Add(layerInfo.LayerID, layerInfo); this._layers.Add(layerInfo); loadOrderLayers.Add(layerInfo); } for (int layerNum = 0; layerNum < nNumLayers; layerNum++) { Layer layer = (Layer)loadOrderLayers[layerNum]; layer.ReadPixels(reader); } reader.JumpToEvenNthByte(4); if (reader.BaseStream.Position != nLayersEndPos) reader.BaseStream.Position = nLayersEndPos; // nAfterLayersDefinitions; //Global layer mask uint maskLength = reader.ReadUInt32(); this._tempGlobalLayerMask = null; if (maskLength > 0) { this._tempGlobalLayerMask = reader.ReadBytes((int)maskLength); //TODO: the docs are obviously wrong here... //ushort overlayColorSpace = reader.ReadUInt16(); //undefined in docs //for (int i = 0; i < 4; i++) // reader.ReadUInt16(); //TODO: UInt16 if 16-bit color? Color components - says *both* 4*2 bytes, and 8 bytes in the docs? //reader.ReadUInt16(); //opacity (0-100) //reader.ReadByte(); //Kind: 0=Color selectedi.e. inverted; 1=Color protected;128=use value stored per layer. //reader.ReadByte(); //padding } //hmm... another section of "global" layer resources..? while (true) { long cpPos = reader.BaseStream.Position; string sHeader = new string(reader.ReadPSDChars(4)); reader.BaseStream.Position = cpPos; //TODO: -= 4 should work, but sometimes ReadPSDChars advances 5?!?! if (sHeader != "8BIM") { break; } LayerResource res = LayerResource.ReadLayerResource(reader, null); this._globalLayerResources.Add(res); } } bool readGlobalImage = true; if (readGlobalImage) { this._globalImage = new GlobalImage(this); this._globalImage.Load(reader); //the big merged bitmap (which is how the photoshop document looked when it was saved) //Bitmap bmp = this._globalImage.Bitmap; } reader.Close(); stream.Close(); }
public Document(string a_sFilename) { this.Init(); FileStream stream = new FileStream(a_sFilename, FileMode.Open, FileAccess.Read); //stream. BinaryPSDReader reader = new BinaryPSDReader(stream); string signature = new string(reader.ReadPSDChars(4)); if (signature != "8BPS") { return; } this._header = new Header(reader); //this.Version = reader.ReadUInt16(); //if (Version != 1) // throw new Exception("Can not read .psd version " + Version); //byte[] buf = new byte[256]; //reader.Read(buf, (int)reader.BaseStream.Position, 6); //6 bytes reserved //this.Channels = reader.ReadInt16(); //this.Rows = reader.ReadUInt32(); //this.Columns = reader.ReadUInt32(); //this.BitsPerPixel = (int)reader.ReadUInt16(); //this.ColorMode = (ColorModes)reader.ReadInt16(); #region Palette uint nPaletteLength = reader.ReadUInt32(); if (nPaletteLength > 0) { this.ColorTable = new List <Color>(); for (int i = 0; i < nPaletteLength; i += 3) { this.ColorTable.Add(Color.FromArgb((int)reader.ReadByte(), (int)reader.ReadByte(), (int)reader.ReadByte())); } //this.ColorTable.Add(Color.FromArgb(255, 10, 20)); if (this.ColorMode == ColorModes.Duotone) { } else { } } #endregion uint nResLength = reader.ReadUInt32(); //? Number of bytes, or number of entries?? if (nResLength > 0) { //read settings this._imageResources = ImageResource.ReadImageResources(reader); } //reader.JumpToEvenNthByte(4); uint nTotalLayersBytes = reader.ReadUInt32(); long nAfterLayersDefinitions = reader.BaseStream.Position + nTotalLayersBytes; if (nTotalLayersBytes == 8) { stream.Position += nTotalLayersBytes; //this.Unknown = Endogine.Serialization.ReadableBinary.CreateHexEditorString(reader.ReadBytes((int)reader.BytesToEnd)); } else { uint nSize = reader.ReadUInt32(); //What's the difference between nTotalLayersBytes and nSize really? long nLayersEndPos = reader.BaseStream.Position + nSize; short nNumLayers = reader.ReadInt16(); bool bSkipFirstAlpha = false; if (nNumLayers < 0) { bSkipFirstAlpha = true; nNumLayers = (short)-nNumLayers; } List <Layer> loadOrderLayers = new List <Layer>(); this._layers = new List <Layer>(); // new Dictionary<int, Layer>(); for (int nLayerNum = 0; nLayerNum < nNumLayers; nLayerNum++) { Layer layerInfo = new Layer(reader, this); layerInfo.DebugLayerLoadOrdinal = nLayerNum; //if (layerInfo.LayerID < 0) // layerInfo.LayerID = nLayerNum; //if (this._layers.ContainsKey(layerInfo.LayerID)) // throw(new Exception("Duplicate layer IDs! " + layerInfo.LayerID.ToString())); //else // this._layers.Add(layerInfo.LayerID, layerInfo); this._layers.Add(layerInfo); loadOrderLayers.Add(layerInfo); } for (int layerNum = 0; layerNum < nNumLayers; layerNum++) { Layer layer = (Layer)loadOrderLayers[layerNum]; layer.ReadPixels(reader); } reader.JumpToEvenNthByte(4); if (reader.BaseStream.Position != nLayersEndPos) { reader.BaseStream.Position = nLayersEndPos; // nAfterLayersDefinitions; } //Global layer mask uint maskLength = reader.ReadUInt32(); this._tempGlobalLayerMask = null; if (maskLength > 0) { this._tempGlobalLayerMask = reader.ReadBytes((int)maskLength); //TODO: the docs are obviously wrong here... //ushort overlayColorSpace = reader.ReadUInt16(); //undefined in docs //for (int i = 0; i < 4; i++) // reader.ReadUInt16(); //TODO: UInt16 if 16-bit color? Color components - says *both* 4*2 bytes, and 8 bytes in the docs? //reader.ReadUInt16(); //opacity (0-100) //reader.ReadByte(); //Kind: 0=Color selectedi.e. inverted; 1=Color protected;128=use value stored per layer. //reader.ReadByte(); //padding } //hmm... another section of "global" layer resources..? while (true) { long cpPos = reader.BaseStream.Position; string sHeader = new string(reader.ReadPSDChars(4)); reader.BaseStream.Position = cpPos; //TODO: -= 4 should work, but sometimes ReadPSDChars advances 5?!?! if (sHeader != "8BIM") { break; } LayerResource res = LayerResource.ReadLayerResource(reader, null); this._globalLayerResources.Add(res); } } bool readGlobalImage = true; if (readGlobalImage) { this._globalImage = new GlobalImage(this); this._globalImage.Load(reader); //the big merged bitmap (which is how the photoshop document looked when it was saved) //Bitmap bmp = this._globalImage.Bitmap; } reader.Close(); stream.Close(); }
public static List<ImageResource> ReadImageResources(BinaryPSDReader reader) { List<ImageResource> result = new List<ImageResource>(); while (true) { long nBefore = reader.BaseStream.Position; string settingSignature = new string(reader.ReadPSDChars(4)); if (settingSignature != "8BIM") { reader.BaseStream.Position = nBefore; //reader.BaseStream.Position-=4; break; } ImageResource imgRes = new ImageResource(reader); ResourceIDs resID = (ResourceIDs)imgRes.ID; if (!Enum.IsDefined(typeof(ResourceIDs), (int)imgRes.ID)) { if (imgRes.ID > 2000 && imgRes.ID <= 2999) { //Stupid Adobe engineers... This is SO not using the same pattern as everything else!!! resID = ResourceIDs.PathInfo; } } if (ResourceTypes.ContainsKey(resID)) { Type type = ResourceTypes[resID]; System.Reflection.ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(ImageResource) }); imgRes = (ImageResource)ci.Invoke(new object[] { imgRes }); } //if (resID != ResourceIDs.Undefined) result.Add(imgRes); } return result; }
public byte[] PreReadPixels(BinaryPSDReader reader, Compression compression) { switch (compression) { case Compression.Rle: //ignore rle "header" with bytes per row... reader.BaseStream.Position += this._height * 2; //ushort[] rowLenghtList = new ushort[height]; //for (int i = 0; i < height; i++) // rowLenghtList[i] = reader.ReadUInt16(); break; } return null; }
public byte[] ReadPixels(BinaryPSDReader reader, Compression compression) { int bytesPerPixelPerChannel = this._bitsPerPixel / 8; // psd.Header.Depth / 8; if (bytesPerPixelPerChannel < 1) bytesPerPixelPerChannel = 1; int bytesPerRow = this._width * bytesPerPixelPerChannel; int totalBytes = bytesPerRow * this._height; byte[] pData = new byte[totalBytes]; switch (compression) { case Compression.None: reader.Read(pData, 0, totalBytes); break; case Compression.Rle: for (int i = 0; i < this._height; i++) { int offset = i * this._width; int numDecodedBytes = 0; int numChunks = 0; while (numDecodedBytes < this._width) { numDecodedBytes += Endogine.Serialization.RleCodec.DecodeChunk(reader.BaseStream, pData, offset + numDecodedBytes); numChunks++; } } break; case Compression.ZipNoPrediction: throw (new Exception("ZIP without prediction, no specification")); case Compression.ZipPrediction: throw (new Exception("ZIP with prediction, no specification")); default: throw (new Exception("Compression not defined: " + compression)); } return pData; }
public static LayerResource ReadLayerResource(BinaryPSDReader reader, Type inheritsType) { long posBefore = reader.BaseStream.Position; string sHeader = new string(reader.ReadPSDChars(4)); if (sHeader != "8BIM") { reader.BaseStream.Position = posBefore; //back it up return null; } string tag = new string(reader.ReadPSDChars(4)); Type type = null; bool usingDefault = false; if (!ResourceTypes.ContainsKey(tag)) { if (inheritsType == null) inheritsType = typeof(LayerResource); //throw new Exception("LayerResource tag unknown: " + tag); type = inheritsType; usingDefault = true; //LayerResource temp = new LayerResource(reader); //temp.Tag = tag; //return temp; } else type = ResourceTypes[tag]; System.Reflection.ConstructorInfo ci = type.GetConstructor(new Type[] { typeof(BinaryPSDReader) }); LayerResource res = (LayerResource)ci.Invoke(new object[] { reader }); res.Tag = tag; return res; }
public string ReadBlendKey(BinaryPSDReader r) { string blendModeSignature = new string(r.ReadPSDChars(4)); return new string(r.ReadPSDChars(4)); }
//public void AddChannel(Channel ch) //{ // this._channels.Add(ch.Usage, ch); //} public Layer(BinaryPSDReader reader, Document document) { this._document = document; this._rect = reader.ReadPSDRectangle(); ushort numChannels = reader.ReadUInt16(); this._channels = new Dictionary<int, Channel>(); for (int channelNum = 0; channelNum < numChannels; channelNum++) { Channel ch = new Channel(reader, this); if (this._channels.ContainsKey(ch.Usage)) continue; //TODO: !! this._channels.Add(ch.Usage, ch); } string sHeader = new string(reader.ReadPSDChars(4)); if (sHeader != "8BIM") throw(new Exception("Layer Channelheader error!")); //'levl'=Levels 'curv'=Curves 'brit'=Brightness/contrast 'blnc'=Color balance 'hue '=Old Hue/saturation, Photoshop 4.0 'hue2'=New Hue/saturation, Photoshop 5.0 'selc'=Selective color 'thrs'=Threshold 'nvrt'=Invert 'post'=Posterize this.BlendKey = new string(reader.ReadPSDChars(4)); int nBlend = -1; try { nBlend = (int)Enum.Parse(typeof(_blendKeysPsd), this.BlendKey); } catch { throw new Exception("Unknown blend key: " + this.BlendKey); } if (nBlend >= 0) { BlendKeys key = (BlendKeys)nBlend; this.BlendKey = Enum.GetName(typeof(BlendKeys), key); } this.Opacity = reader.ReadByte(); this.Clipping = reader.ReadByte(); this.Flags = reader.ReadByte(); reader.ReadByte(); //padding uint extraDataSize = reader.ReadUInt32(); long nChannelEndPos = reader.BaseStream.Position + (long)extraDataSize; if (extraDataSize > 0) { uint nLength; this._mask = new Mask(reader, this); if (this._mask.Rectangle == null) this._mask = null; //blending ranges this._blendRanges = new List<System.Drawing.Color>(); nLength = reader.ReadUInt32(); //First come Composite gray blend source / destination; Contains 2 black values followed by 2 white values. Present but irrelevant for Lab & Grayscale. //Then 4+4 for each channel (source + destination colors) for (uint i = 0; i < nLength/8; i++) { this._blendRanges.Add(System.Drawing.Color.FromArgb((int)reader.ReadUInt32())); this._blendRanges.Add(System.Drawing.Color.FromArgb((int)reader.ReadUInt32())); } //Name //nLength = (uint)reader.ReadByte(); //reader.BaseStream.Position -= 1; //TODO: wtf did I do here? this.Name = reader.ReadPascalString(); //TODO: sometimes there's a 2-byte padding here, but it's not 4-aligned... What is it? long posBefore = reader.BaseStream.Position; sHeader = new string(reader.ReadPSDChars(4)); if (sHeader != "8BIM") { reader.BaseStream.Position-=2; sHeader = new string(reader.ReadPSDChars(4)); } if (sHeader != "8BIM") reader.BaseStream.Position = posBefore; else { reader.BaseStream.Position -= 4; this._resources = LayerResource.ReadLayerResources(reader, null); } if (reader.BaseStream.Position != nChannelEndPos) reader.BaseStream.Position = nChannelEndPos; } }
public static DynVal ReadValue(BinaryPSDReader r, bool ignoreName) { DynVal vt = new DynVal(); if (!ignoreName) vt.Name = GetMeaningOfFourCC(ReadSpecialString(r)); // r.ReadPascalString(); //else //TODO: should be assigned a sequential number? string type = new string(r.ReadPSDChars(4)); switch (type) { case "tdta": vt.Value = Endogine.Serialization.ReadableBinary.CreateHexEditorString(r.ReadBytes(9)); vt.Children = new List<DynVal>(); while (true) { DynVal child = new DynVal(); vt.Children.Add(child); if (child.ReadTdtaItem(r) == false) break; } //r.BaseStream.Position += 9; break; case "Objc": //Decriptor case "GlbO": //GlobalObject (same) string uniName = r.ReadPSDUnicodeString(); //uint numSub = r.ReadUInt32(); //if (numSub > 1) //{ // //A unicode text here!? What does this have to do with numSub?? // r.BaseStream.Position -= 4; // r.ReadPSDUnicodeString(); // r.BaseStream.Position -= 2; //Ehh... What?! //} ////TODO: ah: 1 = 1 short = unknown... //ushort unknown = r.ReadUInt16(); //vt.Children = ReadValues(r); vt = new DynVal(r, false); if (uniName.Length > 0) vt.UnicodeName = uniName; break; case "VlLs": //List vt.Children = new List<DynVal>(); int numValues = (int)r.ReadUInt32(); for (int i = 0; i < numValues; i++) { DynVal ob = ReadValue(r, true); if (ob != null) vt.Children.Add(ob); } break; case "doub": vt.Value = r.ReadPSDDouble(); break; case "UntF": //Unif float //TODO: need a specific type for this, with a double and a type (percent/pixel)? string tst = GetMeaningOfFourCC(new string(r.ReadPSDChars(4))); //#Prc #Pxl #Ang = percent / pixels / angle? double d = r.ReadPSDDouble(); tst += ": " + d; vt.Value = tst; break; case "enum": string namesp = ReadSpecialString(r); string item = ReadSpecialString(r); //vt.Value = namesp + "." + item; //TODO: cast to real enum vt.Value = GetMeaningOfFourCC(namesp) + "." + GetMeaningOfFourCC(item); break; case "long": vt.Value = r.ReadInt32(); //64? break; case "bool": vt.Value = r.ReadBoolean(); break; //case "obj ": //reference // break; case "TEXT": vt.Value = r.ReadPSDUnicodeString(); break; //case "Enmr": //Enumerated // break; //case "Clss": //Class // break; //case "GlbC": //GlobalClass // break; //case "alis": //Alias // break; default: throw new Exception("Unknown type: " + type); } if (vt.Value == null && vt.Children == null) return null; return vt; }
public void Load(BinaryPSDReader reader) { this.CreateLayer(); this._fakeLayer.ReadPixels(reader); //Test: System.Drawing.Bitmap bmp = this.GetChannelBitmap(0); }
public bool ReadTdtaItem(BinaryPSDReader r) { this.Name = ""; while (r.BytesToEnd > 0) { char c = r.ReadChar(); if (c == 0x0a) break; this.Name += c; } byte[] buffer = new byte[255]; int bufPos = 0; int nearEndCnt = 0; //Read until a slash or several 0x00 comes along while (r.BytesToEnd > 0) { byte b = r.ReadByte(); buffer[bufPos++] = b; if (b == 0x2f) // slash "/" seems to be the field delimiter break; if (b <= 0x00) { nearEndCnt++; if (nearEndCnt == 12) break; } else nearEndCnt = 0; } if (this.Name.Contains(" ")) { int index = this.Name.IndexOf(" "); string val = this.Name.Substring(index + 1); //Sometimes it's a unicode string (how do I know..? seems to always have parenthesis) Ugly shortcut: if (val[0] == '(' && val[val.Length - 1] == ')') { bool unicode = true; for (int i = 0; i < val.Length; i ++) if (val[i] != 0 && val[i] <= 31) { unicode = false; break; } if (unicode) { string uniVal = ""; for (int i = 2; i < val.Length; i += 2) uniVal += val[i]; val = uniVal; } else { byte[] tmp = new byte[val.Length]; int i = 0; foreach (char ch in val) tmp[i++] = (byte)ch; val = Endogine.Serialization.ReadableBinary.CreateHexEditorString(tmp).Replace("\r\n", " "); } } this.Value = val; this.Name = this.Name.Remove(index); } int endPos = bufPos - nearEndCnt - 1; //See if it's only 0x09's: for (int i = 0; i < endPos; i++) { if (buffer[i] != 0x09) { //TODO: this.Data = Endogine.Serialization.ReadableBinary.CreateHexEditorString(buffer, 0, endPos); break; } } return (nearEndCnt == 0 && r.BytesToEnd > 0); //OK to continue reading values? }
public static Dictionary<string, LayerResource> ReadLayerResources(BinaryPSDReader reader, Type inheritsType) { Prepare(); Dictionary<string, LayerResource> result = new Dictionary<string, LayerResource>(); while (true) { LayerResource res = ReadLayerResource(reader, inheritsType); if (res == null) break; result.Add(res.Tag, res); } return result; }
public void ReadPixels(BinaryPSDReader reader) { int numChannelsToRead = this._channels.Count; if (this._channels.ContainsKey(-2)) numChannelsToRead--; PixelData px = new PixelData(this.Width, this.Height, this.BitsPerPixel, numChannelsToRead, this._isMerged); px.Read(reader); int i = 0; foreach (Channel ch in this._channels.Values) { if (ch.Usage != -2) ch.Data = px.GetChannelData(i++); //ch.ReadPixels(reader); } if (this._mask != null) { px = new PixelData(this.Width, this.Height, this.BitsPerPixel, 1, false); px.Read(reader); this._mask.Data = px.GetChannelData(0); //this._mask.ReadPixels(reader); } }
//public LayerResource(LayerResource res) //{ // Prepare(); // this.Tag = res.Tag; //} public LayerResource(BinaryPSDReader reader) { //this.Tag = new string(reader.ReadPSDChars(4)); uint settingLength = reader.ReadUInt32(); this.Data = reader.ReadBytes((int)settingLength); if (!(this is EffectBase)) reader.JumpToEvenNthByte(2); }