コード例 #1
0
ファイル: ByteVectorTest.cs プロジェクト: rygos/iTagger
 public void Short()
 {
     Assert.AreEqual(UInt16.MaxValue, ByteVector.FromUShort(UInt16.MaxValue).ToUShort());
     Assert.AreEqual(UInt16.MinValue, ByteVector.FromUShort(UInt16.MinValue).ToUShort());
     Assert.AreEqual(0, ByteVector.FromUShort(0).ToUShort());
     Assert.AreEqual(8009, ByteVector.FromUShort(8009).ToUShort());
 }
コード例 #2
0
        /// <summary>
        ///    Creates a <see cref="ByteVector"/> for the Xmp segment of this file
        /// </summary>
        /// <returns>
        ///    A <see cref="ByteVector"/> with the whole Xmp segment, if xmp tags
        ///    exists, otherwise null.
        /// </returns>
        private ByteVector RenderXMPSegment()
        {
            // Check, if XmpTag is contained
            XmpTag xmp = ImageTag.Xmp;

            if (xmp == null)
            {
                return(null);
            }

            ByteVector xmp_data = XmpTag.XAP_NS + "\0";

            xmp_data.Add(xmp.Render());

            uint segment_size = (uint)(2 + xmp_data.Count);

            // do not render data segments, which cannot fit into the possible segment size
            if (segment_size > ushort.MaxValue)
            {
                throw new Exception("XMP Segment is too big to render");
            }

            // Create whole segment
            ByteVector data = new ByteVector(new byte [] { 0xFF, (byte)Marker.APP1 });

            data.Add(ByteVector.FromUShort((ushort)segment_size));
            data.Add(xmp_data);

            return(data);
        }
コード例 #3
0
        /// <summary>
        ///    Creates a <see cref="ByteVector"/> for the comment segment of this file
        /// </summary>
        /// <returns>
        ///    A <see cref="ByteVector"/> with the whole comment segment, if a comment tag
        ///    exists, otherwise null.
        /// </returns>
        private ByteVector RenderCOMSegment()
        {
            // check, if Comment is contained
            JpegCommentTag com_tag = GetTag(TagTypes.JpegComment) as JpegCommentTag;

            if (com_tag == null)
            {
                return(null);
            }

            // create comment data
            ByteVector com_data =
                ByteVector.FromString(com_tag.Value + "\0", StringType.Latin1);

            uint segment_size = (uint)(2 + com_data.Count);

            // do not render data segments, which cannot fit into the possible segment size
            if (segment_size > ushort.MaxValue)
            {
                throw new Exception("Comment Segment is too big to render");
            }

            // create segment
            ByteVector data = new ByteVector(new byte [] { 0xFF, (byte)Marker.COM });

            data.Add(ByteVector.FromUShort((ushort)segment_size));

            data.Add(com_data);

            return(data);
        }
コード例 #4
0
 /// <summary>
 ///    Adds the data of a single entry to <paramref name="entry_data"/>.
 /// </summary>
 /// <param name="entry_data">
 ///    A <see cref="ByteVector"/> to add the entry to.
 /// </param>
 /// <param name="tag">
 ///    A <see cref="System.UInt16"/> with the tag of the entry.
 /// </param>
 /// <param name="type">
 ///    A <see cref="System.UInt16"/> with the type of the entry.
 /// </param>
 /// <param name="count">
 ///    A <see cref="System.UInt32"/> with the data count of the entry,
 /// </param>
 /// <param name="offset">
 ///    A <see cref="System.UInt32"/> with the offset field of the entry.
 /// </param>
 protected void RenderEntry(ByteVector entry_data, ushort tag, ushort type, uint count, uint offset)
 {
     entry_data.Add(ByteVector.FromUShort(tag, is_bigendian));
     entry_data.Add(ByteVector.FromUShort(type, is_bigendian));
     entry_data.Add(ByteVector.FromUInt(count, is_bigendian));
     entry_data.Add(ByteVector.FromUInt(offset, is_bigendian));
 }
コード例 #5
0
        /// <summary>
        ///    Renders the current instance to a <see cref="ByteVector"/>
        /// </summary>
        /// <param name="is_bigendian">
        ///    A <see cref="System.Boolean"/> indicating the endianess for rendering.
        /// </param>
        /// <param name="offset">
        ///    A <see cref="System.UInt32"/> with the offset, the data is stored.
        /// </param>
        /// <param name="type">
        ///    A <see cref="System.UInt16"/> the ID of the type, which is rendered
        /// </param>
        /// <param name="count">
        ///    A <see cref="System.UInt32"/> with the count of the values which are
        ///    rendered.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector"/> with the rendered data.
        /// </returns>
        public ByteVector Render(bool is_bigendian, uint offset, out ushort type, out uint count)
        {
            type  = (ushort)IFDEntryType.SShort;
            count = 1;

            return(ByteVector.FromUShort((ushort)Value, is_bigendian));
        }
コード例 #6
0
        public ByteVector Render(byte version)
        {
            ByteVector data = new ByteVector();
            ByteVector id   = ConvertId(frame_id, version, true);

            if (id == null)
            {
                throw new NotImplementedException();
            }
            switch (version)
            {
            case 2:
                data.Add(id);
                data.Add(ByteVector.FromUInt(frame_size).Mid(1, 3));
                return(data);

            case 3:
                ushort new_flags = (ushort)((((ushort)flags << 1) & 0xE000) | (((ushort)flags << 4) & 0x00C0) | (((ushort)flags >> 1) & 0x0020));
                data.Add(id);
                data.Add(ByteVector.FromUInt(frame_size));
                data.Add(ByteVector.FromUShort(new_flags));
                return(data);

            case 4:
                data.Add(id);
                data.Add(SynchData.FromUInt(frame_size));
                data.Add(ByteVector.FromUShort((ushort)flags));
                return(data);

            default:
                throw new NotImplementedException("Unsupported tag version.");
            }
        }
コード例 #7
0
        private ByteVector RenderExifSegment()
        {
            IFDTag exif = ImageTag.Exif;

            if (exif == null)
            {
                return(null);
            }
            uint       first_ifd_offset = 8;
            var        renderer         = new IFDRenderer(true, exif.Structure, first_ifd_offset);
            ByteVector exif_data        = renderer.Render();
            uint       segment_size     = (uint)(first_ifd_offset + exif_data.Count + 2 + 6);

            if (segment_size > ushort.MaxValue)
            {
                throw new Exception("Exif Segment is too big to render");
            }
            ByteVector data = new ByteVector(new byte[] { 0xFF, (byte)Marker.APP1 });

            data.Add(ByteVector.FromUShort((ushort)segment_size));
            data.Add("Exif\0\0");
            data.Add(ByteVector.FromString("MM", StringType.Latin1));
            data.Add(ByteVector.FromUShort(42));
            data.Add(ByteVector.FromUInt(first_ifd_offset));
            data.Add(exif_data);
            return(data);
        }
コード例 #8
0
        protected override ByteVector RenderFields(byte version)
        {
            ByteVector data = new ByteVector();

            data.Add(ByteVector.FromString(identification, StringType.Latin1));
            data.Add(ByteVector.TextDelimiter(StringType.Latin1));
            for (byte i = 0; i < 9; i++)
            {
                if (!channels[i].IsSet)
                {
                    continue;
                }
                data.Add(i);
                unchecked
                {
                    data.Add(ByteVector.FromUShort((ushort)channels[i].VolumeAdjustmentIndex));
                }
                byte bits = 0;
                for (byte j = 0; j < 64; j++)
                {
                    if ((channels[i].PeakVolumeIndex & (1UL << j)) != 0)
                    {
                        bits = (byte)(j + 1);
                    }
                }
                data.Add(bits);
                if (bits > 0)
                {
                    data.Add(ByteVector.FromULong(channels[i].PeakVolumeIndex).Mid(8 - BitsToBytes(bits)));
                }
            }
            return(data);
        }
コード例 #9
0
        /// <summary>
        ///    Renders the IFD to an ByteVector where the offset of the IFD
        ///    itself is <paramref name="ifd_offset"/> and all offsets
        ///    contained in the IFD are adjusted accroding it.
        /// </summary>
        /// <param name="directory">
        ///    A <see cref="IFDDirectory"/> with the directory to render.
        /// </param>
        /// <param name="ifd_offset">
        ///    A <see cref="System.UInt32"/> with the offset of the IFD
        /// </param>
        /// <param name="last">
        ///    A <see cref="System.Boolean"/> which is true, if the IFD is
        ///    the last one, i.e. the offset to the next IFD, which is
        ///    stored inside the IFD, is 0. If the value is false, the
        ///    offset to the next IFD is set that it starts directly after
        ///    the current one.
        /// </param>
        /// <returns>
        ///    A <see cref="ByteVector"/> with the rendered IFD.
        /// </returns>
        private ByteVector RenderIFD(IFDDirectory directory, uint ifd_offset, bool last)
        {
            if (directory.Count > (int)UInt16.MaxValue)
            {
                throw new Exception(String.Format("Directory has too much entries: {0}", directory.Count));
            }

            // Remove empty SUB ifds.
            var tags = new List <ushort>(directory.Keys);

            foreach (var tag in tags)
            {
                var entry = directory[tag];
                if (entry is SubIFDEntry && (entry as SubIFDEntry).ChildCount == 0)
                {
                    directory.Remove(tag);
                }
            }

            ushort entry_count = (ushort)directory.Count;

            // ifd_offset + size of entry_count + entries + next ifd offset
            uint data_offset = ifd_offset + 2 + 12 * (uint)entry_count + 4;

            // store the entries itself
            ByteVector entry_data = new ByteVector();

            // store the data referenced by the entries
            ByteVector offset_data = new ByteVector();

            entry_data.Add(ByteVector.FromUShort(entry_count, is_bigendian));

            foreach (IFDEntry entry in directory.Values)
            {
                RenderEntryData(entry, entry_data, offset_data, data_offset);
            }

            if (last)
            {
                entry_data.Add("\0\0\0\0");
            }
            else
            {
                entry_data.Add(ByteVector.FromUInt((uint)(data_offset + offset_data.Count), is_bigendian));
            }

            if (data_offset - ifd_offset != entry_data.Count)
            {
                throw new Exception(String.Format("Expected IFD data size was {0} but is {1}", data_offset - ifd_offset, entry_data.Count));
            }

            entry_data.Add(offset_data);

            return(entry_data);
        }
コード例 #10
0
        public override ByteVector Render(bool is_bigendian, uint offset, out ushort type, out uint count)
        {
            type  = (ushort)IFDEntryType.Short;
            count = (uint)Values.Length;
            ByteVector data = new ByteVector();

            foreach (ushort value in Values)
            {
                data.Add(ByteVector.FromUShort(value, is_bigendian));
            }
            return(data);
        }
コード例 #11
0
        protected ByteVector RenderHeader(uint first_ifd_offset)
        {
            ByteVector data = new ByteVector();

            if (IsBigEndian)
            {
                data.Add("MM");
            }
            else
            {
                data.Add("II");
            }
            data.Add(ByteVector.FromUShort(Magic, IsBigEndian));
            data.Add(ByteVector.FromUInt(first_ifd_offset, IsBigEndian));
            return(data);
        }
コード例 #12
0
        /// <summary>
        ///    Creates a <see cref="ByteVector"/> for the Exif segment of this file
        /// </summary>
        /// <returns>
        ///    A <see cref="ByteVector"/> with the whole Exif segment, if exif tags
        ///    exists, otherwise null.
        /// </returns>
        ByteVector RenderExifSegment()
        {
            // Check, if IFD0 is contained
            IFDTag exif = ImageTag.Exif;

            if (exif == null)
            {
                return(null);
            }

            // first IFD starts at 8
            uint first_ifd_offset = 8;

            // Render IFD0
            // FIXME: store endianess and use it here
            var        renderer  = new IFDRenderer(true, exif.Structure, first_ifd_offset);
            ByteVector exif_data = renderer.Render();

            uint segment_size = (uint)(first_ifd_offset + exif_data.Count + 2 + 6);

            // do not render data segments, which cannot fit into the possible segment size
            if (segment_size > ushort.MaxValue)
            {
                throw new Exception("Exif Segment is too big to render");
            }

            // Create whole segment
            var data = new ByteVector(new byte[] { 0xFF, (byte)Marker.APP1 })
            {
                ByteVector.FromUShort((ushort)segment_size),
                "Exif\0\0",
                ByteVector.FromString("MM", StringType.Latin1),
                ByteVector.FromUShort(42),
                ByteVector.FromUInt(first_ifd_offset),

                // Add ifd data itself
                exif_data
            };

            return(data);
        }
コード例 #13
0
        private ByteVector RenderCOMSegment()
        {
            JpegCommentTag com_tag = GetTag(TagTypes.JpegComment)
                                     as JpegCommentTag;

            if (com_tag == null)
            {
                return(null);
            }
            ByteVector com_data     = ByteVector.FromString(com_tag.Value + "\0", StringType.Latin1);
            uint       segment_size = (uint)(2 + com_data.Count);

            if (segment_size > ushort.MaxValue)
            {
                throw new Exception("Comment Segment is too big to render");
            }
            ByteVector data = new ByteVector(new byte[] { 0xFF, (byte)Marker.COM });

            data.Add(ByteVector.FromUShort((ushort)segment_size));
            data.Add(com_data);
            return(data);
        }
コード例 #14
0
        private ByteVector RenderXMPSegment()
        {
            XmpTag xmp = ImageTag.Xmp;

            if (xmp == null)
            {
                return(null);
            }
            ByteVector xmp_data = XmpTag.XAP_NS + "\0";

            xmp_data.Add(xmp.Render());
            uint segment_size = (uint)(2 + xmp_data.Count);

            if (segment_size > ushort.MaxValue)
            {
                throw new Exception("XMP Segment is too big to render");
            }
            ByteVector data = new ByteVector(new byte[] { 0xFF, (byte)Marker.APP1 });

            data.Add(ByteVector.FromUShort((ushort)segment_size));
            data.Add(xmp_data);
            return(data);
        }
コード例 #15
0
 /// <summary>
 ///    Renders a 2-byte WORD.
 /// </summary>
 /// <param name="value">
 ///    A <see cref="ushort" /> value containing the WORD to
 ///    render.
 /// </param>
 /// <returns>
 ///    A <see cref="ByteVector" /> object containing the
 ///    rendered value.
 /// </returns>
 public static ByteVector RenderWord(ushort value)
 {
     return(ByteVector.FromUShort(value, false));
 }