在GDI +错误外部异常保存特定的图像 [英] External Exception in GDI+ error saving specific image

查看:262
本文介绍了在GDI +错误外部异常保存特定的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要从数据库中抓取图像,所以我做了一些代码吧​​。问题是如何在一些图像的错误,而在其他无效的参数错误。

  OleDbConnection的L =新的OleDbConnection(builder.ConnectionString) ; 
名单<图像> listaImagens =新的List<图像>();
名单,LT;弦乐> listaNomes =新的List<串GT;();
串诺姆=;


{
OleDbDataAdapter的适配器=新OleDbDataAdapter的(SELECT * FROM [FotografiasëManuais去Equipamentos] WHERE ID> 26和ID小于30,L);
的DataSet DS =新的DataSet();
adapter.Fill(DS,FotografiasêManuais去Equipamentos);
//字符串s = ds.Tables [APP_Equip_Ult_Prox_Calibracao]列[16] .ColumnName。
的foreach(DataRow的行ds.Tables [FotografiasëManuais去Equipamentos。行)
{
如果(行[DesignaçãoEquipamento]。的ToString()。等于( ))
{
诺姆=semNome;
}
,否则
{
诺姆=行[DesignaçãoEquipamento]的ToString();
}
listaNomes.Add(行[ID]的ToString()+_+行[马卡报]的ToString()+_+行[MODELO。的ToString()+_+诺姆);

{
字节[] B =(字节[])行[FOTO];
字节[] = imagebyte OleImageUnwrap.GetImageBytesFromOLEField(B,30000);

的MemoryStream毫秒​​=新的MemoryStream();
ms.Write(imagebyte,0,imagebyte.Length);

listaImagens.Add(Image.FromStream(MS));
}
赶上(例外)
{

{
字节[] B =(字节[])行[FOTO];
字节[] = imagebyte OleImageUnwrap.GetImageBytesFromOLEField(B,100000);

的MemoryStream毫秒​​=新的MemoryStream();
ms.Write(imagebyte,0,imagebyte.Length);

listaImagens.Add(Image.FromStream(MS));
}
赶上(例外)
{
字节[] B =(字节[])行[FOTO];
字节[] = imagebyte OleImageUnwrap.GetImageBytesFromOLEField(B,600000);

的MemoryStream毫秒​​=新的MemoryStream();
ms.Write(imagebyte,0,imagebyte.Length);
图片IMG = Image.FromStream(毫秒); CAUGHT在这里DEBBUG
listaImagens.Add(IMG)//无效参数错误;
}
}
}
的for(int i = 0; I< listaImagens.Count;我++)
{
listaImagens [I] .Save (C:\\Users\\sies4578\\Desktop\\Testes\\Fotos\\+ listaNomes [I] +。PNG,System.Drawing.Imaging .ImageFormat.Png); //外部EXCEPTON在GDI +错误CAUGHT在这里DEBBUG
}
}
赶上(异常前)
{
MessageBox.Show(申Øberro:+ ex.Message);
}
}



OleImageUnwrap.GetImageBytesFromOLEField 用于删除从OLE对象的标头是在数据库中的图像,并获得唯一的图像本身的字节数:

 公共静态的byte [] GetImageBytesFromOLEField(字节[] oleFieldBytes,INT NumMaximoBytesSearch)
{
//裁判http://stackoverflow.com/questions/19688641/convert-ole-object-in-datarow-成字节-C-锐
//改编自http://blogs.msdn.com/b/pranab/archive/2008/07/15/removing-ole-header-from-images-stored-in -ms访问-DB-AS-OLE-object.aspx

INT MaxNumberOfBytesToSearch = NumMaximoBytesSearch;
字节[] imageBytes; //返回值

变种ImageSignatures =新的List<字节[]>();
// BITMAP_ID_BLOCK =BM
ImageSignatures.Add(新的byte [] {0x42后,送出0x4d});
// JPG_ID_BLOCK =\\\ÿ\\\Ø\\\ÿ
ImageSignatures.Add(新的byte [] {0xFF的,0xD8,为0xFF});
// PNG_ID_BLOCK =\\\‰PNG\r\\\
\\\\\\

ImageSignatures.Add(新的byte [] {0x89上,为0x50,0x4E,0X47,0X0D,0x0A的, 0x1A的,0x0A的});
// GIF_ID_BLOCK =GIF8
ImageSignatures.Add(新的byte [] {0X47,0x49,将0x46,0x38});
// TIFF_ID_BLOCK =II * \\\
ImageSignatures.Add(新的byte [] {0x49,0x49,0x2A,0×00});

INT NumberOfBytesToSearch =(oleFieldBytes.Count()< MaxNumberOfBytesToSearch oleFieldBytes.Count():MaxNumberOfBytesToSearch?);
变种startingBytes =新的字节[NumberOfBytesToSearch]
Array.Copy(oleFieldBytes,startingBytes,NumberOfBytesToSearch);

变种位置=新的List< INT>();
的foreach(在ImageSignatures的byte [] BlockSignature)
{
位置= IndexOfSequence(startingBytes,BlockSignature,0);
如果(positions.Count大于0)
{
中断;
}
}
INT IPOS = -1;
如果(positions.Count大于0)
{
IPOS =位置[0];
}

如果股票(IPO == -1)
抛出新的异常(无法确定头的大小为OLE对象);

imageBytes =新的字节[oleFieldBytes.LongLength - 首次公开发行]
System.IO.MemoryStream毫秒​​=新System.IO.MemoryStream();
ms.Write(oleFieldBytes,上市,oleFieldBytes.Length - IPOS);
imageBytes = ms.ToArray();
ms.Close();
ms.Dispose();
返回imageBytes;
}

私人静态列表< INT> IndexOfSequence(此字节[]缓冲区,字节[]模式,诠释了startIndex)
{
//参考:http://stackoverflow.com/a/332667/2144390
名单,LT; INT>位置=新的List< INT>();
INT I = Array.IndexOf&所述;字节>(缓冲液,模式[0],则startIndex);
,而(I> = 0&放大器;&安培; I< = buffer.Length - pattern.Length)
{
字节[] =段新的字节[pattern.Length]
Buffer.BlockCopy(缓冲器,我,段0,pattern.Length);
如果(segment.SequenceEqual<位>(模式))
positions.Add(I)
I = Array.IndexOf&所述;字节>(缓冲液,模式[0],I + 1);
}
返回岗位;
}
}



那么,为什么这些误差修改甚至出现?我得到的第18和第26图像的第一个错误的节省部分和其他的产生与内存流图像时的第25位。


解决方案

该错误是由其中 GetImageBytesFromOLEField()正在寻找图像特征的顺序造成的。它被搜索的BMP签名第一,可惜该签名是很短的(BM),因此在少数情况下,它发现字节对的图像数据,并提取它认为是BMP数据。



此修复程序是顺序从

更改

<预类=郎CSHARP prettyprint,覆盖> VAR ImageSignatures =新的List<字节[]>();
// BITMAP_ID_BLOCK =BM
ImageSignatures.Add(新的byte [] {0x42后,送出0x4d});
// JPG_ID_BLOCK =\\\ÿ\\\Ø\\\ÿ
ImageSignatures.Add(新的byte [] {0xFF的,0xD8,为0xFF});
// PNG_ID_BLOCK =\\\‰PNG\r\\\
\\\\\\

ImageSignatures.Add(新的byte [] {0x89上,为0x50,0x4E,0X47,0X0D,0x0A的, 0x1A的,0x0A的});
// GIF_ID_BLOCK =GIF8
ImageSignatures.Add(新的byte [] {0X47,0x49,将0x46,0x38});
// TIFF_ID_BLOCK =II * \\\
ImageSignatures.Add(新的byte [] {0x49,0x49,0x2A,0×00});





<预类=郎CSHARP prettyprint-覆盖> VAR ImageSignatures =新的List<字节[]>();
// JPG_ID_BLOCK =\\\ÿ\\\Ø\\\ÿ
ImageSignatures.Add(新的byte [] {0xFF的,0xD8,为0xFF});
// PNG_ID_BLOCK =\\\‰PNG\r\\\
\\\\\\

ImageSignatures.Add(新的byte [] {0x89上,为0x50,0x4E,0X47,0X0D,0x0A的, 0x1A的,0x0A的});
// GIF_ID_BLOCK =GIF8
ImageSignatures.Add(新的byte [] {0X47,0x49,将0x46,0x38});
// TIFF_ID_BLOCK =II * \\\
ImageSignatures.Add(新的byte [] {0x49,0x49,0x2A,0×00});
// BITMAP_ID_BLOCK =BM
ImageSignatures.Add(新的byte [] {0x42后,送出0x4d});

在我这样做,我可以处理整个文件:



的.mdb的图像转换前大小:37.1 MB结果
的.mdb后,结构紧凑,尺寸:转换之后,但在压缩和修复的.mdb 31.8 MB结果
尺寸修复:8.5 MB



修改



这是我用来转换图像并将其写回代码到数据库:



<预类=郎CSHARP prettyprint-覆盖> 私人无效btnStart_Click(对象发件人,EventArgs五)
{使用
(VAR CON =新的OleDbConnection())
{
con.ConnectionString =
@供应商= Microsoft.ACE.OLEDB.12.0; +
@数据源= C:\__tmp\test\Bd照片Equipamentos 2.mdb;;
con.Open();使用
(OleDbCommand的cmdIn =新的OleDbCommand(),cmdOut =新的OleDbCommand())
{
cmdOut.Connection = CON;
cmdOut.CommandText =UPDATE [FotografiasëManuais去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ëManuais去Equipamentos];
OleDbDataReader RDR = cmdIn.ExecuteReader();
,而(rdr.Read())
{
INT I = Convert.ToInt32(RDR [ID]);
lblStatus.Text =的String.Format(处理ID {0} ......,I);
lblStatus.Refresh();
字节[] B =(字节[])RDR [FOTO];
字节[] = imageBytes OleImageUnwrap.GetImageBytesFromOLEField(B);
字节[] pngBytes;
使用(MemoryStream的MSIN =新的MemoryStream(imageBytes),msOut =新的MemoryStream())
{
图片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();
}



GetImageBytesFromOLEField()代码是相同的,因为我之前使用,用 MaxNumberOfBytesToSearch = 1000000


I needed to grab the images from a database, so I made some code for it. Issue is getting that error in some images and an Invalid Parameter error in others.

        OleDbConnection l = new OleDbConnection(builder.ConnectionString);
        List<Image> listaImagens = new List<Image>();
        List<String> listaNomes = new List<string>();
        string nome = "";

        try
        {
            OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [Fotografias e Manuais de Equipamentos]  WHERE ID >26 AND ID < 30", l);
            DataSet ds = new DataSet();
            adapter.Fill(ds, "Fotografias e Manuais de Equipamentos");
            //string s = ds.Tables["APP_Equip_Ult_Prox_Calibracao"].Columns[16].ColumnName;
            foreach (DataRow row in ds.Tables["Fotografias e Manuais de Equipamentos"].Rows)
            {
                if (row["Designação Equipamento"].ToString().Equals(""))
                {
                    nome = "semNome";
                }
                else
                {
                    nome = row["Designação Equipamento"].ToString();
                }
                listaNomes.Add(row["ID"].ToString()+"_"+row["MARCA"].ToString() + "_" + row["MODELO"].ToString() + "_" + nome);
                try
                {
                    byte[] b = (byte[])row["FOTO"];
                    byte[] imagebyte = OleImageUnwrap.GetImageBytesFromOLEField(b, 30000);

                    MemoryStream ms = new MemoryStream();
                    ms.Write(imagebyte, 0, imagebyte.Length);

                    listaImagens.Add(Image.FromStream(ms));
                }
                catch (Exception)
                {
                    try
                    {
                        byte[] b = (byte[])row["FOTO"];
                        byte[] imagebyte = OleImageUnwrap.GetImageBytesFromOLEField(b, 100000);

                        MemoryStream ms = new MemoryStream();
                        ms.Write(imagebyte, 0, imagebyte.Length);

                        listaImagens.Add(Image.FromStream(ms));
                    }
                    catch (Exception)
                    {
                        byte[] b = (byte[])row["FOTO"];
                        byte[] imagebyte = OleImageUnwrap.GetImageBytesFromOLEField(b, 600000);

                        MemoryStream ms = new MemoryStream();
                        ms.Write(imagebyte, 0, imagebyte.Length);
                        Image img = Image.FromStream(ms); // INVALID PARAMETER ERROR CAUGHT HERE IN DEBBUG
                        listaImagens.Add(img);
                    }
                }
            }
            for (int i = 0; i < listaImagens.Count; i++)
        {
            listaImagens[i].Save("C:\\Users\\sies4578\\Desktop\\Testes\\Fotos\\" + listaNomes[i] +".png", System.Drawing.Imaging.ImageFormat.Png); //EXTERNAL EXCEPTON IN GDI+ ERROR CAUGHT HERE IN DEBBUG
        }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Deu o berro: "+ex.Message);
        }            
    }

The OleImageUnwrap.GetImageBytesFromOLEField is used to remove the header from the OLE object that is the image in the Database and get only the bytes of the image itself :

    public static byte[] GetImageBytesFromOLEField(byte[] oleFieldBytes, int NumMaximoBytesSearch)
    {
        //ref http://stackoverflow.com/questions/19688641/convert-ole-object-in-datarow-into-byte-c-sharp
        // adapted from http://blogs.msdn.com/b/pranab/archive/2008/07/15/removing-ole-header-from-images-stored-in-ms-access-db-as-ole-object.aspx

        int MaxNumberOfBytesToSearch = NumMaximoBytesSearch;
        byte[] imageBytes;  // return value

        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 });

        int NumberOfBytesToSearch = (oleFieldBytes.Count() < MaxNumberOfBytesToSearch ? oleFieldBytes.Count() : MaxNumberOfBytesToSearch);
        var startingBytes = new byte[NumberOfBytesToSearch];
        Array.Copy(oleFieldBytes, startingBytes, NumberOfBytesToSearch);

        var positions = new List<int>();
        foreach (byte[] BlockSignature in ImageSignatures)
        {
            positions = IndexOfSequence(startingBytes, BlockSignature, 0);
            if (positions.Count > 0)
            {
                break;
            }
        }
        int iPos = -1;
        if (positions.Count > 0)
        {
            iPos = positions[0];
        }

        if (iPos == -1)
            throw new Exception("Unable to determine header size for the OLE Object");

        imageBytes = new byte[oleFieldBytes.LongLength - iPos];
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        ms.Write(oleFieldBytes, iPos, oleFieldBytes.Length - iPos);
        imageBytes = ms.ToArray();
        ms.Close();
        ms.Dispose();
        return imageBytes;
    }

    private static List<int> IndexOfSequence(this byte[] buffer, byte[] pattern, int startIndex)
    {
        // ref: http://stackoverflow.com/a/332667/2144390
        List<int> positions = new List<int>();
        int i = Array.IndexOf<byte>(buffer, pattern[0], startIndex);
        while (i >= 0 && i <= buffer.Length - pattern.Length)
        {
            byte[] segment = new byte[pattern.Length];
            Buffer.BlockCopy(buffer, i, segment, 0, pattern.Length);
            if (segment.SequenceEqual<byte>(pattern))
                positions.Add(i);
            i = Array.IndexOf<byte>(buffer, pattern[0], i + 1);
        }
        return positions;
    }
}

So why are these erros even appearing? I get the first error at the 18th and 26th image at the save part and the other at the 25th when generating the image with the memory stream.

解决方案

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.

这篇关于在GDI +错误外部异常保存特定的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆