static Texture[] ToTextureArray(GifMetadata gifMetadata, GifFrameMetadata[] gifFrameMetadata, Color32[][] imageData) { if (gifFrameMetadata == null || imageData == null) { return(new Texture[0]); } var frames = new Texture[imageData.Length]; int width = gifMetadata.width, height = gifMetadata.height; for (int i = 0; i < imageData.Length; i++) { // Create a texture and fill it with pixel data. Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false); tex.hideFlags = HideFlags.HideAndDontSave; tex.wrapMode = TextureWrapMode.Clamp; tex.filterMode = FilterMode.Bilinear; tex.anisoLevel = 0; tex.SetPixels32(imageData[i]); tex.Apply(false, false); frames[i] = tex; } return(frames); }
public void Identify_VerifyRepeatCount(string imagePath, uint repeatCount) { var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { var decoder = new GifDecoder(); IImageInfo image = decoder.Identify(Configuration.Default, stream); GifMetadata meta = image.Metadata.GetGifMetadata(); Assert.Equal(repeatCount, meta.RepeatCount); } }
public void Decode_CanDecodeLargeTextComment() { var options = new GifDecoder(); var testFile = TestFile.Create(TestImages.Gif.LargeComment); using (Image <Rgba32> image = testFile.CreateRgba32Image(options)) { GifMetadata metadata = image.Metadata.GetGifMetadata(); Assert.Equal(2, metadata.Comments.Count); Assert.Equal(new string('c', 349), metadata.Comments[0]); Assert.Equal("ImageSharp", metadata.Comments[1]); } }
public void Decode_IgnoreMetadataIsTrue_CommentsAreIgnored() { var options = new GifDecoder { IgnoreMetadata = true }; var testFile = TestFile.Create(TestImages.Gif.Rings); using (Image <Rgba32> image = testFile.CreateRgba32Image(options)) { GifMetadata metadata = image.Metadata.GetGifMetadata(); Assert.Equal(0, metadata.Comments.Count); } }
static AnimatedClip ToAnimatedClip(GifMetadata gifMetadata, GifFrameMetadata[] gifFrameMetadata, Color32[][] imageData) { if (gifFrameMetadata == null) { return(null); } int width = gifMetadata.width, height = gifMetadata.height; // pre-display delay is in 0.01sec units // we're not supporting delay time variance so just take the value of first frame. int fps = (int)(1 / (gifFrameMetadata[0].delayTime * 0.01f)); var frames = ToTextureArray(gifMetadata, gifFrameMetadata, imageData); return(frames != null && frames.Length > 0 ? new AnimatedClip(width, height, fps, frames) : null); }
public void Decode_IgnoreMetadataIsFalse_CommentsAreRead() { var options = new GifDecoder { IgnoreMetadata = false }; var testFile = TestFile.Create(TestImages.Gif.Rings); using (Image <Rgba32> image = testFile.CreateRgba32Image(options)) { GifMetadata metadata = image.Metadata.GetGifMetadata(); Assert.Equal(1, metadata.Comments.Count); Assert.Equal("ImageSharp", metadata.Comments[0]); } }
public void NonMutatingEncodePreservesPaletteCount() { using (var inStream = new MemoryStream(TestFile.Create(TestImages.Gif.Leo).Bytes)) using (var outStream = new MemoryStream()) { inStream.Position = 0; var image = Image.Load <Rgba32>(inStream); GifMetadata metaData = image.Metadata.GetGifMetadata(); GifFrameMetadata frameMetadata = image.Frames.RootFrame.Metadata.GetGifMetadata(); GifColorTableMode colorMode = metaData.ColorTableMode; var encoder = new GifEncoder { ColorTableMode = colorMode, Quantizer = new OctreeQuantizer(new QuantizerOptions { MaxColors = frameMetadata.ColorTableLength }) }; image.Save(outStream, encoder); outStream.Position = 0; outStream.Position = 0; var clone = Image.Load <Rgba32>(outStream); GifMetadata cloneMetadata = clone.Metadata.GetGifMetadata(); Assert.Equal(metaData.ColorTableMode, cloneMetadata.ColorTableMode); // Gifiddle and Cyotek GifInfo say this image has 64 colors. Assert.Equal(64, frameMetadata.ColorTableLength); for (int i = 0; i < image.Frames.Count; i++) { GifFrameMetadata ifm = image.Frames[i].Metadata.GetGifMetadata(); GifFrameMetadata cifm = clone.Frames[i].Metadata.GetGifMetadata(); Assert.Equal(ifm.ColorTableLength, cifm.ColorTableLength); Assert.Equal(ifm.FrameDelay, cifm.FrameDelay); } image.Dispose(); clone.Dispose(); } }
public void CloneIsDeep() { var meta = new GifMetadata() { RepeatCount = 1, ColorTableMode = GifColorTableMode.Global, GlobalColorTableLength = 2 }; var clone = (GifMetadata)meta.DeepClone(); clone.RepeatCount = 2; clone.ColorTableMode = GifColorTableMode.Local; clone.GlobalColorTableLength = 1; Assert.False(meta.RepeatCount.Equals(clone.RepeatCount)); Assert.False(meta.ColorTableMode.Equals(clone.ColorTableMode)); Assert.False(meta.GlobalColorTableLength.Equals(clone.GlobalColorTableLength)); }
public void Encode_PreservesTextData() { var decoder = new GifDecoder(); var testFile = TestFile.Create(TestImages.Gif.LargeComment); using (Image <Rgba32> input = testFile.CreateRgba32Image(decoder)) using (var memoryStream = new MemoryStream()) { input.Save(memoryStream, new GifEncoder()); memoryStream.Position = 0; using (Image <Rgba32> image = decoder.Decode <Rgba32>(Configuration.Default, memoryStream)) { GifMetadata metadata = image.Metadata.GetGifMetadata(); Assert.Equal(2, metadata.Comments.Count); Assert.Equal(new string('c', 349), metadata.Comments[0]); Assert.Equal("ImageSharp", metadata.Comments[1]); } } }
public void Encode_IgnoreMetadataIsFalse_CommentsAreWritten() { var options = new GifEncoder(); var testFile = TestFile.Create(TestImages.Gif.Rings); using (Image <Rgba32> input = testFile.CreateRgba32Image()) { using (var memStream = new MemoryStream()) { input.Save(memStream, options); memStream.Position = 0; using (var output = Image.Load <Rgba32>(memStream)) { GifMetadata metadata = output.Metadata.GetGifMetadata(); Assert.Equal(1, metadata.Comments.Count); Assert.Equal("ImageSharp", metadata.Comments[0]); } } } }
public void CloneIsDeep() { var meta = new GifMetadata { RepeatCount = 1, ColorTableMode = GifColorTableMode.Global, GlobalColorTableLength = 2, Comments = new List <string> { "Foo" } }; var clone = (GifMetadata)meta.DeepClone(); clone.RepeatCount = 2; clone.ColorTableMode = GifColorTableMode.Local; clone.GlobalColorTableLength = 1; Assert.False(meta.RepeatCount.Equals(clone.RepeatCount)); Assert.False(meta.ColorTableMode.Equals(clone.ColorTableMode)); Assert.False(meta.GlobalColorTableLength.Equals(clone.GlobalColorTableLength)); Assert.False(meta.Comments.Equals(clone.Comments)); Assert.True(meta.Comments.SequenceEqual(clone.Comments)); }
/// <summary> /// Initializes a new instance of the <see cref="GifMetadata"/> class. /// </summary> /// <param name="other">The metadata to create an instance from.</param> private GifMetadata(GifMetadata other) { this.RepeatCount = other.RepeatCount; this.ColorTableMode = other.ColorTableMode; this.GlobalColorTableLength = other.GlobalColorTableLength; }
public RomInfo(string decPath, bool parseImages = false) { byte[] contentBytes = File.ReadAllBytes(decPath); ushort headerChecksum = CalcCrc16Modbus(contentBytes.Slice(0, HeaderChecksumOffset)); ushort romChecksumValue = BitConverter.ToUInt16(contentBytes.Slice(HeaderChecksumOffset, 2, true).Reverse().ToArray()); ValidContent = headerChecksum == romChecksumValue; if (!ValidContent) { return; } GameTitle = new string(contentBytes.Slice(GameTitleOffset, GameTitleSize).AsChars()).TrimEnd('\0'); GameCode = new string(contentBytes.Slice(GameCodeOffset, GameCodeSize).AsChars()); if (GameCode.Length >= GameCodeLength) { RegionCode = GameCode[GameCodeLength - 1]; } else { Log.Instance.Warn($"The gamecode for '{decPath}' is not valid: '{GameCode}'"); } int titleInfoAddress = BitConverter.ToInt32(contentBytes.Slice(TitleInfoAddressOffset, TitleInfoAddressSize, true).Reverse().ToArray()); if (titleInfoAddress == 0x00000000) { return; } TitleInfoVersion = (TitleInfoVersions)BitConverter.ToInt16(contentBytes.Slice(titleInfoAddress, 2, true).Reverse().ToArray()); UnicodeEncoding encoding = new UnicodeEncoding(false, false); int titleCount = TitleInfoVersion == TitleInfoVersions.Original ? 6 : TitleInfoVersion == TitleInfoVersions.ChineseTitle ? 7 : 8; for (int i = 0; i < titleCount; i++) { Titles[i] = encoding.GetString(contentBytes.Slice(titleInfoAddress + TitleInfoTitlesOffset + TitleInfoTitleSize * i, TitleInfoTitleSize)).Trim('\0', '\uffff').AsNullIfEmpty(); } if (!parseImages) { return; } // Static icon StaticIcon = BuildImage(ParseBitmapIndices(contentBytes.Slice(titleInfoAddress + TitleInfoStaticIconOffset, IconBitmapSize)), ParsePalette(contentBytes.Slice(titleInfoAddress + TitleInfoStaticIconOffset + IconBitmapSize, IconPaletteBytesPerColour * IconPaletteColours))); PngMetadata pngMetadata = StaticIcon.Metadata.GetFormatMetadata(PngFormat.Instance); pngMetadata.ColorType = PngColorType.Palette; pngMetadata.TextData = new List <PngTextData> { new PngTextData("description", $"Icon for the DSiWare title \"{GetFriendlyTitle()}\" (game code \"{GameCode}\").", "en-ca", "") }; // Animated icon if (TitleInfoVersion != TitleInfoVersions.ChineseKoreanTitlesAnimated) { return; } byte[] sequenceBytes = contentBytes.Slice(titleInfoAddress + TitleInfoAnimIconSequenceOffset, TitleInfoAnimIconSequenceFrameCount * 2); // Non-animated icons start with 0x01000001 if (sequenceBytes[0] == 0x01 && sequenceBytes[1] == 0x00 && sequenceBytes[2] == 0x00 && sequenceBytes[3] == 0x01) { return; } byte[][] bitmapPaletteIndices = new byte[TitleInfoAnimIconBitmapCount][]; for (int i = 0; i < TitleInfoAnimIconBitmapCount; i++) { bitmapPaletteIndices[i] = ParseBitmapIndices(contentBytes.Slice( titleInfoAddress + TitleInfoAnimIconBitmapsOffset + i * IconBitmapSize, IconBitmapSize)); } Rgba32[][] paletteColours = new Rgba32[TitleInfoAnimIconPaletteCount][]; for (int i = 0; i < TitleInfoAnimIconPaletteCount; i++) { paletteColours[i] = ParsePalette(contentBytes.Slice( titleInfoAddress + TitleInfoAnimIconPalettesOffset + i * IconPaletteBytesPerColour * IconPaletteColours, IconPaletteBytesPerColour * IconPaletteColours)); } AnimatedIcon = new Image <Rgba32>(IconSquareDim, IconSquareDim); for (int i = 0; i < TitleInfoAnimIconSequenceFrameCount; i++) { if (sequenceBytes[i * 2] == 0x00 && sequenceBytes[i * 2 + 1] == 0x00) { break; } bool flipVertical = (sequenceBytes[i * 2 + 1] & 0b10000000) >> 7 == 1; bool flipHorizontal = (sequenceBytes[i * 2 + 1] & 0b01000000) >> 6 == 1; byte paletteIndex = (byte)((sequenceBytes[i * 2 + 1] & 0b00111000) >> 3); byte bitmapIndex = (byte)(sequenceBytes[i * 2 + 1] & 0b00000111); byte frameDuration = sequenceBytes[i * 2]; // in 60Hz units Image <Rgba32> frame = BuildImage(bitmapPaletteIndices[bitmapIndex], paletteColours[paletteIndex], flipHorizontal, flipVertical); ImageFrame <Rgba32> aFrame = AnimatedIcon.Frames.AddFrame(frame.Frames.RootFrame); GifFrameMetadata frameMetadata = aFrame.Metadata.GetFormatMetadata(GifFormat.Instance); frameMetadata.FrameDelay = (int)Math.Round(frameDuration * FrameDurationConversion); frameMetadata.DisposalMethod = GifDisposalMethod.RestoreToBackground; } AnimatedIcon.Frames.RemoveFrame(0); AnimatedIcon.Metadata.GetFormatMetadata(GifFormat.Instance).RepeatCount = 0; GifMetadata gifMetadata = AnimatedIcon.Metadata.GetFormatMetadata(GifFormat.Instance); gifMetadata.RepeatCount = 0; gifMetadata.Comments = new List <string> { $"Icon for the DSiWare title \"{GetFriendlyTitle()}\" (game code \"{GameCode}\")." }; }