Beispiel #1
0
        public override TemplateBuilder Import(byte[] template)
        {
            TemplateBuilder builder = new TemplateBuilder();

            MemoryStream stream = new MemoryStream(template);
            BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);

            // 4B magic
            for (int i = 0; i < Magic.Length; ++i)
            {
                AssertException.Check(reader.ReadByte() == Magic[i]);
            }

            // 1B version (current = 2)
            byte version = reader.ReadByte();

            AssertException.Check(version >= 1 && version <= 2);

            // 2B total length (including magic)
            reader.ReadInt16();

            if (version >= 2)
            {
                // 2B original DPI (since version 2)
                builder.OriginalDpi = IPAddress.NetworkToHostOrder(reader.ReadInt16());

                // 2B original width (since version 2)
                builder.OriginalWidth = IPAddress.NetworkToHostOrder(reader.ReadInt16());

                // 2B original height (since version 2)
                builder.OriginalHeight = IPAddress.NetworkToHostOrder(reader.ReadInt16());
            }

            // 2B minutia count
            int minutiaCount = IPAddress.NetworkToHostOrder(reader.ReadInt16());

            // N*6B minutia records
            for (int i = 0; i < minutiaCount; ++i)
            {
                TemplateBuilder.Minutia minutia = new TemplateBuilder.Minutia();

                //      2B position X
                minutia.Position.X = IPAddress.NetworkToHostOrder(reader.ReadInt16());

                //      2B position Y
                minutia.Position.Y = IPAddress.NetworkToHostOrder(reader.ReadInt16());

                //      1B direction
                minutia.Direction = reader.ReadByte();

                //      1B type
                minutia.Type = (TemplateBuilder.MinutiaType)reader.ReadByte();
                AssertException.Check(Enum.IsDefined(typeof(TemplateBuilder.MinutiaType), minutia.Type));

                builder.Minutiae.Add(minutia);
            }

            return(builder);
        }
Beispiel #2
0
        public ParameterValue GetDifference(ParameterSet original)
        {
            ParameterSet diff = GetDifferences(original);

            ParameterValue[] all = diff.AllParameters;
            AssertException.Check(all.Length <= 1);
            return(all[0]);
        }
Beispiel #3
0
        void TraceRidges(BinaryMap binary, Dictionary <Point, SkeletonBuilder.Minutia> minutiaePoints)
        {
            Dictionary <Point, SkeletonBuilder.Ridge> leads = new Dictionary <Point, SkeletonBuilder.Ridge>();

            foreach (Point minutiaPoint in minutiaePoints.Keys)
            {
                foreach (Point startRelative in Neighborhood.CornerNeighbors)
                {
                    Point start = Calc.Add(minutiaPoint, startRelative);
                    if (binary.GetBitSafe(start, false) && !minutiaePoints.ContainsKey(start) && !leads.ContainsKey(start))
                    {
                        SkeletonBuilder.Ridge ridge = new SkeletonBuilder.Ridge();
                        ridge.Points.Add(minutiaPoint);
                        ridge.Points.Add(start);
                        Point previous = minutiaPoint;
                        Point current  = start;
                        do
                        {
                            Point next = new Point();
                            foreach (Point nextRelative in Neighborhood.CornerNeighbors)
                            {
                                next = Calc.Add(current, nextRelative);
                                if (binary.GetBitSafe(next, false) && next != previous)
                                {
                                    break;
                                }
                            }
                            AssertException.Check(next != new Point());
                            previous = current;
                            current  = next;
                            ridge.Points.Add(current);
                        } while (!minutiaePoints.ContainsKey(current));
                        Point end = current;

                        ridge.Start                     = minutiaePoints[minutiaPoint];
                        ridge.End                       = minutiaePoints[end];
                        leads[ridge.Points[1]]          = ridge;
                        leads[ridge.Reversed.Points[1]] = ridge;
                    }
                }
            }
        }
Beispiel #4
0
        // References:
        // http://www.italdata-roma.com/PDF/Norme%20ISO-IEC%20Minutiae%20Data%20Format%2019794-2.pdf
        // https://biolab.csr.unibo.it/fvcongoing/UI/Form/Download.aspx (ISO section, sample ZIP, ISOTemplate.pdf)
        //
        // Format (all numbers are big-endian):
        // 4B magic "FMR\0"
        // 4B version (ignored, set to " 20\0"
        // 4B total length (including header)
        // 2B rubbish (zeroed)
        // 2B image size in pixels X
        // 2B image size in pixels Y
        // 2B rubbish (pixels per cm X, set to 196 = 500dpi)
        // 2B rubbish (pixels per cm Y, set to 196 = 500dpi)
        // 1B rubbish (number of fingerprints, set to 1)
        // 1B rubbish (zeroed)
        // 1B rubbish (finger position, zeroed)
        // 1B rubbish (zeroed)
        // 1B rubbish (fingerprint quality, set to 100)
        // 1B minutia count
        // N*6B minutiae
        //      2B minutia position X in pixels
        //          2b (upper) minutia type (01 ending, 10 bifurcation, 00 other (considered ending))
        //      2B minutia position Y in pixels (upper 2b ignored, zeroed)
        //      1B direction, compatible with SourceAFIS angles
        //      1B quality (ignored, zeroed)
        // 2B rubbish (extra data length, zeroed)
        // N*1B rubbish (extra data)

        public override byte[] Export(TemplateBuilder builder)
        {
            MemoryStream stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);

            checked
            {
                // 4B magic "FMR\0"
                writer.Write("FMR\0".ToCharArray());

                // 4B version (ignored, set to " 20\0"
                writer.Write(" 20\0".ToCharArray());

                // 4B total length (including header, will be updated later)
                writer.Write(0);

                // 2B rubbish (zeroed)
                writer.Write((short)0);

                // 2B image size in pixels X
                writer.Write(IPAddress.HostToNetworkOrder((short)builder.StandardDpiWidth));

                // 2B image size in pixels Y
                writer.Write(IPAddress.HostToNetworkOrder((short)builder.StandardDpiHeight));

                // 2B rubbish (pixels per cm X, set to 196 = 500dpi)
                writer.Write(IPAddress.HostToNetworkOrder((short)196));

                // 2B rubbish (pixels per cm Y, set to 196 = 500dpi)
                writer.Write(IPAddress.HostToNetworkOrder((short)196));

                // 1B rubbish (number of fingerprints, set to 1)
                writer.Write((byte)1);

                // 1B rubbish (zeroed)
                writer.Write((byte)0);

                // 1B rubbish (finger position, zeroed)
                writer.Write((byte)0);

                // 1B rubbish (zeroed)
                writer.Write((byte)0);

                // 1B rubbish (fingerprint quality, set to 100)
                writer.Write((byte)100);

                // 1B minutia count
                writer.Write((byte)builder.Minutiae.Count);

                // N*6B minutiae
                foreach (var minutia in builder.Minutiae)
                {
                    //      2B minutia position X in pixels
                    //          2b (upper) minutia type (01 ending, 10 bifurcation, 00 other (considered ending))
                    int x = minutia.Position.X;
                    AssertException.Check(x <= 0x3fff, "X position is out of range");
                    int type = minutia.Type == TemplateBuilder.MinutiaType.Extremidade ? 0x4000 : 0x8000;
                    writer.Write(IPAddress.HostToNetworkOrder(unchecked ((short)(x | type))));

                    //      2B minutia position Y in pixels (upper 2b ignored, zeroed)
                    int y = builder.StandardDpiHeight - minutia.Position.Y - 1;
                    AssertException.Check(y <= 0x3fff, "Y position is out of range");
                    writer.Write(IPAddress.HostToNetworkOrder((short)y));

                    //      1B direction, compatible with SourceAFIS angles
                    writer.Write(minutia.Direction);

                    //      1B quality (ignored, zeroed)
                    writer.Write((byte)0);
                }

                // 2B rubbish (extra data length, zeroed)
                // N*1B rubbish (extra data)
                writer.Write((short)0);
            }

            writer.Close();

            // update length
            byte[] template = stream.ToArray();
            BitConverter.GetBytes(IPAddress.HostToNetworkOrder(template.Length)).CopyTo(template, 8);

            return(template);
        }
Beispiel #5
0
        public override TemplateBuilder Import(byte[] template)
        {
            TemplateBuilder builder = new TemplateBuilder();

            builder.OriginalDpi = 500;

            MemoryStream stream = new MemoryStream(template);
            BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);

            // 4B magic "FMR\0"
            AssertException.Check(new String(reader.ReadChars(4)) == "FMR\0", "This is not an ISO template.");

            // 4B version (ignored, set to " 20\0"
            reader.ReadChars(4);

            // 4B total length (including header)
            AssertException.Check(IPAddress.NetworkToHostOrder(reader.ReadInt32()) == template.Length, "Invalid template length.");

            // 2B rubbish (zeroed)
            reader.ReadInt16();

            // 2B image size in pixels X
            builder.StandardDpiWidth = IPAddress.NetworkToHostOrder(reader.ReadInt16());

            // 2B image size in pixels Y
            builder.StandardDpiHeight = IPAddress.NetworkToHostOrder(reader.ReadInt16());

            // 2B rubbish (pixels per cm X, set to 196 = 500dpi)
            reader.ReadInt16();

            // 2B rubbish (pixels per cm Y, set to 196 = 500dpi)
            reader.ReadInt16();

            // 1B rubbish (number of fingerprints, set to 1)
            AssertException.Check(reader.ReadByte() == 1, "Only single-fingerprint ISO templates are supported.");

            // 1B rubbish (zeroed)
            reader.ReadByte();

            // 1B rubbish (finger position, zeroed)
            reader.ReadByte();

            // 1B rubbish (zeroed)
            reader.ReadByte();

            // 1B rubbish (fingerprint quality, set to 100)
            reader.ReadByte();

            // 1B minutia count
            int minutiaCount = reader.ReadByte();

            // N*6B minutiae
            for (int i = 0; i < minutiaCount; ++i)
            {
                TemplateBuilder.Minutia minutia = new TemplateBuilder.Minutia();

                //      2B minutia position X in pixels
                //          2b (upper) minutia type (01 ending, 10 bifurcation, 00 other (considered ending))
                ushort xPacked = (ushort)IPAddress.NetworkToHostOrder(reader.ReadInt16());
                minutia.Position.X = xPacked & (ushort)0x3fff;
                minutia.Type       = (xPacked & (ushort)0xc000) == 0x8000 ? TemplateBuilder.MinutiaType.Bifurcação : TemplateBuilder.MinutiaType.Extremidade;

                //      2B minutia position Y in pixels (upper 2b ignored, zeroed)
                minutia.Position.Y = builder.StandardDpiHeight - 1 - ((ushort)IPAddress.NetworkToHostOrder(reader.ReadInt16()) & (ushort)0x3fff);

                //      1B direction, compatible with SourceAFIS angles
                minutia.Direction = reader.ReadByte();

                //      1B quality (ignored, zeroed)
                reader.ReadByte();

                builder.Minutiae.Add(minutia);
            }

            // 2B rubbish (extra data length, zeroed)
            // N*1B rubbish (extra data)

            return(builder);
        }