public Bitmap Render(Stream s, out IList<IPsdLayer> layers, out Size size,ShowLayerDelegate showLayerCallback, ComposeLayerDelegate composeLayer) { PsdFile file = new PsdFile(); file.Load(s); //Start with a transparent bitmap (not all PSD files have background layers) size = new Size(file.Columns, file.Rows); Bitmap b = new Bitmap(file.Columns, file.Rows); //ImageDecoder.DecodeImage(file.Layers[0]); //Layers collection doesn't include the composed layer Graphics g = Graphics.FromImage(b); using (g){ g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; for (int i = 0; i < file.Layers.Count; i++) { if (showLayerCallback(i,file.Layers[i].Name,file.Layers[i].Visible)){ using (Bitmap frame = ImageDecoder.DecodeImage(file.Layers[i])){ composeLayer(g, frame, file.Layers[i]); } } } } layers = getLayers(file); return b; }
public IList<IPsdLayer> GetLayersAndSize(Stream s, out Size size) { PsdFile file = new PsdFile(); file.Load(s); size = new Size(file.Columns,file.Rows); return getLayers(file); }
public void MapLayers(PsdFile ps) { output.Clear(); ps.Layers.OrderBy(l => l.Rect.X).ThenBy(l => l.Rect.Y) .ToList() .ForEach(l => { var nameTokens = l.Name.Split(new char[] { '-' }, 2); var sizeTokens = nameTokens[0].Split('x'); var size = new Size(Convert.ToInt32(sizeTokens[0]), Convert.ToInt32(sizeTokens[1])); var name = nameTokens[1]; var x = l.Rect.X - Math.Round((size.Width - l.Rect.Width) / 2.0, MidpointRounding.AwayFromZero); var y = l.Rect.Y - Math.Round((size.Height - l.Rect.Height) / 2.0, MidpointRounding.AwayFromZero); output.AppendText( String.Format(".{0} {{ width: {1}px; height: {2}px; background-position: {3}px {4}px; }}{5}", name, size.Width, size.Height, x, y, Environment.NewLine ) ); }); }
/////////////////////////////////////////////////////////////////////////// public Layer(PsdFile psdFile) { PsdFile = psdFile; Rect = new Rect(); Channels = new ChannelList(); BlendModeKey = PsdBlendMode.Normal; AdditionalInfo = new List <LayerInfo>(); }
/////////////////////////////////////////////////////////////////////////// private static Color GetColor(PsdFile psdFile, int pos) { Color c = Color.White; switch (psdFile.ColorMode) { case PsdFile.ColorModes.RGB: c = Color.FromArgb(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); break; case PsdFile.ColorModes.CMYK: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], psdFile.ImageData[3][pos]); break; case PsdFile.ColorModes.Multichannel: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], 0); break; case PsdFile.ColorModes.Bitmap: byte bwValue = ImageDecoder.GetBitmapValue(psdFile.ImageData[0], pos); c = Color.FromArgb(bwValue, bwValue, bwValue); break; case PsdFile.ColorModes.Grayscale: case PsdFile.ColorModes.Duotone: c = Color.FromArgb(psdFile.ImageData[0][pos], psdFile.ImageData[0][pos], psdFile.ImageData[0][pos]); break; case PsdFile.ColorModes.Indexed: { int index = (int)psdFile.ImageData[0][pos]; c = Color.FromArgb((int)psdFile.ColorModeData[index], psdFile.ColorModeData[index + 256], psdFile.ColorModeData[index + 2 * 256]); } break; case PsdFile.ColorModes.Lab: { c = LabToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); } break; } return(c); }
private IList<IPsdLayer> getLayers(PsdFile file) { List<IPsdLayer> items = new List<IPsdLayer>(file.Layers.Count); for (int i = 0; i < file.Layers.Count; i++) { items.Add(new PsdLayer(file.Layers[i],i)); } return items; }
private static Color GetColor(PsdFile psdFile, int pos) { Color c = Color.White; switch (psdFile.ColorMode) { case PsdFile.ColorModes.RGB: c = Color.FromArgb( // read alpha if that channel is available (otherwise default to full alpha) (3 < psdFile.ImageData.Length ? psdFile.ImageData[3][pos] : 255), psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); break; case PsdFile.ColorModes.CMYK: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], psdFile.ImageData[3][pos]); break; case PsdFile.ColorModes.Multichannel: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], 0); break; case PsdFile.ColorModes.Grayscale: case PsdFile.ColorModes.Duotone: c = Color.FromArgb(psdFile.ImageData[0][pos], psdFile.ImageData[0][pos], psdFile.ImageData[0][pos]); break; case PsdFile.ColorModes.Indexed: { int index = (int)psdFile.ImageData[0][pos]; c = Color.FromArgb((int)psdFile.ColorModeData[index], psdFile.ColorModeData[index + 256], psdFile.ColorModeData[index + 2 * 256]); } break; case PsdFile.ColorModes.Lab: { c = LabToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); } break; } return(c); }
/////////////////////////////////////////////////////////////////////////// public static Bitmap DecodeImage(PsdFile psdFile) { Bitmap bitmap = new Bitmap(psdFile.Columns, psdFile.Rows, PixelFormat.Format32bppArgb); #if TEST for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor=GetColor(psdFile,pos); bitmap.SetPixel(x, y, pixelColor); } } #else Rectangle r = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bd = bitmap.LockBits(r, ImageLockMode.ReadWrite, bitmap.PixelFormat); unsafe { byte* pCurrRowPixel = (byte*)bd.Scan0.ToPointer(); for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; PixelData* pCurrPixel = (PixelData*)pCurrRowPixel; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); pCurrPixel->Alpha = 255; pCurrPixel->Red = pixelColor.R; pCurrPixel->Green = pixelColor.G; pCurrPixel->Blue = pixelColor.B; pCurrPixel += 1; } pCurrRowPixel += bd.Stride; } } bitmap.UnlockBits(bd); #endif return bitmap; }
/////////////////////////////////////////////////////////////////////////// public Layer(PsdFile psdFile) { PsdFile = psdFile; Rect = Rectangle.Empty; Channels = new ChannelList(); BlendModeKey = PsdBlendMode.Normal; AdditionalInfo = new List <LayerInfo>(); IsGroup = false; ParentLayer = null; IsEndGroupMarker = false; }
/////////////////////////////////////////////////////////////////////////// /// <summary> /// Decodes the main, composed layer of a PSD file into a bitmap with no transparency. /// </summary> /// <param name="psdFile"></param> /// <returns></returns> public static Bitmap DecodeImage(PsdFile psdFile) { Bitmap bitmap = new Bitmap(psdFile.Columns, psdFile.Rows, PixelFormat.Format32bppArgb); #if TEST for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); bitmap.SetPixel(x, y, pixelColor); } } #else Rectangle r = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bd = bitmap.LockBits(r, ImageLockMode.ReadWrite, bitmap.PixelFormat); unsafe { byte *pCurrRowPixel = (byte *)bd.Scan0.ToPointer(); for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; PixelData *pCurrPixel = (PixelData *)pCurrRowPixel; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); pCurrPixel->Alpha = 255; pCurrPixel->Red = pixelColor.R; pCurrPixel->Green = pixelColor.G; pCurrPixel->Blue = pixelColor.B; pCurrPixel += 1; } pCurrRowPixel += bd.Stride; } } bitmap.UnlockBits(bd); #endif return(bitmap); }
public void OnGUI() { EditorGUI.BeginChangeCheck(); image = (Texture2D)EditorGUILayout.ObjectField("PSD File", image, typeof(Texture2D), true); bool changed = EditorGUI.EndChangeCheck(); if (image != null) { if (changed) { string path = AssetDatabase.GetAssetPath(image); if (path.ToUpper().EndsWith(".PSD")) { psd = new PsdFile(path, Encoding.Default); } else { psd = null; } } if (psd != null) { scrollPos = EditorGUILayout.BeginScrollView(scrollPos); foreach (Layer layer in psd.Layers) { if (layer.Name != "</Layer set>") { layer.Visible = EditorGUILayout.ToggleLeft(layer.Name, layer.Visible); } } EditorGUILayout.EndScrollView(); if (GUILayout.Button("Export visible layers")) { ExportLayers(); } atlassize = EditorGUILayout.IntField("Max. atlas size", atlassize); if (!((atlassize != 0) && ((atlassize & (atlassize - 1)) == 0))) { EditorGUILayout.HelpBox("Atlas size should be a power of 2", MessageType.Warning); } if (GUILayout.Button("Create atlas")) { CreateAtlas(); } if (GUILayout.Button("Create sprites")) { CreateSprites(); } } else { EditorGUILayout.HelpBox("This texture is not a PSD file.", MessageType.Error); } } }
public InfoLayers(PsdFile psdFile, string key) { PsdFile = psdFile; switch (key) { // The key does not have to match the bit depth, but it does have to // be one of the known values. case "Layr": case "Lr16": case "Lr32": this.key = key; break; default: throw new PsdInvalidException( $"{nameof(InfoLayers)} key must be Layr, Lr16, or Lr32."); } }
public InfoLayers(PsdBinaryReader reader, PsdFile psdFile, string key, long dataLength) : this(psdFile, key) { if (psdFile.Layers.Count > 0) { throw new PsdInvalidException( "Cannot have both regular layers and Additional Info layers"); } var endPosition = reader.BaseStream.Position + dataLength; psdFile.LoadLayers(reader, false); if (reader.BaseStream.Position != endPosition) { throw new PsdInvalidException( $"Incorrect length for {nameof(InfoLayers)}."); } }
public Bitmap Decode(Stream s) { //Bitmap we will render to System.Drawing.Bitmap b = null; //Time just the parsing/rendering Stopwatch swRender = new Stopwatch(); swRender.Start(); PsdFile psdFile = new PsdFile(); psdFile.Load(s); //Load background layer b = ImageDecoder.DecodeImage(psdFile); //Layers collection doesn't include the composed layer //How fast? swRender.Stop(); trace("Parsing and rendering PSD to a Bitmap instance took " + swRender.ElapsedMilliseconds.ToString(NumberFormatInfo.InvariantInfo) + "ms"); return b; }
internal static void LoadAll(PsdBinaryReader reader, PsdFile psdFile, List <LayerInfo> layerInfoList, long endPosition, bool globalLayerInfo) { // LayerInfo has a 12-byte minimum length. Anything shorter should be // ignored as padding. while (endPosition - reader.BaseStream.Position >= 12) { var layerInfo = Load(reader, psdFile, globalLayerInfo); layerInfoList.Add(layerInfo); } if (reader.BaseStream.Position < endPosition) { reader.BaseStream.Position = endPosition; } else if (reader.BaseStream.Position > endPosition) { throw new PsdInvalidException( "Read past the end of the LayerInfo fields."); } }
/////////////////////////////////////////////////////////////////////////// public Layer(PsdFile psdFile) { PsdFile = psdFile; Rect = new Rect(); Channels = new ChannelList(); BlendModeKey = PsdBlendMode.Normal; AdditionalInfo = new List<LayerInfo>(); }
public IList<IPsdLayer> GetLayers(Stream s) { PsdFile file = new PsdFile(); file.Load(s); return getLayers(file); }
public Layer(BinaryReverseReader reader, PsdFile psdFile) { //从文档 五 - 4 - 1) 开始读 Children = new List <Layer>(); PsdFile = psdFile; Rect rect = new Rect(); rect.y = reader.ReadInt32(); rect.x = reader.ReadInt32(); rect.height = reader.ReadInt32() - rect.y; rect.width = reader.ReadInt32() - rect.x; Rect = rect; int channelCount = reader.ReadUInt16(); Channels = new List <Channel>(); SortedChannels = new SortedList <short, Channel>(); for (int index = 0; index < channelCount; ++index) { Channel channel = new Channel(reader, this); Channels.Add(channel); SortedChannels.Add(channel.ID, channel); } string head = reader.ReadStringNew(4); if (head != "8BIM") { throw new IOException("Layer Channelheader error!"); } string layerRecordsBlendModeKey = reader.ReadStringNew(4); Opacity = reader.ReadByte(); int Clipping = reader.ReadByte(); _flags = new BitVector32(reader.ReadByte()); int Filler = reader.ReadByte(); _imageTransparent = Convert.ToSingle(Opacity) / byte.MaxValue; //文档 五 - 4 - 13) uint num3 = reader.ReadUInt32(); long position1 = reader.BaseStream.Position; MaskData = new Mask(reader, this); _blendingRangesData = new BlendingRanges(reader); long position2 = reader.BaseStream.Position; // 文档 五 - 4 - 21) Name = reader.ReadPascalString(); // read the adjustment info int count = (int)((reader.BaseStream.Position - position2) % 4L); reader.ReadBytes(count); _adjustmentInfo = new List <AdjustmentLayerInfo>(); long num4 = position1 + num3; while (reader.BaseStream.Position < num4) { try { _adjustmentInfo.Add(new AdjustmentLayerInfo(reader, this)); } catch { reader.BaseStream.Position = num4; } } foreach (AdjustmentLayerInfo adjustmentLayerInfo in _adjustmentInfo) { if (adjustmentLayerInfo.Key == "TySh") { ReadTextLayer(adjustmentLayerInfo.DataReader); } else if (adjustmentLayerInfo.Key == "luni") { // read the unicode name BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; byte[] temp1 = dataReader.ReadBytes(3); byte charCount = dataReader.ReadByte(); //本来 charCount 是文本串的长度,可以传入ReadString()限定读取长度,但Text除串头无文本长度信息,因此改为读一段Unicode字符串 Name = dataReader.ReadString(); if (Name == "") { Name = DefaultLayerName; } } //此处针对字体 图层样式 else if (adjustmentLayerInfo.Key == "lrFX") //样式 相关,对于字体来说,就是描边之类的 { ParseLrfxKeyword(adjustmentLayerInfo); //yanruTODO测试屏蔽 } //仅对于图片的 else if (adjustmentLayerInfo.Key == "lspf") { BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; byte[] data = dataReader.ReadBytes(4); } else if (adjustmentLayerInfo.Key == "lclr") { BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; byte[] data = dataReader.ReadBytes(10); } } reader.BaseStream.Position = num4; int deltaL = (int)(MaskData.Rect.x - Rect.x); int deltaR = (int)(Rect.xMax - MaskData.Rect.xMax); int deltaT = (int)(MaskData.Rect.y - Rect.y); int deltaB = (int)(Rect.yMax - MaskData.Rect.yMax); int l = deltaL > 0 ? deltaL : 0; int r = deltaR > 0 ? deltaR : 0; int t = deltaT > 0 ? deltaT : 0; int b = deltaB > 0 ? deltaB : 0; //Unity Document TextureImporter.spriteBorder X=left, Y=bottom, Z=right, W=top. _border = new Vector4(l, b, r, t); //_is9Slice = SLICE_REG.Match(_name).Success; _is9Slice = _name.Contains(SLICE_HEAD); }
public PsdFileInfo(PsdFile psd) { List<int> layerIndices = new List<int>(); List<PSDLayerGroupInfo> layerGroups = new List<PSDLayerGroupInfo>(); List<PSDLayerGroupInfo> openGroupStack = new List<PSDLayerGroupInfo>(); List<bool> layerVisibility = new List<bool>(); // Reverse loop through layers to get the layers in the // same way they are displayed in Photoshop for (int i = psd.Layers.Count - 1; i >= 0; i--) { Layer layer = psd.Layers[i]; layerVisibility.Add(layer.Visible); // Get the section info for this layer var secInfo = layer.AdditionalInfo .Where(info => info.GetType() == typeof(LayerSectionInfo)) .ToArray(); // Section info is basically layer group info bool isOpen = false; bool isGroup = false; bool closeGroup = false; if (secInfo.Any()) { foreach (var layerSecInfo in secInfo) { LayerSectionInfo info = (LayerSectionInfo)layerSecInfo; isOpen = info.SectionType == LayerSectionType.OpenFolder; isGroup = info.SectionType == LayerSectionType.ClosedFolder | isOpen; closeGroup = info.SectionType == LayerSectionType.SectionDivider; if (isGroup || closeGroup) break; } } if (isGroup) { // Open a new layer group info, because we're iterating // through layers backwards, this layer number is the last logical layer openGroupStack.Add(new PSDLayerGroupInfo(layer.Name, i, layer.Visible, isOpen)); } else if (closeGroup) { // Set the start index of the last LayerGroupInfo var closeInfo = openGroupStack.Last(); closeInfo.start = i; // Add it to the layerGroup list layerGroups.Add(closeInfo); // And remove it from the open group stack openGroupStack.RemoveAt(openGroupStack.Count - 1); } else { // Normal layer layerIndices.Add(i); // look for instances if (layer.Name.Contains(" Copy")) { } } } // End layer loop // Since loop was reversed... layerVisibility.Reverse(); LayerVisibility = layerVisibility.ToArray(); LayerIndices = layerIndices.ToArray(); LayerGroups = layerGroups.ToArray(); }
public Layer(BinaryReverseReader reader, PsdFile psdFile) { Debug.WriteLine("Layer started at " + reader.BaseStream.Position.ToString()); m_psdFile = psdFile; m_rect = new Rectangle(); m_rect.Y = reader.ReadInt32(); m_rect.X = reader.ReadInt32(); m_rect.Height = reader.ReadInt32() - m_rect.Y; m_rect.Width = reader.ReadInt32() - m_rect.X; //----------------------------------------------------------------------- int numberOfChannels = reader.ReadUInt16(); this.m_channels.Clear(); for (int channel = 0; channel < numberOfChannels; channel++) { Channel ch = new Channel(reader, this); m_channels.Add(ch); m_sortedChannels.Add(ch.ID, ch); } //----------------------------------------------------------------------- string signature = new string(reader.ReadChars(4)); if (signature != "8BIM") { throw (new IOException("Layer Channelheader error!")); } m_blendModeKey = new string(reader.ReadChars(4)); m_opacity = reader.ReadByte(); m_clipping = reader.ReadByte() > 0; //----------------------------------------------------------------------- byte flags = reader.ReadByte(); m_flags = new BitVector32(flags); //----------------------------------------------------------------------- reader.ReadByte(); //padding //----------------------------------------------------------------------- Debug.WriteLine("Layer extraDataSize started at " + reader.BaseStream.Position.ToString()); // this is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmentLayerInfo uint extraDataSize = reader.ReadUInt32(); // remember the start position for calculation of the // AdjustmentLayerInfo size long extraDataStartPosition = reader.BaseStream.Position; m_maskData = new Mask(reader, this); m_blendingRangesData = new BlendingRanges(reader, this); //----------------------------------------------------------------------- long namePosition = reader.BaseStream.Position; m_name = reader.ReadPascalString(); int paddingBytes = (int)((reader.BaseStream.Position - namePosition) % 4); Debug.Print("Layer {0} padding bytes after name", paddingBytes); reader.ReadBytes(paddingBytes); //----------------------------------------------------------------------- m_adjustmentInfo.Clear(); long adjustmentLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmentLayerEndPos) { try { AdjustmentLayerInfo ali = new AdjustmentLayerInfo(reader, this); if (ali.Key.Equals("lrFX")) { //A sub-key - we want to merge its sub-layer info items with this dict. m_adjustmentInfo.AddRange(new Effects(ali)._resources.Values); } else { m_adjustmentInfo.Add(ali); // Just add the items } } catch { reader.BaseStream.Position = adjustmentLayerEndPos; } } //----------------------------------------------------------------------- // make sure we are not on a wrong offset, so set the stream position // manually reader.BaseStream.Position = adjustmentLayerEndPos; }
/////////////////////////////////////////////////////////////////////////// public static Bitmap DecodeImage(PsdFile psdFile) { var bitmap = new Bitmap(psdFile.Columns, psdFile.Rows, PixelFormat.Format32bppArgb); // Fix to support different pixel resolutions bitmap.SetResolution(psdFile.Resolution.HRes, psdFile.Resolution.VRes); #if TEST for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); bitmap.SetPixel(x, y, pixelColor); } } #else #if true // fix remove unsafeness (admittedly slower) #if false // safe + slow for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); bitmap.SetPixel(x, y, pixelColor /*Color.FromArgb(255, pixelColor)*/); } } #else // safe + fast // based on MSDN -- Bitmap.LockBits // Lock the bitmap's bits. var bmpData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); // Get the address of the first line. var ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap. var nDestLength = Math.Abs(bmpData.Stride) * bitmap.Height; var arrayOutputARGB = new byte[nDestLength]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(ptr, arrayOutputARGB, 0, nDestLength); var nOutputOffset = 0; for (var y = 0; y < psdFile.Rows; y++) { var rowIndex = y * psdFile.Columns; for (var x = 0; x < psdFile.Columns; x++) { var nSourcePosition = rowIndex + x; SetDestinationColor(psdFile, arrayOutputARGB, nOutputOffset, nSourcePosition); nOutputOffset += 4; } } // Copy the RGB values back to the bitmap System.Runtime.InteropServices.Marshal.Copy(arrayOutputARGB, 0, ptr, nDestLength); // Unlock the bits. bitmap.UnlockBits(bmpData); #endif #else Rectangle r = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bd = bitmap.LockBits(r, ImageLockMode.ReadWrite, bitmap.PixelFormat); unsafe { byte *pCurrRowPixel = (byte *)bd.Scan0.ToPointer(); for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; PixelData *pCurrPixel = (PixelData *)pCurrRowPixel; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); pCurrPixel->Alpha = 255; pCurrPixel->Red = pixelColor.R; pCurrPixel->Green = pixelColor.G; pCurrPixel->Blue = pixelColor.B; pCurrPixel += 1; } pCurrRowPixel += bd.Stride; } } bitmap.UnlockBits(bd); #endif #endif return(bitmap); }
public Layer(BinaryReverseReader reader, PsdFile psdFile) { Debug.WriteLine("Layer started at " + reader.BaseStream.Position); m_psdFile = psdFile; m_rect = new Rectangle { Y = reader.ReadInt32(), X = reader.ReadInt32() }; m_rect.Height = reader.ReadInt32() - m_rect.Y; m_rect.Width = reader.ReadInt32() - m_rect.X; //----------------------------------------------------------------------- int numberOfChannels = reader.ReadUInt16(); m_channels.Clear(); for (int channel = 0; channel < numberOfChannels; channel++) { var ch = new Channel(reader, this); m_channels.Add(ch); m_sortedChannels.Add(ch.ID, ch); } //----------------------------------------------------------------------- var signature = new string(reader.ReadChars(4)); if (signature != LayerConstants.EightBimSignature) throw (new IOException("Layer Channelheader error!")); m_blendModeKey = new string(reader.ReadChars(4)); m_opacity = reader.ReadByte(); m_clipping = reader.ReadByte() > 0; //----------------------------------------------------------------------- byte flags = reader.ReadByte(); m_flags = new BitVector32(flags); //----------------------------------------------------------------------- reader.ReadByte(); //padding //----------------------------------------------------------------------- Debug.WriteLine("Layer extraDataSize started at " + reader.BaseStream.Position); // this is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmenLayerInfo uint extraDataSize = reader.ReadUInt32(); // remember the start position for calculation of the // AdjustmenLayerInfo size long extraDataStartPosition = reader.BaseStream.Position; m_maskData = new Mask(reader, this); m_blendingRangesData = new BlendingRanges(reader, this); //----------------------------------------------------------------------- var namePosition = reader.BaseStream.Position; m_name = reader.ReadPascalString(); var paddingBytes = (int)((reader.BaseStream.Position - namePosition) % 4); Debug.Print("Layer {0} padding bytes after name", paddingBytes); reader.ReadBytes(paddingBytes); //----------------------------------------------------------------------- m_adjustmentInfo.Clear(); long adjustmenLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmenLayerEndPos) { try { m_adjustmentInfo.Add(new AdjusmentLayerInfo(reader, this)); } catch { reader.BaseStream.Position = adjustmenLayerEndPos; } } //----------------------------------------------------------------------- // make shure we are not on a wrong offset, so set the stream position // manually reader.BaseStream.Position = adjustmenLayerEndPos; }
public Layer(PsdBinaryReader reader, PsdFile psdFile) : this(psdFile) { Util.DebugMessage(reader.BaseStream, "Load, Begin, Layer"); Rect = reader.ReadRectangle(); //----------------------------------------------------------------------- // Read channel headers. Image data comes later, after the layer header. int numberOfChannels = reader.ReadUInt16(); for (int channel = 0; channel < numberOfChannels; channel++) { var ch = new Channel(reader, this); Channels.Add(ch); } //----------------------------------------------------------------------- // var signature = reader.ReadAsciiChars(4); if (signature != "8BIM") { throw (new PsdInvalidException("Invalid signature in layer header.")); } BlendModeKey = reader.ReadAsciiChars(4); Opacity = reader.ReadByte(); Clipping = reader.ReadBoolean(); var flagsByte = reader.ReadByte(); flags = new BitVector32(flagsByte); reader.ReadByte(); //padding //----------------------------------------------------------------------- // This is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmentLayerInfo. var extraDataSize = reader.ReadUInt32(); var extraDataStartPosition = reader.BaseStream.Position; Masks = new MaskInfo(reader, this); BlendingRangesData = new BlendingRanges(reader, this); Name = reader.ReadPascalString(4); //----------------------------------------------------------------------- // Process Additional Layer Information long adjustmentLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmentLayerEndPos) { var layerInfo = LayerInfoFactory.Load(reader, psdFile: this.PsdFile, globalLayerInfo: false); AdditionalInfo.Add(layerInfo); } foreach (var adjustmentInfo in AdditionalInfo) { switch (adjustmentInfo.Key) { case "luni": Name = ((LayerUnicodeName)adjustmentInfo).Name; break; } } Util.DebugMessage(reader.BaseStream, "Load, End, Layer, {0}", Name); PsdFile.LoadContext.OnLoadLayerHeader(this); }
/// <summary> /// Imports a Photoshop document (.psd) file at the given path. /// </summary> /// <param name="asset">The path of to the .psd file relative to the project.</param> private static void Import(string asset) { currentDepth = MaximumDepth; string fullPath = Path.Combine(GetFullProjectPath(), asset.Replace('\\', '/')); PsdFile psd = new PsdFile(fullPath); CanvasSize = new Vector2(psd.Width, psd.Height); // Set the depth step based on the layer count. If there are no layers, default to 0.1f. depthStep = psd.Layers.Count != 0 ? MaximumDepth / psd.Layers.Count : 0.1f; int lastSlash = asset.LastIndexOf('/'); string assetPathWithoutFilename = asset.Remove(lastSlash + 1, asset.Length - (lastSlash + 1)); PsdName = asset.Replace(assetPathWithoutFilename, string.Empty).Replace(".psd", string.Empty); currentPath = GetFullProjectPath() + "Assets"; currentPath = Path.Combine(currentPath, PsdName); Directory.CreateDirectory(currentPath); if (LayoutInScene || CreatePrefab) { if (UseUnityUI) { CreateUIEventSystem(); CreateUICanvas(); rootPsdGameObject = Canvas; } else { rootPsdGameObject = new GameObject(PsdName); } currentGroupGameObject = rootPsdGameObject; } List<Layer> tree = BuildLayerTree(psd.Layers); ExportTree(tree); if (CreatePrefab) { UnityEngine.Object prefab = PrefabUtility.CreateEmptyPrefab(asset.Replace(".psd", ".prefab")); PrefabUtility.ReplacePrefab(rootPsdGameObject, prefab); if (!LayoutInScene) { // if we are not flagged to layout in the scene, delete the GameObject used to generate the prefab UnityEngine.Object.DestroyImmediate(rootPsdGameObject); } } AssetDatabase.Refresh(); }
/// <summary> /// Imports a Photoshop document (.psd) file at the given path. /// </summary> /// <param name="asset">The path of to the .psd file relative to the project.</param> private static void Import(string asset) { createdNameList = new List<string>(); currentDepth = MaximumDepth; string fullPath = Path.Combine(GetFullProjectPath(), asset.Replace('\\', '/')); PsdFile psd = new PsdFile(fullPath); CanvasSize = ScreenResolution;// new Vector2(psd.Width, psd.Height); Debug.Log(Time.time + "update canvasSize as UI size=" + CanvasSize); // Set the depth step based on the layer count. If there are no layers, default to 0.1f. depthStep = psd.Layers.Count != 0 ? MaximumDepth / psd.Layers.Count : 0.1f; int lastSlash = asset.LastIndexOf('/'); string assetPathWithoutFilename = asset.Remove(lastSlash + 1, asset.Length - (lastSlash + 1)); PsdName = asset.Replace(assetPathWithoutFilename, string.Empty).Replace(".psd", string.Empty); currentPath = GetFullProjectPath() + "Assets/export_image"; //图片的相对目录! currentPath = Path.Combine(currentPath, PsdName); createDic(currentPath); if (LayoutInScene || CreatePrefab) { if (UseUnityUI) { CreateUIEventSystem(); CreateUICanvas(); } //create ui Root rootPsdGameObject = CreateObj(PsdName); updateParent(rootPsdGameObject, canvasObj); //if (fullScreenUI) { RectTransform rectRoot = rootPsdGameObject.GetComponent<RectTransform>(); rectRoot.anchorMin = new Vector2(0, 0); rectRoot.anchorMax = new Vector2(1, 1); rectRoot.offsetMin = Vector2.zero; rectRoot.offsetMax = Vector2.zero; } Vector3 rootPos = Vector3.zero; updateRectPosition(rootPsdGameObject, rootPos, true); currentGroupGameObject = rootPsdGameObject; } List<Layer> tree = BuildLayerTree(psd.Layers); ExportTree(tree); if (CreatePrefab) { UnityEngine.Object prefab = PrefabUtility.CreateEmptyPrefab(asset.Replace(".psd", ".prefab")); PrefabUtility.ReplacePrefab(rootPsdGameObject, prefab); if (!LayoutInScene) { // if we are not flagged to layout in the scene, delete the GameObject used to generate the prefab UnityEngine.Object.DestroyImmediate(rootPsdGameObject); } } //all ui items created, update components Debug.Log(Time.time + ",dealUI=" + rootPsdGameObject.name + ",finish"); int childCount = rootPsdGameObject.transform.childCount; for (int index = 0; index < childCount; index++) { Transform tran = rootPsdGameObject.transform.GetChild(index); tran.position += new Vector3(ScreenResolution.x / 2f, ScreenResolution.y / 2f, 0); } Dictionary<Transform, bool> _dealDic = new Dictionary<Transform, bool>(); //flag if item will be deleted List<Transform> btnList = new List<Transform>(); List<Transform> deleteList = new List<Transform>(); Transform[] allChild = rootPsdGameObject.GetComponentsInChildren<Transform>(); for (int index = 0; index < allChild.Length; index++) { Transform tran = allChild[index]; if (tran.name.IndexOf(BTN_HEAD) == 0) { Button button = tran.gameObject.AddComponent<Button>(); tran.GetComponent<Image>().raycastTarget = true; button.transition = Selectable.Transition.SpriteSwap; btnList.Add(tran); } } for (int btnIndex = 0; btnIndex < btnList.Count; btnIndex++) { string btnName = btnList[btnIndex].name; for (int index = 0; index < allChild.Length; index++) { Transform tran = allChild[index]; //update image sprite deltaSize and PNG attribute Image image = tran.GetComponent<Image>(); if (image != null && image.sprite != null) { string spriteName = image.sprite.name; //匹配以 数字_数字 结尾的串。匹配结果作为九宫格尺寸 string str1 = spriteName; // "4343434";// "testrewer_4_3"; Regex reg = new Regex(@"\d+[_]\d+$"); Match match = reg.Match(str1); if (match.ToString() != "") { //Debug.LogError(Time.time + ",str1=" + str1 + ",满足?" + reg.Match(str1).ToString()); string[] size = reg.Match(str1).ToString().Split('_'); int width = Convert.ToInt32(size[0]); int height = Convert.ToInt32(size[0]); image.GetComponent<RectTransform>().sizeDelta = new Vector2(width, height); image.type = Image.Type.Sliced; if (image.sprite.border == Vector4.zero) { Debug.LogError(Time.time + "need to set png=" + image.sprite.name + ",slice border"); } } } if (allChild[index].name.IndexOf(btnName) == 0) { if (allChild[index].name.Contains(BTN_TAIL_HIGH))//按钮的高亮图 { SpriteState sprite = btnList[btnIndex].GetComponent<Button>().spriteState; sprite.pressedSprite = allChild[index].GetComponent<Image>().sprite; btnList[btnIndex].GetComponent<Button>().spriteState = sprite; deleteList.Add(tran); } if (allChild[index].name.Contains(BTN_TAIL_DIS))//按钮的禁用图 { SpriteState sprite = btnList[btnIndex].GetComponent<Button>().spriteState; sprite.disabledSprite = allChild[index].GetComponent<Image>().sprite; btnList[btnIndex].GetComponent<Button>().spriteState = sprite; deleteList.Add(tran); } } } } //delete no use items for (int index = 0; index < deleteList.Count; index++) { destroyItem(deleteList[index]); } AssetDatabase.Refresh(); }
/// <summary> /// Initializes a new instance of the <see cref="Layer"/> class using the provided reader containing the PSD file data. /// </summary> /// <param name="reader">The reader containing the PSD file data.</param> /// <param name="psdFile">The PSD file to set as the parent.</param> public Layer(BinaryReverseReader reader, PsdFile psdFile) { Children = new List <Layer>(); PsdFile = psdFile; // read the rect Rect rect = new Rect(); rect.y = reader.ReadInt32(); rect.x = reader.ReadInt32(); rect.height = reader.ReadInt32() - rect.y; rect.width = reader.ReadInt32() - rect.x; Rect = rect; // read the channels int channelCount = reader.ReadUInt16(); Channels = new List <Channel>(); SortedChannels = new SortedList <short, Channel>(); for (int index = 0; index < channelCount; ++index) { Channel channel = new Channel(reader, this); Channels.Add(channel); //Debug.Log(Time.time + "channel.ID=" + channel.ID + ",layer=" + this.Name); SortedChannels.Add(channel.ID, channel); } string head = reader.readStringNew(4); //Debug.Log(Time.time + ",head=" + head); // read the header and verify it if (head != "8BIM") { throw new IOException("Layer Channelheader error!"); } // read the blend mode key (unused) (defaults to "norm") //reader.ReadChars(4); string layerRecordsBlendModeKey = reader.readStringNew(4); // read the opacity Opacity = reader.ReadByte(); // read the clipping (unused) (< 0 = base, > 0 = non base) int Clipping = reader.ReadByte(); // read all of the flags (protectTrans, visible, obsolete, ver5orLater, pixelDataIrrelevant) flags = new BitVector32(reader.ReadByte()); // skip a padding byte int Filler = reader.ReadByte(); imageTransparent = Convert.ToSingle(Opacity) / byte.MaxValue; Debug.Log("layerRecordsBlendModeKey=" + layerRecordsBlendModeKey + ",Opacity=" + Opacity + ",Clipping=" + Clipping + ",flags=" + flags + ", Filler=" + Filler + ",LayerTransparent=" + imageTransparent); uint num3 = reader.ReadUInt32(); long position1 = reader.BaseStream.Position; MaskData = new Mask(reader, this); BlendingRangesData = new BlendingRanges(reader); long position2 = reader.BaseStream.Position; // read the name Name = reader.ReadPascalString(); //Debug.Log(Time.time + ",read layer Name=" + Name + ".end"); // read the adjustment info int count = (int)((reader.BaseStream.Position - position2) % 4L); reader.ReadBytes(count); //Debug.Log(Time.time + ",read count=" + count + ".end"); AdjustmentInfo = new List <AdjustmentLayerInfo>(); long num4 = position1 + num3; while (reader.BaseStream.Position < num4) { try { AdjustmentInfo.Add(new AdjustmentLayerInfo(reader, this)); } catch { reader.BaseStream.Position = num4; } } string keyInfo = ""; foreach (AdjustmentLayerInfo adjustmentLayerInfo in AdjustmentInfo) { keyInfo += ",key=" + adjustmentLayerInfo.Key + "\n"; if (adjustmentLayerInfo.Key == "TySh") { ReadTextLayer(adjustmentLayerInfo.DataReader); } else if (adjustmentLayerInfo.Key == "luni") { // read the unicode name BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; byte[] temp1 = dataReader.ReadBytes(3); byte charCount = dataReader.ReadByte(); //本来 charCount 是文本串的长度,可以传入ReadString()限定读取长度,但Text除串头无文本长度信息,因此改为读一段Unicode字符串 Name = dataReader.ReadString(); if (Name == "") { Name = defaultLayerName; } } //此处针对字体 图层样式 else if (adjustmentLayerInfo.Key == "lrFX") //样式 相关,对于字体来说,就是描边之类的 { parseLrfxKeyword(adjustmentLayerInfo); //yanruTODO测试屏蔽 } //仅对于图片的 else if (adjustmentLayerInfo.Key == "lspf") { BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; byte[] data = dataReader.ReadBytes(4); printbytes(data, "lspf data", true); } else if (adjustmentLayerInfo.Key == "lclr") { BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; byte[] data = dataReader.ReadBytes(10); printbytes(data, "lclr data", true); } } Debug.Log("layer=" + Name + ",Totalkey=\n" + keyInfo); reader.BaseStream.Position = num4; }
public Layer(BinaryReverseReader reader, PsdFile psdFile) { Debug.WriteLine("Layer started at " + reader.BaseStream.Position.ToString()); m_psdFile = psdFile; m_rect = new Rectangle(); m_rect.Y = reader.ReadInt32(); m_rect.X = reader.ReadInt32(); m_rect.Height = reader.ReadInt32() - m_rect.Y; m_rect.Width = reader.ReadInt32() - m_rect.X; //----------------------------------------------------------------------- int numberOfChannels = reader.ReadUInt16(); this.m_channels.Clear(); for (int channel = 0; channel < numberOfChannels; channel++) { Channel ch = new Channel(reader, this); m_channels.Add(ch); m_sortedChannels.Add(ch.ID, ch); } //----------------------------------------------------------------------- string signature = new string(reader.ReadChars(4)); if (signature != "8BIM") throw (new IOException("Layer Channelheader error!")); m_blendModeKey = new string(reader.ReadChars(4)); m_opacity = reader.ReadByte(); m_clipping = reader.ReadByte() > 0; //----------------------------------------------------------------------- byte flags = reader.ReadByte(); m_flags = new BitVector32(flags); //----------------------------------------------------------------------- reader.ReadByte(); //padding //----------------------------------------------------------------------- Debug.WriteLine("Layer extraDataSize started at " + reader.BaseStream.Position.ToString()); // this is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmentLayerInfo uint extraDataSize = reader.ReadUInt32(); // remember the start position for calculation of the // AdjustmentLayerInfo size long extraDataStartPosition = reader.BaseStream.Position; m_maskData = new Mask(reader, this); m_blendingRangesData = new BlendingRanges(reader, this); //----------------------------------------------------------------------- long namePosition = reader.BaseStream.Position; m_name = reader.ReadPascalString(); int paddingBytes =(int)((reader.BaseStream.Position - namePosition) % 4); Debug.Print("Layer {0} padding bytes after name", paddingBytes); reader.ReadBytes(paddingBytes); //----------------------------------------------------------------------- m_adjustmentInfo.Clear(); long adjustmentLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmentLayerEndPos) { try { AdjustmentLayerInfo ali = new AdjustmentLayerInfo(reader, this); if (ali.Key.Equals("lrFX")) { //A sub-key - we want to merge its sub-layer info items with this dict. m_adjustmentInfo.AddRange(new Effects(ali)._resources.Values); } else m_adjustmentInfo.Add(ali); // Just add the items } catch { reader.BaseStream.Position = adjustmentLayerEndPos; } } //----------------------------------------------------------------------- // make sure we are not on a wrong offset, so set the stream position // manually reader.BaseStream.Position = adjustmentLayerEndPos; }
/////////////////////////////////////////////////////////////////////////// // fix for performance private static void SetDestinationColor(PsdFile psdFile, byte[] arrayARGB, int nOutputOffset, int nSourcePosition) { Color c = Color.White; switch (psdFile.ColorMode) { case PsdFile.ColorModes.RGB: // can take advantage of a direct copy of the bytes arrayARGB[nOutputOffset + 3] = (3 < psdFile.ImageData.Length ? psdFile.ImageData[3][nSourcePosition] : (byte)255); // ABGR - apparently arrayARGB[nOutputOffset + 2] = psdFile.ImageData[0][nSourcePosition]; arrayARGB[nOutputOffset + 1] = psdFile.ImageData[1][nSourcePosition]; arrayARGB[nOutputOffset + 0] = psdFile.ImageData[2][nSourcePosition]; return; case PsdFile.ColorModes.CMYK: c = CMYKToRGB(psdFile.ImageData[0][nSourcePosition], psdFile.ImageData[1][nSourcePosition], psdFile.ImageData[2][nSourcePosition], psdFile.ImageData[3][nSourcePosition]); break; case PsdFile.ColorModes.Multichannel: c = CMYKToRGB(psdFile.ImageData[0][nSourcePosition], psdFile.ImageData[1][nSourcePosition], psdFile.ImageData[2][nSourcePosition], 0); break; case PsdFile.ColorModes.Grayscale: case PsdFile.ColorModes.Duotone: // can take advantage of a direct copy of the bytes // TODO: can alpha channel be used? arrayARGB[nOutputOffset + 3] = 0xff; arrayARGB[nOutputOffset + 0] = psdFile.ImageData[0][nSourcePosition]; arrayARGB[nOutputOffset + 1] = psdFile.ImageData[0][nSourcePosition]; arrayARGB[nOutputOffset + 2] = psdFile.ImageData[0][nSourcePosition]; return; case PsdFile.ColorModes.Indexed: { var index = (int)psdFile.ImageData[0][nSourcePosition]; c = Color.FromArgb(psdFile.ColorModeData[index], psdFile.ColorModeData[index + 256], psdFile.ColorModeData[index + 2 * 256]); } break; case PsdFile.ColorModes.Lab: { c = LabToRGB(psdFile.ImageData[0][nSourcePosition], psdFile.ImageData[1][nSourcePosition], psdFile.ImageData[2][nSourcePosition]); } break; } // populate the color data // ABGR - apparently arrayARGB[nOutputOffset + 3] = c.A; arrayARGB[nOutputOffset + 0] = c.B; arrayARGB[nOutputOffset + 1] = c.G; arrayARGB[nOutputOffset + 2] = c.R; }
private void Main_Load(object sender, EventArgs ev) { #region Form location Location = Settings.Default.StartLocation; FormClosing += (s, e) => { Settings.Default.StartLocation = Location; Settings.Default.Save(); }; #endregion DragEventHandler enter = (s, e) => { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = e.Data.GetData(DataFormats.FileDrop, false) as string[]; if (files.FirstOrDefault<string>().EndsWith(".psd", StringComparison.OrdinalIgnoreCase)) { e.Effect = DragDropEffects.Copy; } } }; DragEventHandler drop = (s, e) => { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string file = (e.Data.GetData(DataFormats.FileDrop, false) as string[]).FirstOrDefault<string>(); PsdFile ps = new PsdFile(); ps.Load(file); MapLayers(ps); } }; base.DragEnter += enter; base.DragDrop += drop; }
/////////////////////////////////////////////////////////////////////////// public Layer(PsdFile psdFile) { m_psdFile = psdFile; m_psdFile.Layers.Add(this); }
public virtual void OnLoadLayersHeader(PsdFile psdFile) { }
public Layer(BinaryReverseReader reader, PsdFile psdFile) { Debug.WriteLine("Layer started at " + reader.BaseStream.Position); m_psdFile = psdFile; m_rect = new Rectangle { Y = reader.ReadInt32(), X = reader.ReadInt32() }; m_rect.Height = reader.ReadInt32() - m_rect.Y; m_rect.Width = reader.ReadInt32() - m_rect.X; //----------------------------------------------------------------------- int numberOfChannels = reader.ReadUInt16(); m_channels.Clear(); for (int channel = 0; channel < numberOfChannels; channel++) { var ch = new Channel(reader, this); m_channels.Add(ch); m_sortedChannels.Add(ch.ID, ch); } //----------------------------------------------------------------------- var signature = new string(reader.ReadChars(4)); if (signature != LayerConstants.EightBimSignature) { throw (new IOException("Layer Channelheader error!")); } m_blendModeKey = new string(reader.ReadChars(4)); m_opacity = reader.ReadByte(); m_clipping = reader.ReadByte() > 0; //----------------------------------------------------------------------- byte flags = reader.ReadByte(); m_flags = new BitVector32(flags); //----------------------------------------------------------------------- reader.ReadByte(); //padding //----------------------------------------------------------------------- Debug.WriteLine("Layer extraDataSize started at " + reader.BaseStream.Position); // this is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmenLayerInfo uint extraDataSize = reader.ReadUInt32(); // remember the start position for calculation of the // AdjustmenLayerInfo size long extraDataStartPosition = reader.BaseStream.Position; m_maskData = new Mask(reader, this); m_blendingRangesData = new BlendingRanges(reader, this); //----------------------------------------------------------------------- var namePosition = reader.BaseStream.Position; m_name = reader.ReadPascalString(); var paddingBytes = (int)((reader.BaseStream.Position - namePosition) % 4); Debug.Print("Layer {0} padding bytes after name", paddingBytes); reader.ReadBytes(paddingBytes); //----------------------------------------------------------------------- m_adjustmentInfo.Clear(); long adjustmenLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmenLayerEndPos) { try { m_adjustmentInfo.Add(new AdjusmentLayerInfo(reader, this)); } catch { reader.BaseStream.Position = adjustmenLayerEndPos; } } //----------------------------------------------------------------------- // make shure we are not on a wrong offset, so set the stream position // manually reader.BaseStream.Position = adjustmenLayerEndPos; }
/////////////////////////////////////////////////////////////////////////// private static Color GetColor(PsdFile psdFile, int pos) { Color c = Color.White; switch (psdFile.ColorMode) { case PsdFile.ColorModes.RGB: c = Color.FromArgb(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); break; case PsdFile.ColorModes.CMYK: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], psdFile.ImageData[3][pos]); break; case PsdFile.ColorModes.Multichannel: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], 0); break; case PsdFile.ColorModes.Bitmap: byte bwValue = ImageDecoder.GetBitmapValue(psdFile.ImageData[0], pos); c = Color.FromArgb(bwValue, bwValue, bwValue); break; case PsdFile.ColorModes.Grayscale: case PsdFile.ColorModes.Duotone: c = Color.FromArgb(psdFile.ImageData[0][pos], psdFile.ImageData[0][pos], psdFile.ImageData[0][pos]); break; case PsdFile.ColorModes.Indexed: { int index = (int)psdFile.ImageData[0][pos]; c = Color.FromArgb((int)psdFile.ColorModeData[index], psdFile.ColorModeData[index + 256], psdFile.ColorModeData[index + 2 * 256]); } break; case PsdFile.ColorModes.Lab: { c = LabToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); } break; } return c; }
/// <summary> /// Loads the next LayerInfo record. /// </summary> /// <param name="reader">The file reader</param> /// <param name="psdFile">The PSD file.</param> /// <param name="globalLayerInfo">True if the LayerInfo record is being /// loaded from the end of the Layer and Mask Information section; /// false if it is being loaded from the end of a Layer record.</param> /// <returns>LayerInfo object if it was successfully read, or null if /// padding was found.</returns> private static LayerInfo Load(PsdBinaryReader reader, PsdFile psdFile, bool globalLayerInfo) { Util.DebugMessage(reader.BaseStream, "Load, Begin, LayerInfo"); // Most keys have undocumented signatures, so we always accept either one. var signature = reader.ReadAsciiChars(4); if ((signature != "8BIM") && (signature != "8B64")) { throw new PsdInvalidException( $"{nameof(LayerInfo)} signature invalid, must be 8BIM or 8B64."); } var key = reader.ReadAsciiChars(4); var hasLongLength = LayerInfoUtil.HasLongLength(signature, key, psdFile.IsLargeDocument); var length = hasLongLength ? reader.ReadInt64() : reader.ReadInt32(); var startPosition = reader.BaseStream.Position; LayerInfo result; switch (key) { case "Layr": case "Lr16": case "Lr32": result = new InfoLayers(reader, psdFile, key, length); break; case "lsct": case "lsdk": result = new LayerSectionInfo(reader, key, (int)length); break; case "luni": result = new LayerUnicodeName(reader); break; default: result = new RawLayerInfo(reader, signature, key, length); break; } // May have additional padding applied. var endPosition = startPosition + length; if (reader.BaseStream.Position < endPosition) { reader.BaseStream.Position = endPosition; } // Documentation states that the length is even-padded. Actually: // 1. Most keys have 4-padded lengths. // 2. However, some keys (LMsk) have even-padded lengths. // 3. Other keys (Txt2, Lr16, Lr32) have unpadded lengths. // // Photoshop writes data that is always 4-padded, even when the stated // length is not a multiple of 4. The length mismatch seems to occur // only on global layer info. We do not read extra padding in other // cases because third-party programs are likely to follow the spec. if (globalLayerInfo) { reader.ReadPadding(startPosition, 4); } Util.DebugMessage(reader.BaseStream, $"Load, End, LayerInfo, {result.Signature}, {result.Key}"); return(result); }
public Layer(PsdBinaryReader reader, PsdFile psdFile) : this(psdFile) { Rect = reader.ReadRectangle(); //----------------------------------------------------------------------- // Read channel headers. Image data comes later, after the layer header. int numberOfChannels = reader.ReadUInt16(); for (int channel = 0; channel < numberOfChannels; channel++) { var ch = new Channel(reader, this); Channels.Add(ch); } //----------------------------------------------------------------------- // var signature = reader.ReadAsciiChars(4); if (signature != "8BIM") throw (new PsdInvalidException("Invalid signature in layer header.")); BlendModeKey = reader.ReadAsciiChars(4); Opacity = reader.ReadByte(); Clipping = reader.ReadBoolean(); var flagsByte = reader.ReadByte(); flags = new BitVector32(flagsByte); reader.ReadByte(); //padding //----------------------------------------------------------------------- // This is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmentLayerInfo. var extraDataSize = reader.ReadUInt32(); var extraDataStartPosition = reader.BaseStream.Position; Masks = new MaskInfo(reader, this); BlendingRangesData = new BlendingRanges(reader, this); Name = reader.ReadPascalString(4); //----------------------------------------------------------------------- // Process Additional Layer Information long adjustmentLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmentLayerEndPos) { var layerInfo = LayerInfoFactory.Load(reader); AdditionalInfo.Add(layerInfo); } foreach (var adjustmentInfo in AdditionalInfo) { switch (adjustmentInfo.Key) { case "luni": Name = ((LayerUnicodeName)adjustmentInfo).Name; break; } } }
private static Texture LoadSpriteSheetAbsolute(string title, string file_name) { // Load and decompress Photoshop file structures var psdFile = new PsdFile (); psdFile.Load (file_name, Encoding.Default); if (psdFile.Layers.Count == 0) { psdFile.BaseLayer.CreateMissingChannels (); } var layer = psdFile.BaseLayer; using (Bitmap bmp = new Bitmap(psdFile.ColumnCount, psdFile.RowCount)) { using (Graphics gfx = Graphics.FromImage(bmp)) { gfx.Clear (Color.Transparent); var bmp_data = bmp.LockBits (layer.Rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int pixel_size = 4 * sizeof(byte); int idx = 0; for (int i = 0; i < bmp_data.Height; i++) { for (int j = 0; j < bmp_data.Width; j++) { Marshal.Copy (new byte[]{ layer.Channels [2].ImageData [idx], layer.Channels [1].ImageData [idx], layer.Channels [0].ImageData [idx], layer.Channels [3].ImageData [idx], }, 0, new IntPtr ((long)bmp_data.Scan0 + i * bmp_data.Stride + j * pixel_size), pixel_size); idx++; } } bmp.UnlockBits (bmp_data); } var texture = Texture.LoadTexture (title, bmp); psdFile.SlicesToTextureRegionInfo (ref texture); return texture; } }
//public BitVector32 Flags //{ // get { return flags; } //} /// <summary> /// Initializes a new instance of the <see cref="Layer"/> class using the provided reader containing the PSD file data. /// </summary> /// <param name="reader">The reader containing the PSD file data.</param> /// <param name="psdFile">The PSD file to set as the parent.</param> public Layer(BinaryReverseReader reader, PsdFile psdFile) { Children = new List<Layer>(); PsdFile = psdFile; // read the rect Rect rect = new Rect(); rect.y = reader.ReadInt32(); rect.x = reader.ReadInt32(); rect.height = reader.ReadInt32() - rect.y; rect.width = reader.ReadInt32() - rect.x; Rect = rect; // read the channels int channelCount = reader.ReadUInt16(); Channels = new List<Channel>(); SortedChannels = new SortedList<short, Channel>(); for (int index = 0; index < channelCount; ++index) { Channel channel = new Channel(reader, this); Channels.Add(channel); SortedChannels.Add(channel.ID, channel); } // read the header and verify it if (new string(reader.ReadChars(4)) != "8BIM") { throw new IOException("Layer Channelheader error!"); } // read the blend mode key (unused) (defaults to "norm") reader.ReadChars(4); // read the opacity Opacity = reader.ReadByte(); // read the clipping (unused) (< 0 = base, > 0 = non base) reader.ReadByte(); // read all of the flags (protectTrans, visible, obsolete, ver5orLater, pixelDataIrrelevant) flags = new BitVector32(reader.ReadByte()); // skip a padding byte reader.ReadByte(); uint num3 = reader.ReadUInt32(); long position1 = reader.BaseStream.Position; MaskData = new Mask(reader, this); BlendingRangesData = new BlendingRanges(reader); long position2 = reader.BaseStream.Position; // read the name Name = reader.ReadPascalString(); // read the adjustment info int count = (int)((reader.BaseStream.Position - position2) % 4L); reader.ReadBytes(count); AdjustmentInfo = new List<AdjustmentLayerInfo>(); long num4 = position1 + num3; while (reader.BaseStream.Position < num4) { try { AdjustmentInfo.Add(new AdjustmentLayerInfo(reader, this)); } catch { reader.BaseStream.Position = num4; } } foreach (AdjustmentLayerInfo adjustmentLayerInfo in AdjustmentInfo) { if (adjustmentLayerInfo.Key == "TySh") { ReadTextLayer(adjustmentLayerInfo.DataReader); } else if (adjustmentLayerInfo.Key == "luni") { // read the unicode name BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; dataReader.ReadBytes(3); dataReader.ReadByte(); Name = dataReader.ReadString().TrimEnd(new char[1]); } } reader.BaseStream.Position = num4; }
private void OnSaveClick(object sender, EventArgs e) { if (m_fileStructure.Nodes.Count == 0) return; PsdFile psdFileSrc = (PsdFile)m_fileStructure.Nodes[0].Tag; PsdFile psdFile = new PsdFile(); //----------------------------------------------------------------------- psdFile.Rows = psdFileSrc.Rows; psdFile.Columns = psdFileSrc.Columns; // we have an Alpha channel which will be saved, // we have to add this to our image resources psdFile.Channels = 3;// 4; // for now we oly save the images as RGB psdFile.ColorMode = PsdFile.ColorModes.RGB; psdFile.Depth = 8; //----------------------------------------------------------------------- // no color mode Data //----------------------------------------------------------------------- psdFile.ImageResources.Clear(); psdFile.ImageResources.AddRange(psdFileSrc.ImageResources.ToArray()); //----------------------------------------------------------------------- int size = psdFile.Rows * psdFile.Columns; psdFile.ImageData = new byte[psdFile.Channels][]; for (int i = 0; i < psdFile.Channels; i++) { psdFile.ImageData[i] = new byte[size]; } Bitmap bmp = ImageDecoder.DecodeImage(psdFileSrc); for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = bmp.GetPixel(x, y); psdFile.ImageData[0][pos] = pixelColor.R; psdFile.ImageData[1][pos] = pixelColor.G; psdFile.ImageData[2][pos] = pixelColor.B; //psdFile.ImageData[3][pos] = pixelColor.A; } } //----------------------------------------------------------------------- psdFile.ImageCompression = ImageCompression.Rle; psdFile.Save(Path.Combine(Path.GetDirectoryName(m_fileName.Text), Path.GetFileNameWithoutExtension(m_fileName.Text) + "-saved.psd")); }
/// <summary> /// Loads the next LayerInfo record. /// </summary> /// <param name="reader">The file reader</param> /// <param name="psdFile">The PSD file.</param> /// <param name="globalLayerInfo">True if the LayerInfo record is being /// loaded from the end of the Layer and Mask Information section; /// false if it is being loaded from the end of a Layer record.</param> public static LayerInfo Load(PsdBinaryReader reader, PsdFile psdFile, bool globalLayerInfo, long fileEndPos) { Util.DebugMessage(reader.BaseStream, "Load, Begin, LayerInfo"); // Some keys use a signature of 8B64, but the identity of these keys // is undocumented. We will therefore accept either signature. var signature = reader.ReadAsciiChars(4); if ((signature != "8BIM") && (signature != "8B64")) { throw new PsdInvalidException( "LayerInfo signature invalid, must be 8BIM or 8B64."); } var key = reader.ReadAsciiChars(4); var hasLongLength = LayerInfoUtil.HasLongLength(key, psdFile.IsLargeDocument); LayerInfo result = new RawLayerInfo("dummy"); bool breakFromLoop = false; while (!breakFromLoop) { var baseStartPosition = reader.BaseStream.Position; var length = hasLongLength ? reader.ReadInt64() : reader.ReadInt32(); var startPosition = reader.BaseStream.Position; switch (key) { case "Layr": case "Lr16": case "Lr32": result = new InfoLayers(reader, psdFile, key, length); break; case "lsct": case "lsdk": result = new LayerSectionInfo(reader, key, (int)length); break; case "luni": result = new LayerUnicodeName(reader); break; case "lyid": result = new LayerId(reader, key, length); break; default: result = new RawLayerInfo(reader, signature, key, length); break; } // May have additional padding applied. var endPosition = startPosition + length; if (reader.BaseStream.Position < endPosition) { reader.BaseStream.Position = endPosition; } // Documentation states that the length is even-padded. Actually: // 1. Most keys have 4-padded lengths. // 2. However, some keys (LMsk) have even-padded lengths. // 3. Other keys (Txt2, Lr16, Lr32) have unpadded lengths. // // Photoshop writes data that is always 4-padded, even when the stated // length is not a multiple of 4. The length mismatch seems to occur // only on global layer info. We do not read extra padding in other // cases because third-party programs are likely to follow the spec. if (globalLayerInfo) { reader.ReadPadding(startPosition, 4); } //try if we can read the next signature if (reader.BaseStream.Position < fileEndPos) { var nowPosition = reader.BaseStream.Position; signature = reader.ReadAsciiChars(4); if ((signature != "8BIM") && (signature != "8B64")) { hasLongLength = true; reader.BaseStream.Position = baseStartPosition; } else { reader.BaseStream.Position = nowPosition; breakFromLoop = true; } } else { breakFromLoop = true; } } Util.DebugMessage(reader.BaseStream, "Load, End, LayerInfo, {0}, {1}", result.Signature, result.Key); return(result); }
private void OnOpenClick(object sender, EventArgs e) { string fileName = m_fileName.Text; if (File.Exists(fileName)) { UpdateFileLst(fileName); PsdFile pt = new PsdFile(); this.Cursor = Cursors.WaitCursor; pt.Load(fileName); m_fileStructure.Nodes.Clear(); TreeNode fileNode = new TreeNode("PSD File"); fileNode.Tag = pt; m_fileStructure.Nodes.Add(fileNode); foreach (Layer layer in pt.Layers) { TreeNode layerNode = new TreeNode("Layer Name=" + layer.Name); layerNode.Tag = layer; fileNode.Nodes.Add(layerNode); foreach (Layer.Channel ch in layer.Channels) { TreeNode chNode = new TreeNode("Channel ID=" + ch.ID.ToString()); chNode.Tag = ch; layerNode.Nodes.Add(chNode); } TreeNode maskNode = new TreeNode("Mask"); maskNode.Tag = layer.MaskData; layerNode.Nodes.Add(maskNode); TreeNode blendingNode = new TreeNode("BlendingRangesData"); blendingNode.Tag = layer.BlendingRangesData; layerNode.Nodes.Add(blendingNode); foreach (Layer.AdjustmentLayerInfo adjInfo in layer.AdjustmentInfo) { TreeNode node = new TreeNode(adjInfo.Key); node.Tag = adjInfo; layerNode.Nodes.Add(node); } } m_fileStructure.SelectedNode = fileNode; this.Cursor = Cursors.Default; //pt.Save(Path.Combine(Path.GetDirectoryName(m_fileName.Text), Path.GetFileNameWithoutExtension(m_fileName.Text) + "-s.psd")); } }
/////////////////////////////////////////////////////////////////////////// // fix for performance private static void SetDestinationColor(PsdFile psdFile, byte[] arrayARGB, int nOutputOffset, int nSourcePosition) { Color c = Color.White; switch (psdFile.ColorMode) { case PsdFile.ColorModes.RGB: // can take advantage of a direct copy of the bytes arrayARGB[nOutputOffset + 3] = (3 < psdFile.ImageData.Length ? psdFile.ImageData[3][nSourcePosition] : (byte) 255); // ABGR - apparently arrayARGB[nOutputOffset + 2] = psdFile.ImageData[0][nSourcePosition]; arrayARGB[nOutputOffset + 1] = psdFile.ImageData[1][nSourcePosition]; arrayARGB[nOutputOffset + 0] = psdFile.ImageData[2][nSourcePosition]; return; case PsdFile.ColorModes.CMYK: c = CMYKToRGB(psdFile.ImageData[0][nSourcePosition], psdFile.ImageData[1][nSourcePosition], psdFile.ImageData[2][nSourcePosition], psdFile.ImageData[3][nSourcePosition]); break; case PsdFile.ColorModes.Multichannel: c = CMYKToRGB(psdFile.ImageData[0][nSourcePosition], psdFile.ImageData[1][nSourcePosition], psdFile.ImageData[2][nSourcePosition], 0); break; case PsdFile.ColorModes.Grayscale: case PsdFile.ColorModes.Duotone: // can take advantage of a direct copy of the bytes // TODO: can alpha channel be used? arrayARGB[nOutputOffset + 3] = 0xff; arrayARGB[nOutputOffset + 0] = psdFile.ImageData[0][nSourcePosition]; arrayARGB[nOutputOffset + 1] = psdFile.ImageData[0][nSourcePosition]; arrayARGB[nOutputOffset + 2] = psdFile.ImageData[0][nSourcePosition]; return; case PsdFile.ColorModes.Indexed: { var index = (int) psdFile.ImageData[0][nSourcePosition]; c = Color.FromArgb(psdFile.ColorModeData[index], psdFile.ColorModeData[index + 256], psdFile.ColorModeData[index + 2*256]); } break; case PsdFile.ColorModes.Lab: { c = LabToRGB(psdFile.ImageData[0][nSourcePosition], psdFile.ImageData[1][nSourcePosition], psdFile.ImageData[2][nSourcePosition]); } break; } // populate the color data // ABGR - apparently arrayARGB[nOutputOffset + 3] = c.A; arrayARGB[nOutputOffset + 0] = c.B; arrayARGB[nOutputOffset + 1] = c.G; arrayARGB[nOutputOffset + 2] = c.R; }
public PsdExportSettings(Texture2D image) { string path = AssetDatabase.GetAssetPath(image); if (!path.ToUpper().EndsWith(".PSD")) return; Psd = new PsdFile(path, Encoding.Default); Filename = Path.GetFileNameWithoutExtension(path); Image = image; ScaleBy = 0; Pivot = SpriteAlignment.Center; PixelsToUnitSize = 100f; LoadMetaData(); }
private static Color GetColor(PsdFile psdFile, int pos) { Color c = Color.White; switch (psdFile.ColorMode) { case PsdFile.ColorModes.RGB: c = Color.FromArgb( // read alpha if that channel is available (otherwise default to full alpha) (3 < psdFile.ImageData.Length ? psdFile.ImageData[3][pos] : 255), psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); break; case PsdFile.ColorModes.CMYK: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], psdFile.ImageData[3][pos]); break; case PsdFile.ColorModes.Multichannel: c = CMYKToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos], 0); break; case PsdFile.ColorModes.Grayscale: case PsdFile.ColorModes.Duotone: c = Color.FromArgb(psdFile.ImageData[0][pos], psdFile.ImageData[0][pos], psdFile.ImageData[0][pos]); break; case PsdFile.ColorModes.Indexed: { int index = (int) psdFile.ImageData[0][pos]; c = Color.FromArgb((int) psdFile.ColorModeData[index], psdFile.ColorModeData[index + 256], psdFile.ColorModeData[index + 2*256]); } break; case PsdFile.ColorModes.Lab: { c = LabToRGB(psdFile.ImageData[0][pos], psdFile.ImageData[1][pos], psdFile.ImageData[2][pos]); } break; } return c; }
/////////////////////////////////////////////////////////////////////////// public static Bitmap DecodeImage(PsdFile psdFile) { var bitmap = new Bitmap(psdFile.Columns, psdFile.Rows, PixelFormat.Format32bppArgb); // Fix to support different pixel resolutions bitmap.SetResolution(psdFile.Resolution.HRes, psdFile.Resolution.VRes); #if TEST for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor=GetColor(psdFile,pos); bitmap.SetPixel(x, y, pixelColor); } } #else #if true // fix remove unsafeness (admittedly slower) #if false // safe + slow for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); bitmap.SetPixel(x, y, pixelColor/*Color.FromArgb(255, pixelColor)*/); } } #else // safe + fast // based on MSDN -- Bitmap.LockBits // Lock the bitmap's bits. var bmpData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); // Get the address of the first line. var ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap. var nDestLength = Math.Abs(bmpData.Stride)*bitmap.Height; var arrayOutputARGB = new byte[nDestLength]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(ptr, arrayOutputARGB, 0, nDestLength); var nOutputOffset = 0; for (var y = 0; y < psdFile.Rows; y++) { var rowIndex = y*psdFile.Columns; for (var x = 0; x < psdFile.Columns; x++) { var nSourcePosition = rowIndex + x; SetDestinationColor(psdFile, arrayOutputARGB, nOutputOffset, nSourcePosition); nOutputOffset += 4; } } // Copy the RGB values back to the bitmap System.Runtime.InteropServices.Marshal.Copy(arrayOutputARGB, 0, ptr, nDestLength); // Unlock the bits. bitmap.UnlockBits(bmpData); #endif #else Rectangle r = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bd = bitmap.LockBits(r, ImageLockMode.ReadWrite, bitmap.PixelFormat); unsafe { byte* pCurrRowPixel = (byte*)bd.Scan0.ToPointer(); for (int y = 0; y < psdFile.Rows; y++) { int rowIndex = y * psdFile.Columns; PixelData* pCurrPixel = (PixelData*)pCurrRowPixel; for (int x = 0; x < psdFile.Columns; x++) { int pos = rowIndex + x; Color pixelColor = GetColor(psdFile, pos); pCurrPixel->Alpha = 255; pCurrPixel->Red = pixelColor.R; pCurrPixel->Green = pixelColor.G; pCurrPixel->Blue = pixelColor.B; pCurrPixel += 1; } pCurrRowPixel += bd.Stride; } } bitmap.UnlockBits(bd); #endif #endif return bitmap; }
/// <summary> /// Initializes a new instance of the <see cref="Layer"/> class using the provided reader containing the PSD file data. /// </summary> /// <param name="reader">The reader containing the PSD file data.</param> /// <param name="psdFile">The PSD file to set as the parent.</param> public Layer(BinaryReverseReader reader, PsdFile psdFile) { Children = new List <Layer>(); PsdFile = psdFile; // read the rect Rect rect = new Rect(); rect.y = reader.ReadInt32(); rect.x = reader.ReadInt32(); rect.height = reader.ReadInt32() - rect.y; rect.width = reader.ReadInt32() - rect.x; Rect = rect; // read the channels int channelCount = reader.ReadUInt16(); Channels = new List <Channel>(); SortedChannels = new SortedList <short, Channel>(); for (int index = 0; index < channelCount; ++index) { Channel channel = new Channel(reader, this); Channels.Add(channel); SortedChannels.Add(channel.ID, channel); } // read the header and verify it if (new string(reader.ReadChars(4)) != "8BIM") { throw new IOException("Layer Channelheader error!"); } // read the blend mode key (unused) (defaults to "norm") reader.ReadChars(4); // read the opacity Opacity = reader.ReadByte(); // read the clipping (unused) (< 0 = base, > 0 = non base) reader.ReadByte(); // read all of the flags (protectTrans, visible, obsolete, ver5orLater, pixelDataIrrelevant) flags = new BitVector32(reader.ReadByte()); // skip a padding byte reader.ReadByte(); uint num3 = reader.ReadUInt32(); long position1 = reader.BaseStream.Position; MaskData = new Mask(reader, this); BlendingRangesData = new BlendingRanges(reader); long position2 = reader.BaseStream.Position; // read the name Name = reader.ReadPascalString(); // read the adjustment info int count = (int)((reader.BaseStream.Position - position2) % 4L); reader.ReadBytes(count); AdjustmentInfo = new List <AdjustmentLayerInfo>(); long num4 = position1 + num3; while (reader.BaseStream.Position < num4) { try { AdjustmentInfo.Add(new AdjustmentLayerInfo(reader, this)); } catch { reader.BaseStream.Position = num4; } } foreach (AdjustmentLayerInfo adjustmentLayerInfo in AdjustmentInfo) { if (adjustmentLayerInfo.Key == "TySh") { ReadTextLayer(adjustmentLayerInfo.DataReader); } else if (adjustmentLayerInfo.Key == "luni") { // read the unicode name BinaryReverseReader dataReader = adjustmentLayerInfo.DataReader; dataReader.ReadBytes(3); dataReader.ReadByte(); Name = dataReader.ReadString().TrimEnd(new char[1]); } } reader.BaseStream.Position = num4; }
public Layer(PsdBinaryReader reader, PsdFile psdFile) : this(psdFile) { IsText = false; Rect = reader.ReadRectangle(); //----------------------------------------------------------------------- // Read channel headers. Image data comes later, after the layer header. int numberOfChannels = reader.ReadUInt16(); for (int channel = 0; channel < numberOfChannels; channel++) { var ch = new Channel(reader, this); Channels.Add(ch); } //----------------------------------------------------------------------- // var signature = reader.ReadAsciiChars(4); if (signature != "8BIM") { throw (new PsdInvalidException("Invalid signature in layer header.")); } BlendModeKey = reader.ReadAsciiChars(4); Opacity = reader.ReadByte(); Clipping = reader.ReadBoolean(); var flagsByte = reader.ReadByte(); flags = new BitVector32(flagsByte); reader.ReadByte(); //padding //----------------------------------------------------------------------- // This is the total size of the MaskData, the BlendingRangesData, the // Name and the AdjustmentLayerInfo. var extraDataSize = reader.ReadUInt32(); var extraDataStartPosition = reader.BaseStream.Position; Masks = new MaskInfo(reader, this); BlendingRangesData = new BlendingRanges(reader, this); Name = reader.ReadPascalString(4); //----------------------------------------------------------------------- // Process Additional Layer Information long adjustmentLayerEndPos = extraDataStartPosition + extraDataSize; while (reader.BaseStream.Position < adjustmentLayerEndPos) { var layerInfo = LayerInfoFactory.Load(reader); AdditionalInfo.Add(layerInfo); } foreach (var adjustmentInfo in AdditionalInfo) { switch (adjustmentInfo.Key) { case "luni": Name = ((LayerUnicodeName)adjustmentInfo).Name; break; case "TySh": IsText = true; LayerText = (LayerText)adjustmentInfo; break; case "lrFX": Effects = (EffectsLayer)adjustmentInfo; break; case "lfx2": BaseEffect = (ObjectBasedEffect)adjustmentInfo; break; } } }