public Neuron(Layer OwnerLayer) { Random R = new Random(DateTime.Now.Millisecond); _OwnerLayer = OwnerLayer; _Result = 0f; _Bias = R.Next(-100, 100) / 100; NeuronType = OwnerLayer.LAYERTYPE; }
public static Layer Parse(JsonReader reader, LottieComposition composition) { string layerName = null; Layer.LayerType layerType = Layer.LayerType.Unknown; string refId = null; long layerId = 0; int solidWidth = 0; int solidHeight = 0; Color solidColor; int preCompWidth = 0; int preCompHeight = 0; long parentId = -1; float timeStretch = 1f; float startFrame = 0f; float inFrame = 0f; float outFrame = 0f; string cl = null; Layer.MatteType matteType = Layer.MatteType.None; AnimatableTransform transform = null; AnimatableTextFrame text = null; AnimatableTextProperties textProperties = null; AnimatableFloatValue timeRemapping = null; List <Mask> masks = new List <Mask>(); List <IContentModel> shapes = new List <IContentModel>(); reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "nm": layerName = reader.NextString(); break; case "ind": layerId = reader.NextInt(); break; case "refId": refId = reader.NextString(); break; case "ty": int layerTypeInt = reader.NextInt(); if (layerTypeInt < (int)Layer.LayerType.Unknown) { layerType = (Layer.LayerType)layerTypeInt; } else { layerType = Layer.LayerType.Unknown; } break; case "parent": parentId = reader.NextInt(); break; case "sw": solidWidth = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "sh": solidHeight = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "sc": solidColor = Utils.Utils.GetSolidColorBrush(reader.NextString()); break; case "ks": transform = AnimatableTransformParser.Parse(reader, composition); break; case "tt": matteType = (Layer.MatteType)reader.NextInt(); break; case "masksProperties": reader.BeginArray(); while (reader.HasNext()) { masks.Add(MaskParser.Parse(reader, composition)); } reader.EndArray(); break; case "shapes": reader.BeginArray(); while (reader.HasNext()) { var shape = ContentModelParser.Parse(reader, composition); if (shape != null) { shapes.Add(shape); } } reader.EndArray(); break; case "t": reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "d": text = AnimatableValueParser.ParseDocumentData(reader, composition); break; case "a": reader.BeginArray(); if (reader.HasNext()) { textProperties = AnimatableTextPropertiesParser.Parse(reader, composition); } while (reader.HasNext()) { reader.SkipValue(); } reader.EndArray(); break; default: reader.SkipValue(); break; } } reader.EndObject(); break; case "ef": reader.BeginArray(); List <string> effectNames = new List <string>(); while (reader.HasNext()) { reader.BeginObject(); while (reader.HasNext()) { switch (reader.NextName()) { case "nm": effectNames.Add(reader.NextString()); break; default: reader.SkipValue(); break; } } reader.EndObject(); } reader.EndArray(); composition.AddWarning("Lottie doesn't support layer effects. If you are using them for " + " fills, strokes, trim paths etc. then try adding them directly as contents " + " in your shape. Found: " + effectNames); break; case "sr": timeStretch = reader.NextDouble(); break; case "st": startFrame = reader.NextDouble(); break; case "w": preCompWidth = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "h": preCompHeight = (int)(reader.NextInt() * Utils.Utils.DpScale()); break; case "ip": inFrame = reader.NextDouble(); break; case "op": outFrame = reader.NextDouble(); break; case "tm": timeRemapping = AnimatableValueParser.ParseFloat(reader, composition, false); break; case "cl": cl = reader.NextString(); break; default: reader.SkipValue(); break; } } reader.EndObject(); // Bodymovin pre-scales the in frame and out frame by the time stretch. However, that will // cause the stretch to be double counted since the in out animation gets treated the same // as all other animations and will have stretch applied to it again. inFrame /= timeStretch; outFrame /= timeStretch; List <Keyframe <float?> > inOutKeyframes = new List <Keyframe <float?> >(); // Before the in frame if (inFrame > 0) { Keyframe <float?> preKeyframe = new Keyframe <float?>(composition, 0f, 0f, null, 0f, inFrame); inOutKeyframes.Add(preKeyframe); } // The + 1 is because the animation should be visible on the out frame itself. outFrame = (outFrame > 0 ? outFrame : composition.EndFrame) + 1; Keyframe <float?> visibleKeyframe = new Keyframe <float?>(composition, 1f, 1f, null, inFrame, outFrame); inOutKeyframes.Add(visibleKeyframe); Keyframe <float?> outKeyframe = new Keyframe <float?>(composition, 0f, 0f, null, outFrame, float.MaxValue); inOutKeyframes.Add(outKeyframe); if (layerName.EndsWith(".ai") || "ai".Equals(cl)) { composition.AddWarning("Convert your Illustrator layers to shape layers."); } return(new Layer(shapes, composition, layerName, layerId, layerType, parentId, refId, masks, transform, solidWidth, solidHeight, solidColor, timeStretch, startFrame, preCompWidth, preCompHeight, text, textProperties, inOutKeyframes, matteType, timeRemapping)); }
YamlScalar Scalar(Layer.LayerType type) => Scalar(type, type.ToString());
//TODO: This only works with local files. Add a way for it to support internet images. public bool UpdatePreview(Layer.LayerType layerType) { var backdrop = new Bitmap(DataAccess.Properties.Resources.LayerPreviewImage, PreviewSize, PreviewSize); // If no file has been specified, we dont have anything to show preview-wise if (string.IsNullOrWhiteSpace(File)) { Image = BitmapHelper.ConvertBitmapToImageSource(backdrop); return(true); } Bitmap image; //Image in its actual size var loadedImage = ImageLoader.TryLoadBitmapFromFile(File, out image); if (!loadedImage) { return(false); } Bitmap imageSmall = BitmapHelper.ConvertToPixelFormat_32bppArgb(new Bitmap(image, PreviewSize, PreviewSize)); //Image scaled to the size of the preview. Bitmap mask; switch (layerType) { case Layer.LayerType.Border: switch (MaskType) { case MaskTypes.None: BitmapHelper.AddLayerToImage(backdrop, imageSmall); break; case MaskTypes.User: //If the user hasn't specified a mask, dont attempt to load it. Just show image without a mask. if (string.IsNullOrWhiteSpace(Mask)) { BitmapHelper.AddLayerToImage(backdrop, imageSmall); break; } var loadedMask = ImageLoader.TryLoadBitmapFromFile(Mask, out mask, PreviewSize, PreviewSize); if (!loadedMask) { return(false); } BitmapHelper.ApplyMaskToImage(backdrop, mask); //For Border-layers we apply the mask to the backdrop BitmapHelper.AddLayerToImage(backdrop, imageSmall); break; case MaskTypes.Autogenerated: var generatedMask = BitmapHelper.GenerateMask(image); //Generate mask for full-size image, and then scale it down afterward so we have as much detail as possible var generatedMaskSmall = BitmapHelper.ConvertToPixelFormat_32bppArgb(new Bitmap(generatedMask, PreviewSize, PreviewSize)); BitmapHelper.ApplyMaskToImage(backdrop, generatedMaskSmall); BitmapHelper.AddLayerToImage(backdrop, imageSmall); GeneratedMask = generatedMask; break; default: throw new ArgumentOutOfRangeException(); } break; case Layer.LayerType.Overlay: switch (MaskType) { case MaskTypes.None: BitmapHelper.AddLayerToImage(backdrop, imageSmall); break; case MaskTypes.User: //If the user hasn't specified a mask, dont attempt to load it. Just show image without a mask. if (string.IsNullOrWhiteSpace(Mask)) { BitmapHelper.AddLayerToImage(backdrop, imageSmall); break; } var loadedMask = ImageLoader.TryLoadBitmapFromFile(Mask, out mask, PreviewSize, PreviewSize); if (!loadedMask) { return(false); } BitmapHelper.ApplyMaskToImage(imageSmall, mask); //For Overlay-layers we apply the mask to the overlay BitmapHelper.AddLayerToImage(backdrop, imageSmall); break; case MaskTypes.Autogenerated: throw new InvalidEnumArgumentException("Overlays cant have autogenerated masks"); default: throw new ArgumentOutOfRangeException(); } break; default: throw new ArgumentOutOfRangeException(nameof(layerType), layerType, null); } Image = BitmapHelper.ConvertBitmapToImageSource(backdrop); return(true); }
/// <summary> /// Creates a new layer by copying the referenced paths into the custom layer directory /// and creates a .json file representing the layer at the layer path. /// </summary> /// <param name="name">The name of the layer. (Not the name of the resulting layer-file)</param> /// <param name="filepath">A path to the main image file</param> /// <param name="maskpath">A path to the mask file</param> /// <param name="type">The layer type</param> public static bool CreateNewLayer(string name, string filepath, string maskpath, Layer.LayerType type) { var layer = new Layer { File = filepath, Mask = maskpath, Name = name, Type = type }; var absoluteOutputFolder = Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), LayerDirectory), CustomDirectory); if (!Directory.Exists(absoluteOutputFolder)) { Directory.CreateDirectory(absoluteOutputFolder); } string filedest = null; string maskdest = null; string jsondest = null; try { filedest = Path.Combine(absoluteOutputFolder, Path.GetFileName(filepath)); if (!File.Exists(filedest)) { File.Copy(filepath, filedest); } layer.File = Path.Combine(CustomDirectory, Path.GetFileName(filedest)); //relative path if (!string.IsNullOrEmpty(maskpath)) { maskdest = Path.Combine(absoluteOutputFolder, Path.GetFileName(maskpath)); if (!File.Exists(maskdest)) { File.Copy(maskpath, maskdest); } layer.Mask = Path.Combine(CustomDirectory, Path.GetFileName(maskdest)); //relative path } else { layer.Mask = string.Empty; } jsondest = Path.Combine(Directory.GetCurrentDirectory(), LayerDirectory); jsondest = Path.Combine(jsondest, $"{Guid.NewGuid()}.json"); File.WriteAllText(jsondest, JsonConvert.SerializeObject(layer)); } catch (Exception e) when(e is ArgumentException || e is IOException) { if (filedest != null && File.Exists(filedest)) { File.Delete(filedest); } if (maskdest != null && File.Exists(maskdest)) { File.Delete(maskdest); } if (jsondest != null && File.Exists(jsondest)) { File.Delete(jsondest); } return(false); } return(true); }