예제 #1
0
        /// <summary>
        /// Store layer metadata and image data.
        /// </summary>
        public static void StoreLayer(BitmapLayer layer,
                                      PhotoshopFile.Layer psdLayer, PsdSaveConfigToken psdToken)
        {
            // Set layer metadata
            psdLayer.Name               = layer.Name;
            psdLayer.Rect               = FindImageRectangle(layer.Surface);
            psdLayer.BlendModeKey       = PsdBlendMode.Normal;
            psdLayer.Opacity            = layer.Opacity;
            psdLayer.Visible            = layer.Visible;
            psdLayer.Masks              = new MaskInfo();
            psdLayer.BlendingRangesData = new BlendingRanges(psdLayer);

            // Store channel metadata
            int layerSize = psdLayer.Rect.Width * psdLayer.Rect.Height;

            for (int i = -1; i < 3; i++)
            {
                var ch = new Channel((short)i, psdLayer);
                ch.ImageCompression = psdToken.RleCompress ? ImageCompression.Rle : ImageCompression.Raw;
                ch.ImageData        = new byte[layerSize];
                psdLayer.Channels.Add(ch);
            }

            // Store and compress channel image data
            var channelsArray = psdLayer.Channels.ToIdArray();

            StoreLayerImage(channelsArray, psdLayer.AlphaChannel, layer.Surface, psdLayer.Rect);
        }
예제 #2
0
파일: Mask.cs 프로젝트: hgrandry/Mgx
 public Mask(Layer layer, Rectangle rect, byte color, BitVector32 flags)
 {
     Layer = layer;
     Rect = rect;
     BackgroundColor = color;
     this.flags = flags;
 }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Mask"/> class.
        /// </summary>
        /// <param name="reader">The reader to use to initialize the instance.</param>
        /// <param name="layer">The layer this mask belongs to.</param>
        internal Mask(BinaryReverseReader reader, Layer layer)
        {
            Layer = layer;
            uint num1 = reader.ReadUInt32();
            if (num1 <= 0U)
            {
                return;
            }

            long position = reader.BaseStream.Position;
            rect = new Rect();
            rect.y = reader.ReadInt32();
            rect.x = reader.ReadInt32();
            rect.height = reader.ReadInt32() - rect.y;
            rect.width = reader.ReadInt32() - rect.x;
            DefaultColor = reader.ReadByte();
            flags = new BitVector32(reader.ReadByte());
            if ((int)num1 == 36)
            {
                reader.ReadByte();  // bit vector
                reader.ReadByte();  // ???
                reader.ReadInt32(); // rect Y
                reader.ReadInt32(); // rect X
                reader.ReadInt32(); // rect total height (actual height = this - Y)
                reader.ReadInt32(); // rect total width (actual width = this - Y)
            }

            reader.BaseStream.Position = position + num1;
        }
            public DecodeContext(PhotoshopFile.Layer layer, Rectangle bounds)
            {
                Layer           = layer;
                ByteDepth       = Util.BytesFromBitDepth(layer.PsdFile.BitDepth);
                HasAlphaChannel = 0;
                Channels        = layer.Channels.ToIdArray();

                var alphaSize = 4;

                if (layer.AlphaChannel != null && layer.AlphaChannel.ImageData.Length > 0)
                {
                    HasAlphaChannel = 1;
                    alphaSize       = layer.AlphaChannel.ImageData.Length;
                    alphaSize       = (alphaSize / 4) + (alphaSize % 4 > 0 ? 1 : 0);
                    alphaSize       = alphaSize * 4;
                }
                AlphaChannel = new NativeArray <byte>(alphaSize, Allocator.TempJob);
                if (HasAlphaChannel > 0)
                {
                    NativeArray <byte> .Copy(layer.AlphaChannel.ImageData, AlphaChannel, layer.AlphaChannel.ImageData.Length);
                }
                ColorMode     = layer.PsdFile.ColorMode;
                ColorModeData = new NativeArray <byte>(layer.PsdFile.ColorModeData, Allocator.TempJob);

                // Clip the layer to the specified bounds
                Rectangle = Layer.Rect.IntersectWith(bounds);

                if (layer.Masks != null)
                {
                    LayerMaskContext = GetMaskContext(layer.Masks.LayerMask);
                    UserMaskContext  = GetMaskContext(layer.Masks.UserMask);
                }
            }
예제 #5
0
        private ComposeLayerDelegate BuildModifyLayerCallback(NameValueCollection queryString)
        {
            PsdCommandSearcher searcher = new PsdCommandSearcher(new PsdCommandBuilder(queryString));

            return(delegate(Graphics g, Bitmap b, object layer)
            {
                PhotoshopFile.Layer l = (PhotoshopFile.Layer)layer;
                //See if this layer is supposed to be re-colored.
                Nullable <Color> color = searcher.getColor(l.Name);

                if (b == null && l.Rect.X == 0 && l.Rect.Y == 0 && l.Rect.Width == 0 && l.Rect.Height == 0)
                {
                    return; //This layer has no size, it is probably a layer group.
                }

                //See if we need to re-draw this text layer
                Nullable <bool> redraw = searcher.getRedraw(l.Name);
                if (redraw != null && redraw == true)
                {
                    //Verify it has text layer information:
                    bool hasText = false;
                    foreach (PhotoshopFile.Layer.AdjustmentLayerInfo lInfo in  l.AdjustmentInfo)
                    {
                        if (lInfo.Key.Equals("TySh", StringComparison.Ordinal))
                        {
                            hasText = true; break;
                        }
                    }


                    if (hasText)
                    {
                        //Re-draw the text directly, ignoring the bitmap
                        var tlr = new TextLayerRenderer(l);
                        tlr.IgnoreMissingFonts = !isStrictMode();
                        tlr.Render(g, color, searcher.getReplacementText(l.Name));
                        return;
                    }
                }


                if (b == null && !isStrictMode())
                {
                    return;                                   //Skip drawing layers that have no bitmap data.
                }
                if (b == null)
                {
                    throw new Exception("No bitmap data found for layer " + l.Name);
                }
                //Draw the existing bitmap
                //Blend color into bitmap
                if (color != null)
                {
                    ColorBitmap(b, color.Value);
                }
                //Draw image
                g.DrawImage(b, l.Rect);
            });
        }
예제 #6
0
 public LoadLayerContext(PhotoshopFile.Layer psdLayer, Document document, UserBlendOp blendOp, List <Layer> layersList, int idxLayersList)
 {
     this.psdLayer      = psdLayer;
     this.document      = document;
     this.blendOp       = blendOp;
     this.layersList    = layersList;
     this.idxLayersList = idxLayersList;
 }
예제 #7
0
        ///////////////////////////////////////////////////////////////////////////

        public PsdFile() {
            Version = 1;
            BaseLayer = new Layer(this);

            ImageResources = new ImageResources();
            Layers = new List<Layer>();
            AdditionalInfo = new List<LayerInfo>();
        }
예제 #8
0
        public override void OnLoadLayerHeader(PhotoshopFile.Layer layer)
        {
            var psdFile = layer.PsdFile;

            if (psdFile.ColorMode == PsdColorMode.Multichannel)
            {
                PsdLoad.CheckSufficientMemory(psdFile);
            }
        }
예제 #9
0
 public SaveLayerPixelsContext(BitmapLayer layer, PsdFile psdFile,
                               Document input, PhotoshopFile.Layer psdLayer, PsdSaveConfigToken psdToken)
 {
     this.layer    = layer;
     this.psdFile  = psdFile;
     this.input    = input;
     this.psdToken = psdToken;
     this.psdLayer = psdLayer;
 }
예제 #10
0
        /// <summary>
        /// Store layer metadata and image data.
        /// </summary>
        public static void StoreLayer(
            BitmapLayerInfo layerInfo,
            PhotoshopFile.Layer psdLayer,
            PsdSaveConfigToken psdToken)
        {
            var layer = layerInfo.Layer;

            // Set layer metadata
            psdLayer.Name = layerInfo.Name;
            psdLayer.Rect = FindImageRectangle(layer.Surface);

            psdLayer.Opacity            = layer.Opacity;
            psdLayer.Masks              = new MaskInfo();
            psdLayer.BlendingRangesData = new BlendingRanges(psdLayer);

            // Store channel metadata
            int layerSize = psdLayer.Rect.Width * psdLayer.Rect.Height;

            for (int i = -1; i < 3; i++)
            {
                var ch = new Channel((short)i, psdLayer);
                ch.ImageCompression = psdToken.RleCompress ? ImageCompression.Rle : ImageCompression.Raw;
                ch.ImageData        = new byte[layerSize];
                psdLayer.Channels.Add(ch);
            }

            psdLayer.BlendModeKey = layer.BlendMode.ToPsdBlendMode();
            psdLayer.Visible      = layer.Visible;

            // Create folders/groups before actual image data will be saved.
            if (psdToken.SaveLayers && !layerInfo.RenderAsRegularLayer)
            {
                if (layerInfo.IsGroupStart)
                {
                    var status = layer.Visible ? LayerSectionType.OpenFolder : LayerSectionType.ClosedFolder;
                    psdLayer.AdditionalInfo.Add(new LayerSectionInfo(status));
                    psdLayer.Name    = layerInfo.Name;
                    psdLayer.Visible = true;
                }
                else if (layerInfo.IsGroupEnd)
                {
                    // End of the group
                    psdLayer.Opacity      = 255;
                    psdLayer.BlendModeKey = PsdBlendMode.PassThrough;
                    psdLayer.Name         = "</Layer group>";
                    psdLayer.AdditionalInfo.Add(new LayerSectionInfo(LayerSectionType.SectionDivider));
                }

                return;
            }

            // Store and compress channel image data
            var channelsArray = psdLayer.Channels.ToIdArray();

            StoreLayerImage(channelsArray, psdLayer.AlphaChannel, layer.Surface, psdLayer.Rect);
        }
예제 #11
0
        ///////////////////////////////////////////////////////////////////////////
        public BlendingRanges(PsdBinaryReader reader, Layer layer)
        {
            Debug.WriteLine("BlendingRanges started at " + reader.BaseStream.Position.ToString(CultureInfo.InvariantCulture));

            Layer = layer;
            var dataLength = reader.ReadInt32();
            if (dataLength <= 0)
                return;

            Data = reader.ReadBytes(dataLength);
        }
예제 #12
0
 /////////////////////////////////////////////////////////////////////////// 
 unsafe private static void SetPDNColor(ColorBgra* dstPixel, PhotoshopFile.Layer layer,
     PhotoshopFile.Layer.Channel[] channels, PhotoshopFile.Layer.Channel alphaChannel, int pos)
 {
   switch (layer.PsdFile.ColorMode)
   {
     case PsdFile.ColorModes.RGB:
       dstPixel->R = channels[0].ImageData[pos];
       dstPixel->G = channels[1].ImageData[pos];
       dstPixel->B = channels[2].ImageData[pos];
       break;
     case PsdFile.ColorModes.CMYK:
       SetPDNColorCMYK(dstPixel,
         channels[0].ImageData[pos],
         channels[1].ImageData[pos],
         channels[2].ImageData[pos],
         channels[3].ImageData[pos]);
       break;
     case PsdFile.ColorModes.Multichannel:
       SetPDNColorCMYK(dstPixel,
         channels[0].ImageData[pos],
         channels[1].ImageData[pos],
         channels[2].ImageData[pos],
         0);
       break;
     case PsdFile.ColorModes.Bitmap:
       byte bwValue = ImageDecoder.GetBitmapValue(channels[0].ImageData, pos);
       dstPixel->R = bwValue;
       dstPixel->G = bwValue;
       dstPixel->B = bwValue;
       break;
     case PsdFile.ColorModes.Grayscale:
     case PsdFile.ColorModes.Duotone:
       dstPixel->R = channels[0].ImageData[pos];
       dstPixel->G = channels[0].ImageData[pos];
       dstPixel->B = channels[0].ImageData[pos];
       break;
     case PsdFile.ColorModes.Indexed:
       int index = (int)channels[0].ImageData[pos];
       dstPixel->R = (byte)layer.PsdFile.ColorModeData[index];
       dstPixel->G = layer.PsdFile.ColorModeData[index + 256];
       dstPixel->B = layer.PsdFile.ColorModeData[index + 2 * 256];
       break;
     case PsdFile.ColorModes.Lab:
       SetPDNColorLab(dstPixel,
         channels[0].ImageData[pos],
         channels[1].ImageData[pos],
         channels[2].ImageData[pos]);
       break;
   }
 }
예제 #13
0
    /////////////////////////////////////////////////////////////////////////// 

    public static BitmapLayer DecodeImage(PhotoshopFile.Layer psdLayer)
    {
      BitmapLayer pdnLayer = new BitmapLayer(psdLayer.PsdFile.Columns, psdLayer.PsdFile.Rows);

      Surface surface = pdnLayer.Surface;
      surface.Clear((ColorBgra)0);

      bool hasMaskChannel = psdLayer.SortedChannels.ContainsKey(-2);
      var channels = psdLayer.ChannelsArray;
      var alphaChannel = psdLayer.AlphaChannel;

      int yPsdLayerStart = Math.Max(0, -psdLayer.Rect.Y);
      int yPsdLayerEnd = Math.Min(psdLayer.Rect.Height, surface.Height - psdLayer.Rect.Y);

      for (int yPsdLayer = yPsdLayerStart; yPsdLayer < yPsdLayerEnd; yPsdLayer++)
      {
        unsafe
        {
          ColorBgra* dstRow = surface.GetRowAddress(yPsdLayer + psdLayer.Rect.Y);

          int xPsdLayerStart = Math.Max(0, -psdLayer.Rect.X);
          int xPsdLayerEnd = Math.Min(psdLayer.Rect.Width, psdLayer.PsdFile.Columns - psdLayer.Rect.Left);
          int xPsdLayerEndCopy = Math.Min(xPsdLayerEnd, surface.Width - psdLayer.Rect.X);

          int srcRowIndex = yPsdLayer * psdLayer.Rect.Width;
          int dstIndex = psdLayer.Rect.Left + xPsdLayerStart;
          ColorBgra* dstPixel = dstRow + dstIndex;

          for (int xPsdLayer = xPsdLayerStart; xPsdLayer < xPsdLayerEnd; xPsdLayer++)
          {
            if (xPsdLayer < xPsdLayerEndCopy)
            {
              int srcIndex = srcRowIndex + xPsdLayer;
              SetPDNColor(dstPixel, psdLayer, channels, alphaChannel, srcIndex);
              int maskAlpha = 255;
              if (hasMaskChannel)
              {
                maskAlpha = GetMaskAlpha(psdLayer.MaskData, xPsdLayer, yPsdLayer);
              }
              SetPDNAlpha(dstPixel, alphaChannel, srcIndex, maskAlpha);
            }

            dstPixel++;
          }
        }
      }

      return pdnLayer;
    }
예제 #14
0
        internal static JobHandle DecodeToPdnLayer(this PhotoshopFile.Layer psdLayer, JobHandle inputDeps, out BitmapLayer pdnLayer)
        {
            var psdFile = psdLayer.PsdFile;

            psdLayer.CreateMissingChannels();

            pdnLayer           = new BitmapLayer(psdFile.ColumnCount, psdFile.RowCount);
            pdnLayer.Name      = psdLayer.Name;
            pdnLayer.Opacity   = psdLayer.Opacity;
            pdnLayer.Visible   = psdLayer.Visible;
            pdnLayer.IsGroup   = psdLayer.IsGroup;
            pdnLayer.LayerID   = psdLayer.LayerID;
            pdnLayer.BlendMode = BlendModeMapping.FromPsdBlendMode(psdLayer.BlendModeKey);
            return(ImageDecoderPdn.DecodeImage(pdnLayer, psdLayer, inputDeps));
        }
예제 #15
0
            public PsdLayer(Layer layer, int index)
            {
                _name = layer.Name;
                _rect = layer.Rect;
                _visible = layer.Visible;
                _index = index;

                List<PhotoshopFile.Layer.AdjustmentLayerInfo> adjustments = layer.AdjustmentInfo;
                for (int j = 0; j < adjustments.Count; j++)
                {
                    if (adjustments[j].Key.Equals("TySh"))
                    {
                        this._isTextLayer = true;
                    }
                }
            }
        /// <summary>
        /// Initializes a new instance of the <see cref="AdjustmentLayerInfo"/> class.
        /// </summary>
        /// <param name="reader">The reader containing the PSD file data</param>
        /// <param name="layer">The layer that this adjustment info belongs to</param>
        public AdjustmentLayerInfo(BinaryReverseReader reader, Layer layer)
        {
            if (new string(reader.ReadChars(4)) != "8BIM")
            {
                throw new IOException("Could not read an image resource");
            }

            Key = new string(reader.ReadChars(4));
            if (Key == "lfx2" || Key == "lrFX")
            {
                layer.HasEffects = true;
            }

            uint length = reader.ReadUInt32();
            Data = reader.ReadBytes((int)length);
        }
예제 #17
0
        internal static BitmapLayer DecodeToPdnLayer(
            this PhotoshopFile.Layer psdLayer)
        {
            var psdFile = psdLayer.PsdFile;

            psdLayer.CreateMissingChannels();

            var pdnLayer = new BitmapLayer(psdFile.ColumnCount, psdFile.RowCount);

            pdnLayer.Name    = psdLayer.Name;
            pdnLayer.Opacity = psdLayer.Opacity;
            pdnLayer.Visible = psdLayer.Visible;
            ImageDecoderPdn.DecodeImage(pdnLayer, psdLayer);

            return(pdnLayer);
        }
예제 #18
0
        /// <summary>
        /// Decode image from Photoshop's channel-separated formats to BGRA.
        /// </summary>
        public static unsafe void DecodeImage(BitmapLayer pdnLayer,
                                              PhotoshopFile.Layer psdLayer)
        {
            var            decodeContext = new DecodeContext(psdLayer, pdnLayer.Bounds);
            DecodeDelegate decoder       = null;

            if (decodeContext.ByteDepth == 4)
            {
                decoder = GetDecodeDelegate32(decodeContext.ColorMode);
            }
            else
            {
                decoder = GetDecodeDelegate(decodeContext.ColorMode);
            }

            DecodeImage(pdnLayer, decodeContext, decoder);
        }
예제 #19
0
            public DecodeContext(PhotoshopFile.Layer layer, Rectangle bounds)
            {
                Layer         = layer;
                ByteDepth     = Util.BytesFromBitDepth(layer.PsdFile.BitDepth);
                Channels      = layer.Channels.ToIdArray();
                AlphaChannel  = layer.AlphaChannel;
                ColorMode     = layer.PsdFile.ColorMode;
                ColorModeData = layer.PsdFile.ColorModeData;

                // Clip the layer to the specified bounds
                Rectangle = Layer.Rect.IntersectWith(bounds);

                if (layer.Masks != null)
                {
                    LayerMaskContext = GetMaskContext(layer.Masks.LayerMask);
                    UserMaskContext  = GetMaskContext(layer.Masks.UserMask);
                }
            }
예제 #20
0
        /// <summary>
        /// Decode image from Photoshop's channel-separated formats to BGRA.
        /// </summary>
        public static void DecodeImage(BitmapLayer pdnLayer,
                                       PhotoshopFile.Layer psdLayer)
        {
            UnityEngine.Profiling.Profiler.BeginSample("DecodeImage");
            var            decodeContext = new DecodeContext(psdLayer, pdnLayer.Bounds);
            DecodeDelegate decoder       = null;

            if (decodeContext.ByteDepth == 4)
            {
                decoder = GetDecodeDelegate32(decodeContext.ColorMode);
            }
            else
            {
                decoder = GetDecodeDelegate(decodeContext.ColorMode);
            }

            DecodeImage(pdnLayer, decodeContext, decoder);
            UnityEngine.Profiling.Profiler.EndSample();
        }
        /// <summary>
        /// Decode image from Photoshop's channel-separated formats to BGRA.
        /// </summary>
        public static JobHandle DecodeImage(BitmapLayer pdnLayer, PhotoshopFile.Layer psdLayer, JobHandle inputDeps)
        {
            UnityEngine.Profiling.Profiler.BeginSample("DecodeImage");
            var            decodeContext = new DecodeContext(psdLayer, pdnLayer.Bounds);
            DecodeDelegate decoder       = null;
            DecodeType     decoderType   = 0;

            if (decodeContext.ByteDepth == 4)
            {
                decoder = GetDecodeDelegate32(decodeContext.ColorMode, ref decoderType);
            }
            else
            {
                decoder = GetDecodeDelegate(decodeContext.ColorMode, ref decoderType);
            }

            JobHandle jobHandle = DecodeImage(pdnLayer, decodeContext, decoderType, inputDeps);

            UnityEngine.Profiling.Profiler.EndSample();
            return(jobHandle);
        }
예제 #22
0
        private Layer AddNewLayer(PsdFile psdFile, int index)
        {
            PhotoshopFile.Layer psdLayer = new PhotoshopFile.Layer(psdFile)
            {
                BlendModeKey = "norm",
                Visible      = true,

                // Set layer metadata
                Rect    = new System.Drawing.Rectangle(0, 0, psdFile.Columns, psdFile.Rows),
                Name    = "Layer " + index,
                Opacity = 255
            };
            psdLayer.Visible            = true;
            psdLayer.MaskData           = new PhotoshopFile.Layer.Mask(psdLayer);
            psdLayer.BlendingRangesData = new PhotoshopFile.Layer.BlendingRanges(psdLayer);

            // Preserve Unicode layer name as Additional Layer Information
            var luniLayerInfo = new PhotoshopFile.Layer.AdjustmentLayerInfo("luni");
            var luniData      = Encoding.BigEndianUnicode.GetBytes("\u0000\u0000" + psdLayer.Name);

            Util.SetBigEndianInt32(luniData, 0, psdLayer.Name.Length);
            luniLayerInfo.Data = luniData;
            psdLayer.AdjustmentInfo.Add(luniLayerInfo);

            // Store channel metadata
            int layerSize = psdLayer.Rect.Width * psdLayer.Rect.Height;

            for (int i = -1; i < 3; i++)
            {
                PhotoshopFile.Layer.Channel ch = new PhotoshopFile.Layer.Channel((short)i, psdLayer)
                {
                    ImageCompression = ImageCompression.Rle,
                    ImageData        = new byte[layerSize]
                };
            }
            return(psdLayer);
        }
예제 #23
0
        /// <summary>
        /// Decodes a <see cref="Layer"/> into a <see cref="Texture2D"/>.
        /// </summary>
        /// <param name="layer">The <see cref="Layer"/> to decode.</param>
        /// <returns>The <see cref="Texture2D"/> decoded from the layer.</returns>
        public static Texture2D DecodeImage(Layer layer)
        {
            if (layer.Rect.width == 0 || layer.Rect.height == 0)
            {
                return null;
            }

            Texture2D texture = new Texture2D((int)layer.Rect.width, (int)layer.Rect.height, TextureFormat.ARGB32, false);

            Color32[] colors = new Color32[(int)(layer.Rect.width * layer.Rect.height)];

            for (int y = 0; y < layer.Rect.height; ++y)
            {
                int layerRow = y * (int)layer.Rect.width;

                // we need to reverse the Y position for the Unity texture
                int textureRow = ((int)layer.Rect.height - 1 - y) * (int)layer.Rect.width;

                for (int x = 0; x < layer.Rect.width; ++x)
                {
                    int layerPosition = layerRow + x;
                    int texturePosition = textureRow + x;

                    colors[texturePosition] = GetColor(layer, layerPosition);

                    // set the alpha
                    if (layer.SortedChannels.ContainsKey(-2))
                    {
                        byte color = GetColor(layer.MaskData, x, y);
                        colors[texturePosition].a = (byte)(colors[texturePosition].a * color);
                    }
                }
            }

            texture.SetPixels32(colors);
            return texture;
        }
예제 #24
0
 /// <summary>
 /// Exports an art layer as an image file and sprite.  It can also generate text meshes from text layers.
 /// </summary>
 /// <param name="layer">The art layer to export.</param>
 private static void ExportArtLayer(Layer layer)
 {
     if (!layer.IsTextLayer)
     {
         if (LayoutInScene || CreatePrefab)
         {
             // create a sprite from the layer to lay it out in the scene
             if (!UseUnityUI)
             {
                 CreateSpriteGameObject(layer);
             }
             else
             {
                 CreateUIImage(layer);
             }
         }
         else
         {
             // it is not being laid out in the scene, so simply save out the .png file
             CreatePNG(layer);
         }
     }
     else
     {
         // it is a text layer
         if (LayoutInScene || CreatePrefab)
         {
             // create text mesh
             if (!UseUnityUI)
             {
                 CreateTextGameObject(layer);
             }
             else
             {
                 CreateUIText(layer);
             }
         }
     }
 }
예제 #25
0
            public AdjusmentLayerInfo(BinaryReverseReader reader, Layer layer)
            {
                Debug.WriteLine("AdjusmentLayerInfo started at " + reader.BaseStream.Position);

                m_layer = layer;

                var signature = new string(reader.ReadChars(4));
                if (signature != LayerConstants.EightBimSignature)
                {
                    throw new IOException("Could not read an image resource");
                }

                m_key = new string(reader.ReadChars(4));

                uint dataLength = reader.ReadUInt32();
                m_data = reader.ReadBytes((int) dataLength);
            }
예제 #26
0
            ///////////////////////////////////////////////////////////////////////////

            public BlendingRanges(BinaryReverseReader reader, Layer layer)
            {
                Debug.WriteLine("BlendingRanges started at " + reader.BaseStream.Position);

                m_layer = layer;
                int dataLength = reader.ReadInt32();
                if (dataLength <= 0)
                    return;

                m_data = reader.ReadBytes(dataLength);
            }
예제 #27
0
            ///////////////////////////////////////////////////////////////////////////

            internal Mask(BinaryReverseReader reader, Layer layer)
            {
                Debug.WriteLine("Mask started at " + reader.BaseStream.Position);

                m_layer = layer;

                uint maskLength = reader.ReadUInt32();

                if (maskLength <= 0)
                    return;

                long startPosition = reader.BaseStream.Position;

                //-----------------------------------------------------------------------

                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;

                m_defaultColor = reader.ReadByte();

                //-----------------------------------------------------------------------

                byte flags = reader.ReadByte();
                m_flags = new BitVector32(flags);

                //-----------------------------------------------------------------------

                if (maskLength == 36)
                {
                    //var realFlags = new BitVector32(reader.ReadByte());

                    //var realUserMaskBackground = reader.ReadByte();
#if false
                    var y = reader.ReadInt32();
                    var x = reader.ReadInt32();
                    var rect = new Rectangle
                    {
                        Y = y,
                        X = x,
                        Height = reader.ReadInt32() - y,
                        Width = reader.ReadInt32() - x
                    };
#else // this is just reading unused bytes...
                    reader.ReadInt32();
                    reader.ReadInt32();
                    reader.ReadInt32();
                    reader.ReadInt32();
#endif
                }


                // there is other stuff following, but we will ignore this.
                reader.BaseStream.Position = startPosition + maskLength;
            }
예제 #28
0
            internal Channel(BinaryReverseReader reader, Layer layer)
            {
                Debug.WriteLine("Channel started at " + reader.BaseStream.Position);

                m_id = reader.ReadInt16();
                Length = reader.ReadInt32();

                m_layer = layer;
            }
예제 #29
0
        /// <summary>
        /// Decodes a <see cref="Layer"/> into a <see cref="Texture2D"/>.
        /// </summary>
        /// <param name="layer">The <see cref="Layer"/> to decode.</param>
        /// <returns>The <see cref="Texture2D"/> decoded from the layer.</returns>
        public static Texture2D DecodeImage(Layer layer)
        {
            if (layer.Rect.width == 0 || layer.Rect.height == 0)
            {
                return(null);
            }

            Texture2D texture = new Texture2D((int)layer.Rect.width, (int)layer.Rect.height, TextureFormat.ARGB32, false);

            Color32[] colors = new Color32[(int)(layer.Rect.width * layer.Rect.height)];

            for (int y = 0; y < layer.Rect.height; ++y)
            {
                int layerRow = y * (int)layer.Rect.width;

                // we need to reverse the Y position for the Unity texture
                int textureRow = ((int)layer.Rect.height - 1 - y) * (int)layer.Rect.width;

                for (int x = 0; x < layer.Rect.width; ++x)
                {
                    int layerPosition   = layerRow + x;
                    int texturePosition = textureRow + x;

                    colors[texturePosition] = GetColor(layer, layerPosition);

                    //// set the alpha
                    //if(layer.SortedChannels.ContainsKey(-2))
                    //{
                    //    byte color = GetColor(layer.MaskData, x, y);
                    //    colors[texturePosition].a = (byte)(colors[texturePosition].a * color);
                    //}
                }
            }

            texture.SetPixels32(colors);

            if (layer.Is9Slice)
            {
                Regex    reg   = Layer.SLICE_REG;
                Match    match = reg.Match(layer.Name);
                string[] size  = match.Success ? match.ToString().Split(Layer.SLICE_SEPECTOR) : new string[] { "5", "5" };

                int width  = 0;
                int height = 0;
                //l t r b     Border l b r t
                // y w
                if (layer.Border.x == 0 || layer.Border.z == 0)
                {
                    width  = (int)layer.Rect.width;
                    height = int.Parse(size[1]);
                }
                else if (layer.Border.y == 0 || layer.Border.w == 0)
                {
                    height = (int)layer.Rect.height;
                    width  = int.Parse(size[0]);
                }

                if (layer.Border.x != 0 && layer.Border.y != 0 && layer.Border.z != 0 && layer.Border.w != 0 && size.Length >= 2)
                {
                    width  = int.Parse(size[0]);
                    height = int.Parse(size[1]);
                }

                int destWidth  = (int)(layer.Border.x + layer.Border.z + width);
                int destHeight = (int)(layer.Border.y + layer.Border.w + height);

                float scaleFactorX = (texture.width * 1.0f - layer.Border.x - layer.Border.z) / width;
                float scaleFactorY = (texture.height * 1.0f - layer.Border.y - layer.Border.w) / height;

                return(Util9Slice.Create9Slice(texture, new Params((int)layer.Border.x, (int)layer.Border.z, (int)layer.Border.w, (int)layer.Border.y,
                                                                   width, height, destWidth, destHeight, scaleFactorX, scaleFactorY)));
            }

            return(texture);
        }
예제 #30
0
 public Mask(Layer layer)
 {
     Layer      = layer;
     this.flags = new BitVector32();
 }
예제 #31
0
        //////////////////////////////////////////////////////////////////

        internal Channel(short id, Layer layer)
        {
            ID    = id;
            Layer = layer;
        }
예제 #32
0
        ///////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Load Layers Info section, including image data.
        /// </summary>
        /// <param name="reader">PSD reader.</param>
        /// <param name="hasHeader">Whether the Layers Info section has a length header.</param>
        internal void LoadLayers(PsdBinaryReader reader, bool hasHeader)
        {
            Util.DebugMessage(reader.BaseStream, "Load, Begin, Layers Info section");

            long sectionLength = 0;

            if (hasHeader)
            {
                sectionLength = IsLargeDocument
                    ? reader.ReadInt64()
                    : reader.ReadUInt32();

                if (sectionLength <= 0)
                {
                    // The callback may take action when there are 0 layers, so it must
                    // be called even though the Layers Info section is empty.
                    LoadContext.OnLoadLayersHeader(this);
                    Util.DebugMessage(reader.BaseStream, "Load, End, Layers Info section");
                    return;
                }
            }

            var startPosition = reader.BaseStream.Position;
            var numLayers     = reader.ReadInt16();

            // If numLayers < 0, then number of layers is absolute value,
            // and the first alpha channel contains the transparency data for
            // the merged result.
            if (numLayers < 0)
            {
                AbsoluteAlpha = true;
                numLayers     = Math.Abs(numLayers);
            }

            for (int i = 0; i < numLayers; i++)
            {
                var layer = new Layer(reader, this);
                Layers.Add(layer);
            }

            // Header is complete just before loading pixel data
            LoadContext.OnLoadLayersHeader(this);

            //-----------------------------------------------------------------------

            // Load image data for all channels.
            foreach (var layer in Layers)
            {
                Util.DebugMessage(reader.BaseStream,
                                  "Load, Begin, Layer image, layer.Name");
                foreach (var channel in layer.Channels)
                {
                    channel.LoadPixelData(reader);
                }
                Util.DebugMessage(reader.BaseStream,
                                  "Load, End, Layer image, layer.Name");
            }

            // Length is set to 0 when called on higher bitdepth layers.
            if (sectionLength > 0)
            {
                // Layers Info section is documented to be even-padded, but Photoshop
                // actually pads to 4 bytes.
                var endPosition    = startPosition + sectionLength;
                var positionOffset = reader.BaseStream.Position - endPosition;
                Debug.Assert(positionOffset > -4,
                             "LoadLayers did not read the full length of the Layers Info section.");
                Debug.Assert(positionOffset <= 0,
                             "LoadLayers read past the end of the Layers Info section.");


                if (reader.BaseStream.Position < endPosition)
                {
                    reader.BaseStream.Position = endPosition;
                }
            }

            Util.DebugMessage(reader.BaseStream, "Load, End, Layers");
        }
예제 #33
0
 /// <summary>
 /// Returns true if the given <see cref="Layer"/> is marking the start of a layer group.
 /// </summary>
 /// <param name="layer">The <see cref="Layer"/> to check if it's the start of a group</param>
 /// <returns>True if the layer starts a group, otherwise false.</returns>
 private static bool IsStartGroup(Layer layer)
 {
     return layer.IsPixelDataIrrelevant;
 }
예제 #34
0
        /////////////////////////////////////////////////////////////////////////// 

        public static Bitmap DecodeImage(Layer.Mask mask)
        {

            if (mask.Rect.Width == 0 || mask.Rect.Height == 0)
            {
                return null;
            }

            var bitmap = new Bitmap(mask.Rect.Width, mask.Rect.Height, PixelFormat.Format32bppArgb);

#if true // fix remove unsafeness (admittedly slower)
            // TODO: fast mode
            for (var y = 0; y < mask.Rect.Height; y++)
            {
                var rowIndex = y*mask.Rect.Width;
                for (var x = 0; x < mask.Rect.Width; x++)
                {
                    var pos = rowIndex + x;

                    var pixelColor = Color.FromArgb(mask.ImageData[pos], mask.ImageData[pos], mask.ImageData[pos]);

                    // TODO: why is alpha ignored
                    bitmap.SetPixel(x, y, Color.FromArgb(255, pixelColor));
                }
            }
#else
      Layer layer = mask.Layer;
      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 < mask.Rect.Height; y++)
        {
          int rowIndex = y * mask.Rect.Width;
          PixelData* pCurrPixel = (PixelData*)pCurrRowPixel;
          for (int x = 0; x < mask.Rect.Width; x++)
          {
            int pos = rowIndex + x;

            Color pixelColor = Color.FromArgb(mask.ImageData[pos], mask.ImageData[pos], mask.ImageData[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;
        }
예제 #35
0
        /////////////////////////////////////////////////////////////////////////// 

        private static Color GetColor(Layer layer, int pos)
        {
            var c = Color.White;

            switch (layer.PsdFile.ColorMode)
            {
                case PsdFile.ColorModes.RGB:
                    c = Color.FromArgb(layer.SortedChannels[0].ImageData[pos],
                        layer.SortedChannels[1].ImageData[pos],
                        layer.SortedChannels[2].ImageData[pos]);
                    break;
                case PsdFile.ColorModes.CMYK:
                    c = CMYKToRGB(layer.SortedChannels[0].ImageData[pos],
                        layer.SortedChannels[1].ImageData[pos],
                        layer.SortedChannels[2].ImageData[pos],
                        layer.SortedChannels[3].ImageData[pos]);
                    break;
                case PsdFile.ColorModes.Multichannel:
                    c = CMYKToRGB(layer.SortedChannels[0].ImageData[pos],
                        layer.SortedChannels[1].ImageData[pos],
                        layer.SortedChannels[2].ImageData[pos],
                        0);
                    break;
                case PsdFile.ColorModes.Grayscale:
                case PsdFile.ColorModes.Duotone:
                    c = Color.FromArgb(layer.SortedChannels[0].ImageData[pos],
                        layer.SortedChannels[0].ImageData[pos],
                        layer.SortedChannels[0].ImageData[pos]);
                    break;
                case PsdFile.ColorModes.Indexed:
                {
                    var index = (int)layer.SortedChannels[0].ImageData[pos];
                    c = Color.FromArgb(layer.PsdFile.ColorModeData[index],
                        layer.PsdFile.ColorModeData[index + 256],
                        layer.PsdFile.ColorModeData[index + 2*256]);
                }
                    break;
                case PsdFile.ColorModes.Lab:
                {
                    c = LabToRGB(layer.SortedChannels[0].ImageData[pos],
                        layer.SortedChannels[1].ImageData[pos],
                        layer.SortedChannels[2].ImageData[pos]);
                }
                    break;
            }

            if (layer.SortedChannels.ContainsKey(-1))
                c = Color.FromArgb(layer.SortedChannels[-1].ImageData[pos], c);

            return c;
        }
		private static Texture2D CreateTexture(Layer layer)
		{
			if ((int)layer.Rect.width == 0 || (int)layer.Rect.height == 0)
				return null;

			// For possible clip to document functionality
			//int fileWidth = psd.ColumnCount;
			//int fileHeight = psd.RowCount;

			//int textureWidth = (int) layer.Rect.width;
			//int textureHeight = (int) layer.Rect.height;

			Texture2D tex = new Texture2D((int)layer.Rect.width, (int)layer.Rect.height, TextureFormat.RGBA32, true);
			Color32[] pixels = new Color32[tex.width * tex.height];

			Channel red = (from l in layer.Channels where l.ID == 0 select l).First();
			Channel green = (from l in layer.Channels where l.ID == 1 select l).First();
			Channel blue = (from l in layer.Channels where l.ID == 2 select l).First();
			Channel alpha = layer.AlphaChannel;

			for (int i = 0; i < pixels.Length; i++)
			{
				byte r = red.ImageData[i];
				byte g = green.ImageData[i];
				byte b = blue.ImageData[i];
				byte a = 255;

				if (alpha != null)
					a = alpha.ImageData[i];

				int mod = i % tex.width;
				int n = ((tex.width - mod - 1) + i) - mod;
				pixels[pixels.Length - n - 1] = new Color32(r, g, b, a);
			}

			tex.SetPixels32(pixels);
			tex.Apply();

			return tex;
		}
예제 #37
0
        private void BlendOpToBlendModeKey(UserBlendOp op, PhotoshopFile.Layer layer)
        {
            switch (op.ToString())
            {
            case "Normal":
                layer.BlendModeKey = "norm";
                break;

            case "Multiply":
                layer.BlendModeKey = "mul ";
                break;

            case "Additive":
                layer.BlendModeKey = "norm";
                break;

            case "ColorBurn":
                layer.BlendModeKey = "div ";
                break;

            case "ColorDodge":
                layer.BlendModeKey = "idiv";
                break;

            case "Reflect":
                layer.BlendModeKey = "norm";
                break;

            case "Glow":
                layer.BlendModeKey = "norm";
                break;

            case "Overlay":
                layer.BlendModeKey = "over";
                break;

            case "Difference":
                layer.BlendModeKey = "diff";
                break;

            case "Negation":
                layer.BlendModeKey = "norm";
                break;

            case "Lighten":
                layer.BlendModeKey = "lite";
                break;

            case "Darken":
                layer.BlendModeKey = "dark";
                break;

            case "Screen":
                layer.BlendModeKey = "scrn";
                break;

            case "Xor":
                layer.BlendModeKey = "norm";
                break;

            default:
                layer.BlendModeKey = "norm";
                break;
            }
        }
예제 #38
0
            ///////////////////////////////////////////////////////////////////////////

            internal Mask(Layer layer)
            {
                m_layer = layer;
                m_layer.MaskData = this;
            }
예제 #39
0
        private UserBlendOp BlendModeKeyToBlendOp(PhotoshopFile.Layer layer)
        {
            UserBlendOp blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.NormalBlendOp));

            switch (layer.BlendModeKey)
            {
            case "norm":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.NormalBlendOp));
                break;

            case "dark":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.DarkenBlendOp));
                break;

            case "lite":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.LightenBlendOp));
                break;

            case "hue ":
                break;

            case "sat ":
                break;

            case "colr":
                break;

            case "lum ":
                break;

            case "mul ":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.MultiplyBlendOp));
                break;

            case "scrn":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.ScreenBlendOp));
                break;

            case "diss":
                break;

            case "over":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.OverlayBlendOp));
                break;

            case "hLit":
                break;

            case "sLit":
                break;

            case "diff":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.DifferenceBlendOp));
                break;

            case "smud":
                break;

            case "div ":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.ColorDodgeBlendOp));
                break;

            case "idiv":
                blendOp = UserBlendOps.CreateBlendOp(typeof(UserBlendOps.ColorBurnBlendOp));
                break;
            }
            return(blendOp);
        }
예제 #40
0
            ///////////////////////////////////////////////////////////////////////////

            public BlendingRanges(Layer layer)
            {
                m_layer = layer;
                m_layer.BlendingRangesData = this;
            }
예제 #41
0
 /// <summary>
 /// Returns true if the given <see cref="Layer"/> is marking the end of a layer group.
 /// </summary>
 /// <param name="layer">The <see cref="Layer"/> to check if it's the end of a group.</param>
 /// <returns>True if the layer ends a group, otherwise false.</returns>
 private static bool IsEndGroup(Layer layer)
 {
     return layer.Name.Contains("</Layer set>") ||
         layer.Name.Contains("</Layer group>") ||
         (layer.Name == " copy" && layer.Rect.height == 0);
 }
예제 #42
0
 public AdjusmentLayerInfo(string key, Layer layer)
 {
     m_key = key;
     m_layer = layer;
     m_layer.AdjustmentInfo.Add(this);
 }
예제 #43
0
 /// <summary>
 /// Exports a single layer from the tree.
 /// </summary>
 /// <param name="layer">The layer to export.</param>
 private static void ExportLayer(Layer layer)
 {
     layer.Name = MakeNameSafe(layer.Name);
     if (layer.Children.Count > 0 || layer.Rect.width == 0)
     {
         ExportFolderLayer(layer);
     }
     else
     {
         ExportArtLayer(layer);
     }
 }
예제 #44
0
        /// <summary>
        /// Gets the color at the given position in the given <see cref="Layer"/>.
        /// </summary>
        /// <param name="layer">The <see cref="Layer"/> to sample.</param>
        /// <param name="position">The position to sample.</param>
        /// <returns>The sampled color.</returns>
        private static Color32 GetColor(Layer layer, int position)
        {
            Color32 baseColor = new Color32(1, 1, 1, 1);
            switch (layer.PsdFile.ColorMode)
            {
                case ColorModes.Grayscale:
                case ColorModes.Duotone:
                    baseColor = new Color32(layer.SortedChannels[0].ImageData[position], layer.SortedChannels[0].ImageData[position], layer.SortedChannels[0].ImageData[position], 1);
                    break;
                case ColorModes.Indexed:
                    int index = layer.SortedChannels[0].ImageData[position];
                    baseColor = new Color32(layer.PsdFile.ColorModeData[index], layer.PsdFile.ColorModeData[index + 256], layer.PsdFile.ColorModeData[index + 512], 1);
                    break;
                case ColorModes.RGB:
                    baseColor = new Color32(layer.SortedChannels[0].ImageData[position], layer.SortedChannels[1].ImageData[position], layer.SortedChannels[2].ImageData[position], 1);
                    break;
                case ColorModes.CMYK:
                    baseColor = CMYKToRGB(layer.SortedChannels[0].ImageData[position], layer.SortedChannels[1].ImageData[position], layer.SortedChannels[2].ImageData[position], layer.SortedChannels[3].ImageData[position]);
                    break;
                case ColorModes.Multichannel:
                    baseColor = CMYKToRGB(layer.SortedChannels[0].ImageData[position], layer.SortedChannels[1].ImageData[position], layer.SortedChannels[2].ImageData[position], 0);
                    break;
                case ColorModes.Lab:
                    baseColor = LabToRGB(layer.SortedChannels[0].ImageData[position], layer.SortedChannels[1].ImageData[position], layer.SortedChannels[2].ImageData[position]);
                    break;
            }

            // set the alpha
            if (layer.SortedChannels.ContainsKey(-1))
            {
                baseColor.a = layer.SortedChannels[-1].ImageData[position];
            }

            return baseColor;
        }
예제 #45
0
        /// <summary>
        /// Creates a layer for each channel in a multichannel image.
        /// </summary>
        private static void CreateLayersFromChannels(PsdFile psdFile)
        {
            if (psdFile.ColorMode != PsdColorMode.Multichannel)
            {
                throw new Exception("Not a multichannel image.");
            }
            if (psdFile.Layers.Count > 0)
            {
                throw new PsdInvalidException("Multichannel image should not have layers.");
            }

            // Get alpha channel names, preferably in Unicode.
            var alphaChannelNames = (AlphaChannelNames)psdFile.ImageResources
                                    .Get(ResourceID.AlphaChannelNames);
            var unicodeAlphaNames = (UnicodeAlphaNames)psdFile.ImageResources
                                    .Get(ResourceID.UnicodeAlphaNames);

            if ((alphaChannelNames == null) && (unicodeAlphaNames == null))
            {
                throw new PsdInvalidException("No channel names found.");
            }

            var channelNames = (unicodeAlphaNames != null)
                ? unicodeAlphaNames.ChannelNames
                : alphaChannelNames.ChannelNames;
            var channels = psdFile.BaseLayer.Channels;

            if (channels.Count > channelNames.Count)
            {
                throw new PsdInvalidException("More channels than channel names.");
            }

            // Channels are stored from top to bottom, but layers are stored from
            // bottom to top.
            for (int i = channels.Count - 1; i >= 0; i--)
            {
                var channel     = channels[i];
                var channelName = channelNames[i];

                // Copy metadata over from base layer
                var layer = new PhotoshopFile.Layer(psdFile);
                layer.Rect               = psdFile.BaseLayer.Rect;
                layer.Visible            = true;
                layer.Masks              = new MaskInfo();
                layer.BlendingRangesData = new BlendingRanges(layer);

                // We do not attempt to reconstruct the appearance of the image, but
                // only to provide access to the channels image data.
                layer.Name         = channelName;
                layer.BlendModeKey = PsdBlendMode.Darken;
                layer.Opacity      = 255;

                // Copy channel image data into the new grayscale layer
                var layerChannel = new Channel(0, layer);
                layerChannel.ImageCompression = channel.ImageCompression;
                layerChannel.ImageData        = channel.ImageData;
                layer.Channels.Add(layerChannel);

                psdFile.Layers.Add(layer);
            }
        }
예제 #46
0
        public static void Save(Document input, Stream output, PsdSaveConfigToken psdToken,
                                Surface scratchSurface, ProgressEventHandler progressCallback)
        {
            var psdVersion = ((input.Height > 30000) || (input.Width > 30000))
        ? PsdFileVersion.PsbLargeDocument
        : PsdFileVersion.Psd;
            var psdFile = new PsdFile(psdVersion);

            psdFile.RowCount    = input.Height;
            psdFile.ColumnCount = input.Width;

            // We only save in RGBA format, 8 bits per channel, which corresponds to
            // Paint.NET's internal representation.

            psdFile.ChannelCount     = 4;
            psdFile.ColorMode        = PsdColorMode.RGB;
            psdFile.BitDepth         = 8;
            psdFile.Resolution       = GetResolutionInfo(input);
            psdFile.ImageCompression = psdToken.RleCompress
        ? ImageCompression.Rle
        : ImageCompression.Raw;

            // Treat the composite image as another layer when reporting progress.
            var progress        = new ProgressNotifier(progressCallback);
            var percentPerLayer = percentStoreImages
                                  / (input.Layers.Count + 1);

            // Render the composite image.  This operation is parallelized within
            // Paint.NET using its own private thread pool.
            using (var ra = new RenderArgs(scratchSurface))
            {
                input.Flatten(scratchSurface);
                progress.Notify(percentRenderComposite);
            }

            // Delegate to store the composite
            Action storeCompositeAction = () =>
            {
                // Allocate space for the composite image data
                int imageSize = psdFile.RowCount * psdFile.ColumnCount;
                for (short i = 0; i < psdFile.ChannelCount; i++)
                {
                    var channel = new Channel(i, psdFile.BaseLayer);
                    channel.ImageData        = new byte[imageSize];
                    channel.ImageCompression = psdFile.ImageCompression;
                    psdFile.BaseLayer.Channels.Add(channel);
                }

                var channelsArray = psdFile.BaseLayer.Channels.ToIdArray();
                StoreLayerImage(channelsArray, channelsArray[3],
                                scratchSurface, psdFile.BaseLayer.Rect);

                progress.Notify(percentPerLayer);
            };

            // Delegate to store the layers
            Action storeLayersAction = () =>
            {
                // LayerList is an ArrayList, so we have to cast to get a generic
                // IEnumerable that works with LINQ.
                var pdnLayers = input.Layers.Cast <BitmapLayer>();

                // Create folders/groups before actual image data will be saved.
                var layerInfos = PrepareLayers(pdnLayers, psdToken.SaveLayers);


                var psdLayers = layerInfos.AsParallel().AsOrdered().Select(pdnLayer =>
                {
                    var psdLayer = new PhotoshopFile.Layer(psdFile);
                    StoreLayer(pdnLayer, psdLayer, psdToken);

                    progress.Notify(percentPerLayer);
                    return(psdLayer);
                });
                psdFile.Layers.AddRange(psdLayers);
            };

            // Process composite and layers in parallel
            Parallel.Invoke(storeCompositeAction, storeLayersAction);

            psdFile.Save(output, Encoding.Default);
        }
예제 #47
0
        /////////////////////////////////////////////////////////////////////////// 

        public static Bitmap DecodeImage(Layer layer)
        {
            if (layer.Rect.Width == 0 || layer.Rect.Height == 0)
            {
                return null;
            }

            var bitmap = new Bitmap(layer.Rect.Width, layer.Rect.Height, PixelFormat.Format32bppArgb);

#if TEST
      for (int y = 0; y < layer.Rect.Height; y++)
      {
        int rowIndex = y * layer.Rect.Width;

        for (int x = 0; x < layer.Rect.Width; x++)
        {
          int pos = rowIndex + x;

          //Color pixelColor=GetColor(psdFile,pos);
          Color pixelColor = Color.FromArgb(x % 255, Color.ForestGreen);// 255, 128, 0);

          bitmap.SetPixel(x, y, pixelColor);
        }
      }

#else

#if true // fix remove unsafeness (admittedly slower)
            // TODO: fast mode
            for (var y = 0; y < layer.Rect.Height; y++)
            {
                var rowIndex = y * layer.Rect.Width;
                for (var x = 0; x < layer.Rect.Width; x++)
                {
                    var pos = rowIndex + x;

                    var pixelColor = GetColor(layer, pos);

                    if (layer.SortedChannels.ContainsKey(-2))
                    {
                        var maskAlpha = GetColor(layer.MaskData, x, y);
                        int oldAlpha = pixelColor.A;

                        var newAlpha = (oldAlpha * maskAlpha) / 255;
                        pixelColor = Color.FromArgb(newAlpha, pixelColor);
                    }
                    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 < layer.Rect.Height; y++)
        {
          int rowIndex = y * layer.Rect.Width;
          PixelData* pCurrPixel = (PixelData*)pCurrRowPixel;
          for (int x = 0; x < layer.Rect.Width; x++)
          {
            int pos = rowIndex + x;

            Color pixelColor = GetColor(layer, pos);

            if (layer.SortedChannels.ContainsKey(-2))
            {
                int maskAlpha = GetColor(layer.MaskData, x, y);
                int oldAlpha = pixelColor.A;

                int newAlpha = (oldAlpha * maskAlpha) / 255;
                pixelColor = Color.FromArgb(newAlpha,pixelColor);
            }

            pCurrPixel->Alpha = pixelColor.A;
            pCurrPixel->Red = pixelColor.R;
            pCurrPixel->Green = pixelColor.G;
            pCurrPixel->Blue = pixelColor.B;

            pCurrPixel += 1;
          }
          pCurrRowPixel += bd.Stride;
        }
      }

      bitmap.UnlockBits(bd);
#endif
#endif

            return bitmap;
        }
예제 #48
0
 ///////////////////////////////////////////////////////////////////////////
 public BlendingRanges(Layer layer)
 {
     Layer = layer;
     Data = new byte[0];
 }
예제 #49
0
파일: Mask.cs 프로젝트: hgrandry/Mgx
 public Mask(Layer layer)
 {
     Layer = layer;
     this.flags = new BitVector32();
 }
예제 #50
0
        protected override void OnSave(Document input, System.IO.Stream output,
                                       SaveConfigToken token, Surface scratchSurface, ProgressEventHandler callback)
        {
            PsdSaveConfigToken psdToken = (PsdSaveConfigToken)token;
            PsdFile            psdFile  = new PsdFile();

            //-----------------------------------------------------------------------

            psdFile.Rows    = input.Height;
            psdFile.Columns = input.Width;

            // we have an Alpha channel which will be saved,
            // we have to add this to our image resources
            psdFile.Channels = 4;

            // for now we oly save the images as RGB
            psdFile.ColorMode = PsdFile.ColorModes.RGB;

            psdFile.Depth = 8;

            //-----------------------------------------------------------------------
            // no color mode Data

            //-----------------------------------------------------------------------

            ResolutionInfo resInfo = new ResolutionInfo();

            resInfo.HeightUnit = ResolutionInfo.Unit.In;
            resInfo.WidthUnit  = ResolutionInfo.Unit.In;

            if (input.DpuUnit == MeasurementUnit.Inch)
            {
                resInfo.HResUnit = ResolutionInfo.ResUnit.PxPerInch;
                resInfo.VResUnit = ResolutionInfo.ResUnit.PxPerInch;

                resInfo.HRes = (short)input.DpuX;
                resInfo.VRes = (short)input.DpuY;
            }
            else
            {
                resInfo.HResUnit = ResolutionInfo.ResUnit.PxPerCent;
                resInfo.VResUnit = ResolutionInfo.ResUnit.PxPerCent;


                resInfo.HRes = (short)(input.DpuX / 2.54);
                resInfo.VRes = (short)(input.DpuY / 2.54);
            }

            psdFile.Resolution = resInfo;
            //-----------------------------------------------------------------------

            psdFile.ImageCompression = psdToken.RleCompress ? ImageCompression.Rle : ImageCompression.Raw;

            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];
            }

            using (RenderArgs ra = new RenderArgs(scratchSurface))
            {
                input.Flatten(scratchSurface);
            }

            unsafe
            {
                for (int y = 0; y < psdFile.Rows; y++)
                {
                    int        rowIndex = y * psdFile.Columns;
                    ColorBgra *srcRow   = scratchSurface.GetRowAddress(y);
                    ColorBgra *srcPixel = srcRow;

                    for (int x = 0; x < psdFile.Columns; x++)
                    {
                        int pos = rowIndex + x;

                        psdFile.ImageData[0][pos] = srcPixel->R;
                        psdFile.ImageData[1][pos] = srcPixel->G;
                        psdFile.ImageData[2][pos] = srcPixel->B;
                        psdFile.ImageData[3][pos] = srcPixel->A;
                        srcPixel++;
                    }
                }
            }

            PaintDotNet.Threading.PrivateThreadPool threadPool = new PaintDotNet.Threading.PrivateThreadPool();
            foreach (BitmapLayer layer in input.Layers)
            {
                PhotoshopFile.Layer psdLayer = new PhotoshopFile.Layer(psdFile);
                BlendOpToBlendModeKey(layer.BlendOp, psdLayer);

                SaveLayerPixelsContext slc          = new SaveLayerPixelsContext(layer, psdFile, input, psdLayer, psdToken);
                WaitCallback           waitCallback = new WaitCallback(slc.SaveLayer);
                threadPool.QueueUserWorkItem(waitCallback);
            }
            threadPool.Drain();

            psdFile.Save(output);
        }
예제 #51
0
        /////////////////////////////////////////////////////////////////////////// 

        private static int GetColor(Layer.Mask mask, int x, int y)
        {
            int c = 255;

            if (mask.PositionIsRelative)
            {
                x -= mask.Rect.X;
                y -= mask.Rect.Y;
            }
            else
            {
                x = (x + mask.Layer.Rect.X) - mask.Rect.X;
                y = (y + mask.Layer.Rect.Y) - mask.Rect.Y;
            }

            if (y >= 0 && y < mask.Rect.Height &&
                x >= 0 && x < mask.Rect.Width)
            {
                var pos = y * mask.Rect.Width + x;
                if (pos < mask.ImageData.Length)
                {
                    c = mask.ImageData[pos];
                }
                else
                {
                    c = 255;
                }
            }

            return c;
        }
예제 #52
0
        /// <summary>
        /// Exports a <see cref="Layer"/> that is a folder containing child layers.
        /// </summary>
        /// <param name="layer">The layer that is a folder.</param>
        private static void ExportFolderLayer(Layer layer)
        {
            if (layer.Name.ContainsIgnoreCase("|Button"))
            {
                layer.Name = layer.Name.ReplaceIgnoreCase("|Button", string.Empty);

                if (UseUnityUI)
                {
                    CreateUIButton(layer);
                }
                else
                {
                    ////CreateGUIButton(layer);
                }
            }
            else if (layer.Name.ContainsIgnoreCase("|Animation"))
            {
                layer.Name = layer.Name.ReplaceIgnoreCase("|Animation", string.Empty);

                string oldPath = currentPath;
                GameObject oldGroupObject = currentGroupGameObject;

                currentPath = Path.Combine(currentPath, layer.Name.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)[0]);
                Directory.CreateDirectory(currentPath);

                if (UseUnityUI)
                {
                    ////CreateUIAnimation(layer);
                }
                else
                {
                    CreateAnimation(layer);
                }

                currentPath = oldPath;
                currentGroupGameObject = oldGroupObject;
            }
            else
            {
                // it is a "normal" folder layer that contains children layers
                string oldPath = currentPath;
                GameObject oldGroupObject = currentGroupGameObject;

                currentPath = Path.Combine(currentPath, layer.Name);
                Directory.CreateDirectory(currentPath);

                if (LayoutInScene || CreatePrefab)
                {
                    currentGroupGameObject = new GameObject(layer.Name);
                    currentGroupGameObject.transform.parent = oldGroupObject.transform;
                }

                ExportTree(layer.Children);

                currentPath = oldPath;
                currentGroupGameObject = oldGroupObject;
            }
        }
예제 #53
0
        ///////////////////////////////////////////////////////////////////////////

        public BlendingRanges(Layer layer)
        {
            Layer = layer;
            Data  = new byte[0];
        }
예제 #54
0
파일: Mask.cs 프로젝트: hgrandry/Mgx
        public MaskInfo(PsdBinaryReader reader, Layer layer)
        {
            Debug.WriteLine("MaskInfo started at " + reader.BaseStream.Position.ToString(CultureInfo.InvariantCulture));

            var maskLength = reader.ReadUInt32();
            if (maskLength <= 0)
                return;

            var startPosition = reader.BaseStream.Position;
            var endPosition = startPosition + maskLength;

            // Read layer mask
            var rectangle = reader.ReadRectangle();
            var backgroundColor = reader.ReadByte();
            var flagsByte = reader.ReadByte();
            LayerMask = new Mask(layer, rectangle, backgroundColor, new BitVector32(flagsByte));

            // User mask is supplied separately when there is also a vector mask.
            if (maskLength == 36)
            {
                var userFlagsByte = reader.ReadByte();
                var userBackgroundColor = reader.ReadByte();
                var userRectangle = reader.ReadRectangle();
                UserMask = new Mask(layer, userRectangle, userBackgroundColor,
                  new BitVector32(userFlagsByte));
            }

            // 20-byte mask data will end with padding.
            reader.BaseStream.Position = endPosition;
        }
예제 #55
0
            //////////////////////////////////////////////////////////////////

            internal Channel(short id, Layer layer)
            {
                m_id = id;
                m_layer = layer;
                m_layer.Channels.Add(this);
                m_layer.SortedChannels.Add(ID, this);
            }
예제 #56
0
        public static void SaveLayerPixels(BitmapLayer layer, PsdFile psdFile,
                                           Document input, PhotoshopFile.Layer psdLayer, PsdSaveConfigToken psdToken)
        {
            Surface surface = layer.Surface;

            int rectLeft   = input.Width;
            int rectTop    = input.Height;
            int rectRight  = 0;
            int rectBottom = 0;

            // Determine the real size of this layer, i.e., the smallest rectangle
            // that includes all all non-invisible pixels
            unsafe
            {
                for (int y = 0; y < psdFile.Rows; y++)
                {
                    int        rowIndex = y * psdFile.Columns;
                    ColorBgra *srcRow   = surface.GetRowAddress(y);
                    ColorBgra *srcPixel = srcRow;

                    for (int x = 0; x < psdFile.Columns; x++)
                    {
                        int pos = rowIndex + x;

                        // Found a non-transparent pixel, potentially increase the size of the rectangle
                        if (srcPixel->A > 0)
                        {
                            // Expand the rectangle
                            if (x < rectLeft)
                            {
                                rectLeft = x;
                            }
                            if (x > rectRight)
                            {
                                rectRight = x;
                            }
                            if (y < rectTop)
                            {
                                rectTop = y;
                            }
                            if (y > rectBottom)
                            {
                                rectBottom = y;
                            }
                        }

                        srcPixel++;
                    }
                }
            }

            psdLayer.Rect               = new Rectangle(rectLeft, rectTop, rectRight - rectLeft + 1, rectBottom - rectTop + 1);
            psdLayer.Name               = layer.Name;
            psdLayer.Opacity            = layer.Opacity;
            psdLayer.Visible            = layer.Visible;
            psdLayer.MaskData           = new PhotoshopFile.Layer.Mask(psdLayer);
            psdLayer.BlendingRangesData = new PhotoshopFile.Layer.BlendingRanges(psdLayer);

            int layerSize = psdLayer.Rect.Width * psdLayer.Rect.Height;

            for (int i = -1; i < 3; i++)
            {
                PhotoshopFile.Layer.Channel ch = new PhotoshopFile.Layer.Channel((short)i, psdLayer);

                ch.ImageCompression = psdToken.RleCompress ? ImageCompression.Rle : ImageCompression.Raw;
                ch.ImageData        = new byte[layerSize];
            }

            var channels     = psdLayer.ChannelsArray;
            var alphaChannel = psdLayer.AlphaChannel;

            unsafe
            {
                int rowIndex = 0;
                for (int y = 0; y < psdLayer.Rect.Height; y++)
                {
                    ColorBgra *srcRow   = surface.GetRowAddress(y + psdLayer.Rect.Top);
                    ColorBgra *srcPixel = srcRow + psdLayer.Rect.Left;

                    for (int x = 0; x < psdLayer.Rect.Width; x++)
                    {
                        int pos = rowIndex + x;

                        channels[0].ImageData[pos]  = srcPixel->R;
                        channels[1].ImageData[pos]  = srcPixel->G;
                        channels[2].ImageData[pos]  = srcPixel->B;
                        alphaChannel.ImageData[pos] = srcPixel->A;
                        srcPixel++;
                    }
                    rowIndex += psdLayer.Rect.Width;
                }
            }
        }
예제 #57
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Channel"/> class.
 /// </summary>
 /// <param name="reader">The reader to use to initialize the instance.</param>
 /// <param name="layer">The layer this channel belongs to.</param>
 internal Channel(BinaryReverseReader reader, Layer layer)
 {
     ID = reader.ReadInt16();
     Length = reader.ReadInt32();
     Layer = layer;
 }