External Exception in GDI+ error saving specific image

▼魔方 西西 提交于 2019-12-01 13:32:17

The errors were caused by the order in which GetImageBytesFromOLEField() was searching for image signatures. It was searching for the BMP signature first, and unfortunately that signature is very short ('BM') so in a few cases it found that pair of bytes inside the data of the image and extracted what it thought was BMP data.

The fix was to change the order from

var ImageSignatures = new List<byte[]>();
// BITMAP_ID_BLOCK = "BM"
ImageSignatures.Add(new byte[] { 0x42, 0x4D });
// JPG_ID_BLOCK = "\u00FF\u00D8\u00FF"
ImageSignatures.Add(new byte[] { 0xFF, 0xD8, 0xFF });
// PNG_ID_BLOCK = "\u0089PNG\r\n\u001a\n"
ImageSignatures.Add(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A });
// GIF_ID_BLOCK = "GIF8"
ImageSignatures.Add(new byte[] { 0x47, 0x49, 0x46, 0x38 });
// TIFF_ID_BLOCK = "II*\u0000"
ImageSignatures.Add(new byte[] { 0x49, 0x49, 0x2A, 0x00 });

to

var ImageSignatures = new List<byte[]>();
// JPG_ID_BLOCK = "\u00FF\u00D8\u00FF"
ImageSignatures.Add(new byte[] { 0xFF, 0xD8, 0xFF });
// PNG_ID_BLOCK = "\u0089PNG\r\n\u001a\n"
ImageSignatures.Add(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A });
// GIF_ID_BLOCK = "GIF8"
ImageSignatures.Add(new byte[] { 0x47, 0x49, 0x46, 0x38 });
// TIFF_ID_BLOCK = "II*\u0000"
ImageSignatures.Add(new byte[] { 0x49, 0x49, 0x2A, 0x00 });
// BITMAP_ID_BLOCK = "BM"
ImageSignatures.Add(new byte[] { 0x42, 0x4D });

Once I did that I could process the entire file:

Size of .mdb before image conversion: 31.8 MB
Size of .mdb after conversion but before Compact and Repair: 37.1 MB
Size of .mdb after Compact and Repair: 8.5 MB

Edit

This is the code that I used to convert the images and write them back to the database:

private void btnStart_Click(object sender, EventArgs e)
{
    using (var con = new OleDbConnection())
    {
        con.ConnectionString =
                @"Provider=Microsoft.ACE.OLEDB.12.0;" +
                @"Data Source=C:\__tmp\test\Bd Fotos Equipamentos 2.mdb;";
        con.Open();
        using (OleDbCommand cmdIn = new OleDbCommand(), cmdOut = new OleDbCommand())
        {
            cmdOut.Connection = con;
            cmdOut.CommandText = "UPDATE [Fotografias e Manuais de Equipamentos] SET [FOTO]=? WHERE [ID]=?";
            cmdOut.Parameters.Add("?", OleDbType.VarBinary);
            cmdOut.Parameters.Add("?", OleDbType.Integer);

            cmdIn.Connection = con;
            cmdIn.CommandText = "SELECT [ID], [FOTO] FROM [Fotografias e Manuais de Equipamentos]";
            OleDbDataReader rdr = cmdIn.ExecuteReader();
            while (rdr.Read())
            {
                int i = Convert.ToInt32(rdr["ID"]);
                lblStatus.Text = string.Format("Processing ID {0}...", i);
                lblStatus.Refresh();
                byte[] b = (byte[])rdr["FOTO"];
                byte[] imageBytes = OleImageUnwrap.GetImageBytesFromOLEField(b);
                byte[] pngBytes;
                using (MemoryStream msIn = new MemoryStream(imageBytes), msOut = new MemoryStream())
                {
                    Image img = Image.FromStream(msIn);
                    img.Save(msOut, System.Drawing.Imaging.ImageFormat.Png);
                    img.Dispose();
                    pngBytes = msOut.ToArray();
                }
                cmdOut.Parameters[0].Value = pngBytes;
                cmdOut.Parameters[1].Value = rdr["ID"];
                cmdOut.ExecuteNonQuery();
            }
        }
        con.Close();
    }
    this.Close();
}

The GetImageBytesFromOLEField() code is the same as I used before, with MaxNumberOfBytesToSearch = 1000000.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!