0

I have a Java system to enroll the fingerprint in my system. In my database, we save a byte array of the fingerprint.

Piece of my Java Code to Enroll the Fingerprint

       enrollStmt = con.prepareStatement("INSERT INTO EnrollDigital (template, Client_Id) VALUES (?, ?)");

public void enroll(String clientID) {
       enrollStmt.setBinaryStream(1, new ByteArrayInputStream(template.getData()),  template.getData().length);
       enrollStmt.setString(2, clientID);
       enrollStmt.executeUpdate();
}

Now I need to do the inverse. With the byte array thar are saved in my database, I need get this data, and return an Image.

I've tryied do this, with this C# code

public Form1()
{
     InitializeComponent();
     Image img = byteArrayToImage(GetBytes("my_array_that_was_saved_in_my_database"));                
}

public Image byteArrayToImage(byte[] byteArrayIn)
{
     MemoryStream ms = new MemoryStream(byteArrayIn);
     Image returnImage = Image.FromStream(ms);
     return returnImage;
}

static byte[] GetBytes(string str)
{
     byte[] bytes = new byte[str.Length * sizeof(char)];
     System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
     return bytes;
}

But it returns a Invalid Argument Exception. I saw some post here in Stackoverflow like this one but without success.

Can someone help me to transform the byte array that was saved in my database in a Image ? I need recover the fingerprint Image.

Table Structure

CREATE TABLE [dbo].[EnrollDigital](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [template] [varbinary](1000) NULL,
    [template2] [varbinary](1000) NULL,
    [template3] [varbinary](1000) NULL,
    [Client_Id] [int] NULL)

ID  Template 
4   0xA7FF011DCB00FD00013B01DA00E400023601A700FD00013B01A600EF00018D00D3001901018200C40043010282008E00C800024701A500B200018700D0004501013601E5000801018200B100B400013B016A00370101930063002E0102580194005E010130016E00E000029E0068000E01024C0198005001027C00C9007301027100D1006C01022B01B8007B01011F017B009501026B00680060010177005C004A01020C0048005F010144008600BC01021F01DC00B80101300158005801015A006F00C301011F016C00A901016B009D000B0C11120A07080502031A160D10171A151A1311160B1B1815161C1404091B1C0900171604000001160C13120C0F15170607181C00021A0B0901120800030E06060A18140B0F150B12051A0C150D080405040F0E10050306130D11081B141105150C15100402170B100B0301040113100D051415170C02010D0B1008110D1305030E130802060D16030A0D1A140D10161110160F03070403010A0902100C120D1210020E1A100F020D0808091413090305090D0C0F03141A050019130E070800191101071C15020A1417141002071A0F170D05021912000A0C0E0F060E0A1004171001060006100F1C1718131C1A120408021002000713150B020C021C0D14111819170F0B0E1C13180D000E1815090A1B151811120919141B131B1709071B0D1B1A1B1911091817191C190D1908150219051302170E17021909    0xA7FF011E8C00D700014400A600E900014F00C0001301026B00C8009300015801A7001601015A0091001501025A00C8008300025201CD001C01026B00CB002C01021F016D00A4000239004900BF0001F800A6004301016000DC00270102710060001F01014F000D01D600017C004300C500024400C3004C01026B0065007600012D001E01CF00013601BE00570001AF0010018300013B011A01A200018700F9002B01017700DF004300015801C500C700026301D200C100024701C500E700016000BA00EC00015A008500250102550093005301015500AA000F0A1B1A18190807070203060E12080C0C071B011C05040504021D0B0802160C100B011A01001A18151410080C021C041C0D0704021B13171B181A1908040B08021A0B1C061304010B04100C12150A09041B0816011816070911190305021D1C1B19100702011D1005010D050B051B00071B18030F09071A0E150B070B02041A0C041002051B00181A00011900090705100403130B0C16021D05050008051C02190610160E191D04081B0C1A061718061C011D080400081A081C000A06140D041D0D00190E1803141A0E000F0218121912141C000A111D0219150B0D14170E14150303171A030D00160404180F111B0E161A0B16160E191415060D01121801090719000301031A1214130903181505181113070E18090D0F0C0E0E0309060D0A16120611010A000603111B120011010F080E19131A150C12050A151709131813050F1C0F1C0A18111917111718170A0616150914  

UPDATE

I follow some instructions at this post on StackOverflow and I got the following method.

    internal static void BytesToBitmap(byte[] ptrNativeImage, Size imageSize, int resolution, out Bitmap ptrBitmapData)
    {
        const PixelFormat pxFormat = PixelFormat.Format8bppIndexed;

        ptrBitmapData = new Bitmap(imageSize.Width, imageSize.Height);
        ptrBitmapData.SetResolution(resolution, resolution);


        // Method #2
        BitmapData mapData = null;

        try
        {
            mapData = ptrBitmapData.LockBits(new Rectangle(Point.Empty, ptrBitmapData.Size),
                ImageLockMode.WriteOnly, pxFormat);

            //[https://stackoverflow.com/questions/1983781/why-does-bitmapsource-create-throw-an-argumentexception/1983886#1983886][3]
            int bitsPerPixel = ((int)pxFormat >> 8) & 0xFF;

            //Number of bits used to store the image data per line (only the valid data)
            int validBitsPerLine = imageSize.Width * bitsPerPixel;

            //4 bytes for every int32 (32 bits)
            int stride = ((validBitsPerLine + 31) / 32) * 4;
            mapData.Stride = stride;

            Marshal.Copy(ptrNativeImage, 0, mapData.Scan0, ptrNativeImage.Length);
        }
        finally
        {                
            if (mapData != null)
                ptrBitmapData.UnlockBits(mapData);
        }
    }

And I call this method

Size s = new System.Drawing.Size();
s.Height = 750;
s.Width = 750;
try
{
     Bitmap bmp = new Bitmap(10, 10);
     BytesToBitmap(templateData, s, 10, out bmp);
     bmp.Save("F:\\img.bmp");
}
catch (System.Exception e)
{
}            

But it saves a black image.

Community
  • 1
  • 1
Lucas_Santos
  • 4,638
  • 17
  • 71
  • 118

2 Answers2

1

When saving binary data into sql server using the varbinary datatype, the SqlDataReader or similar classes already know how to get the byte array.

No need to convert the varbinary to a string...

You should use a code like that:

        using (SqlCommand cmd = new SqlCommand("select template from dbo.EnrollDigital where id=4", sqlConnection))
        {
            byte[] templateData = (byte[])cmd.ExecuteScalar();
            Image img = byteArrayToImage(templateData);
        }
Nir Kornfeld
  • 827
  • 7
  • 11
  • Is it possible that the code that saves the image uses a different format than the code that reads it? Maybe you should try to write a C# code that saves an image and test this. – Nir Kornfeld Sep 09 '13 at 18:03
  • The manufacturer of the fingerprint reader, tell me that the image is an BMP, 8 bits. – Lucas_Santos Sep 09 '13 at 18:12
  • I got some news about this problem, and I got a method that convert Bytes to Bitmap, like you can see in my Update, I think this is the closest that I've got since this morning. – Lucas_Santos Sep 09 '13 at 19:31
  • If I put 750x750 in my Size, it save a black image. – Lucas_Santos Sep 09 '13 at 20:22
  • Is the source image saved by the fingerprint device is 750x750? If your binary data stream is a full BMP file, it should have all the metadata in it. there is no need for you to specify the resolution and all the other parameters in your code. Can you check that out with the device manufacturer? – Nir Kornfeld Sep 10 '13 at 04:37
0

Why not just let the Bitmap class load the image for you:

byte[] templateData = .... // get bytes from db.
Bitmap bm = new Bitmap(new MemoryStream(templateData));

Bitmap (inherits from Image) will read the image header and figure out how to load it.

mp3ferret
  • 1,183
  • 11
  • 16
  • because this way return `Invalid Argument Exception` – Lucas_Santos Sep 09 '13 at 20:21
  • ok - then I'd guess the image isn't valid. Can you extract the image to a file and try and open it like that - give it a bmp extension. Compare it in a hex editor to a know valid 8bit bmp, or look at the header spec : http://en.wikipedia.org/wiki/BMP_file_format. I'd just go with comparing it to another valid bmp if i where you - at least to start with. – mp3ferret Sep 09 '13 at 20:35