/// <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); }
/// <summary> /// Prepare Paint.NET's flat layer list to be exported as Photoshop layers. /// Indicate where layer sections begin and end and create missing layers while user can break the structure. /// </summary> private static IEnumerable <BitmapLayerInfo> PrepareLayers(IEnumerable <BitmapLayer> paintLayers, bool saveGroupLayers) { var toReturn = new List <BitmapLayerInfo>(); var layer = paintLayers.FirstOrDefault(); var openedGroupsCount = 0; var reversed = paintLayers.Reverse(); foreach (var paintLayer in reversed) { var layerInfo = new BitmapLayerInfo(); layerInfo.Name = paintLayer.Name; layerInfo.Layer = paintLayer; // Render as default image layerInfo.RenderAsRegularLayer = true; var isGroupLayerStart = false; var layerGroup = string.Empty; if (saveGroupLayers && CheckIsGroupLayer(paintLayer, out isGroupLayerStart, out layerGroup)) { layerInfo.Name = layerGroup ?? "Layer"; layerInfo.IsGroupStart = isGroupLayerStart; layerInfo.IsGroupEnd = !isGroupLayerStart; layerInfo.RenderAsRegularLayer = false; if (isGroupLayerStart) { openedGroupsCount++; } else if (layerInfo.IsGroupEnd) { if (openedGroupsCount == 0) { // Structure is broken. Close layer tag is before any other start. // In this case we should render group as regular layer. layerInfo.RenderAsRegularLayer = true; } else { openedGroupsCount--; } } } toReturn.Add(layerInfo); } toReturn.Reverse(); // Add missing close groups. if (openedGroupsCount > 0) { for (int count = 0; count < openedGroupsCount; count++) { var emptyLayer = new BitmapLayer(layer.Width, layer.Height); var layerInfo = new BitmapLayerInfo() { Layer = emptyLayer, IsGroupEnd = true, Name = "Layer end" }; toReturn.Insert(0, layerInfo); } } return(toReturn); }