public void ShouldReadIEND() { string filePath = @"../../../Data/przekladnia.png"; IEND iend = new IEND(PNGFile.Read(filePath).Last()); Assert.AreEqual("IEND", iend.Type); }
// Info from: // https://wiki.mozilla.org/APNG_Specification // http://www.w3.org/TR/PNG/ /// <summary> /// Save an animation in a APNG file (Firefox supported) /// </summary> /// <param name="pngs">All frames (path of files or bitmaps)</param> /// <param name="apng">The path of the output file</param> /// <param name="delay">The delay between frames (delay/1000)</param> /// <param name="loops">The number of loops (if 0 = infinite)</param> public static void Create(string[] pngs, string apng, int delay, int loops) { byte[] pngSignature = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }; IHDR ihdr = Read_IHDR(pngs[0]); #region Section acTL acTL actl = new acTL(); actl.length = BitConverter.GetBytes(8).Reverse().ToArray(); actl.id = Encoding.ASCII.GetBytes(new char[] { 'a', 'c', 'T', 'L' }); actl.num_frames = BitConverter.GetBytes(pngs.Length).Reverse().ToArray(); actl.num_plays = BitConverter.GetBytes(loops).Reverse().ToArray(); // Loop List <byte> stream = new List <byte>(); stream.AddRange(actl.id); stream.AddRange(actl.num_frames); stream.AddRange(actl.num_plays); actl.crc = Helper.CRC32.Calculate(stream.ToArray()); stream.Clear(); #endregion List <fcTL> fctl = new List <fcTL>(); List <fdAT> fdat = new List <fdAT>(); int i = 0; fctl.Add(Read_fcTL(pngs[0], i, delay)); i++; byte[] IDAT = Read_IDAT(pngs[0]); foreach (string png in pngs) { if (png == pngs[0]) { continue; } fctl.Add(Read_fcTL(png, i, delay)); i++; fdat.Add(Read_fdAT(png, i)); i++; } IEND iend = new IEND(); iend.id = Encoding.ASCII.GetBytes(new char[] { 'I', 'E', 'N', 'D' }); iend.length = BitConverter.GetBytes(0); iend.crc = Helper.CRC32.Calculate(iend.id); Write(apng, pngSignature, ihdr, actl, IDAT, fctl.ToArray(), fdat.ToArray(), iend); }
// Info from: // https://wiki.mozilla.org/APNG_Specification // http://www.w3.org/TR/PNG/ /// <summary> /// Save an animation in a APNG file (Firefox supported) /// </summary> /// <param name="pngs">All frames (path of files or bitmaps)</param> /// <param name="apng">The path of the output file</param> /// <param name="delay">The delay between frames (delay/1000)</param> /// <param name="loops">The number of loops (if 0 = infinite)</param> public static void Create(string[] pngs, string apng, int delay, int loops) { byte[] pngSignature = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }; IHDR ihdr = Read_IHDR(pngs[0]); #region Section acTL acTL actl = new acTL(); actl.length = BitConverter.GetBytes(8).Reverse().ToArray(); actl.id = Encoding.ASCII.GetBytes(new char[] { 'a', 'c', 'T', 'L' }); actl.num_frames = BitConverter.GetBytes(pngs.Length).Reverse().ToArray(); actl.num_plays = BitConverter.GetBytes(loops).Reverse().ToArray(); // Loop List<byte> stream = new List<byte>(); stream.AddRange(actl.id); stream.AddRange(actl.num_frames); stream.AddRange(actl.num_plays); actl.crc = Helper.CRC32.Calculate(stream.ToArray()); stream.Clear(); #endregion List<fcTL> fctl = new List<fcTL>(); List<fdAT> fdat = new List<fdAT>(); int i = 0; fctl.Add(Read_fcTL(pngs[0], i, delay)); i++; byte[] IDAT = Read_IDAT(pngs[0]); foreach (string png in pngs) { if (png == pngs[0]) continue; fctl.Add(Read_fcTL(png, i, delay)); i++; fdat.Add(Read_fdAT(png, i)); i++; } IEND iend = new IEND(); iend.id = Encoding.ASCII.GetBytes(new char[] { 'I', 'E', 'N', 'D' }); iend.length = BitConverter.GetBytes(0); iend.crc = Helper.CRC32.Calculate(iend.id); Write(apng, pngSignature, ihdr, actl, IDAT, fctl.ToArray(), fdat.ToArray(), iend); }
private static void Write(string apng, byte[] signature, IHDR ihdr, acTL actl, byte[] idat, fcTL[] fctl, fdAT[] fdat, IEND iend) { BinaryWriter bw = new BinaryWriter(new FileStream(apng, FileMode.Create)); bw.Write(signature); bw.Write(ihdr.length); bw.Write(ihdr.id); bw.Write(ihdr.width); bw.Write(ihdr.height); bw.Write(ihdr.depth); bw.Write(ihdr.colour_type); bw.Write(ihdr.compression); bw.Write(ihdr.filter); bw.Write(ihdr.interlace); bw.Write(ihdr.crc); bw.Write(actl.length); bw.Write(actl.id); bw.Write(actl.num_frames); bw.Write(actl.num_plays); bw.Write(actl.crc); bw.Write(fctl[0].length); bw.Write(fctl[0].id); bw.Write(fctl[0].sequence_numer); bw.Write(fctl[0].width); bw.Write(fctl[0].height); bw.Write(fctl[0].x_offset); bw.Write(fctl[0].y_offset); bw.Write(fctl[0].delay_num); bw.Write(fctl[0].delay_den); bw.Write(fctl[0].dispose_op); bw.Write(fctl[0].blend_op); bw.Write(fctl[0].crc); bw.Write(idat); for (int i = 0; i < fdat.Length; i++) { bw.Write(fctl[i + 1].length); bw.Write(fctl[i + 1].id); bw.Write(fctl[i + 1].sequence_numer); bw.Write(fctl[i + 1].width); bw.Write(fctl[i + 1].height); bw.Write(fctl[i + 1].x_offset); bw.Write(fctl[i + 1].y_offset); bw.Write(fctl[i + 1].delay_num); bw.Write(fctl[i + 1].delay_den); bw.Write(fctl[i + 1].dispose_op); bw.Write(fctl[i + 1].blend_op); bw.Write(fctl[i + 1].crc); bw.Write(fdat[i].length); bw.Write(fdat[i].id); bw.Write(fdat[i].sequence_number); bw.Write(fdat[i].data); bw.Write(fdat[i].crc); } bw.Write(iend.length); bw.Write(iend.id); bw.Write(iend.crc); bw.Flush(); bw.Close(); }