2010-01-26 19 views
6

Tengo una base de datos simple en el archivo de acceso .mdb, pero no sé cómo tratar con la excepción "parámetro no válido" cuando estoy creando Image desde la secuencia. He leído que necesito quitar 78 bytes de desplazamiento (from here) pero I todavía obtengo un error "parámetro no válido" cuando llamo FromStream, incluso después de quitar los primeros 78 bytes.Lectura de imagen desde Access - parámetro no válido


Esto no funciona para mí:

byte[] abytPic = (byte[])dt.Rows[0]["Photo"]; byte arrary with image 
if ((abytPic[0] == 21) && (abytPic[1] == 28)) //It's true 
{ 
    byte[] abytStripped = new byte[abytPic.Length - 78]; 
    System.Buffer.BlockCopy(abytPic, 78, abytStripped, 0, abytPic.Length - 78); 
    msPic = new emoryStream(abytStripped); 
} 
+0

Cuando ve la tabla de MS Access que contiene su columna Imagen, ¿qué texto ve en el campo? ¿Es 'Long binary data' o algo diferente? – Stewbob

Respuesta

6

Si está leyendo los datos directamente desde MS Access, no es necesario quitar cualquier información de cabecera.

Suponiendo que la imagen se almacena como un BLOB, que es el más común, aquí está el código para leer en la matriz de bytes a partir de la base de datos y almacenar como un archivo de imagen (lo siento, VB en lugar de C#):

Dim varBytes() As Byte 

    Using cn As New OleDbConnection(myConnectionString) 
    cn.Open() 

    sqlText = "SELECT [myColumn] " _ 
       & "FROM [myTable] " _ 
       & "WHERE ([mySearchCriteria] = '" & mySearchTerm & "')" 

    Using cm As New OleDbCommand(sqlText, cn) 
     Dim rdr As OleDbDataReader 

     rdr = cm.ExecuteReader 

     rdr.Read() 

     varBytes = rdr.GetValue(0) 
    End Using 

    End Using 

    My.Computer.FileSystem.WriteAllBytes(myPath & "\myFile.emf", varBytes, True) 

Este ejemplo que tuve es uno en el que sabía que los archivos en la base de datos eran imágenes .emf. Si conoce la extensión, puede ponerla en el nombre del archivo. Si no lo hace, puede dejarlo en blanco y luego abrir el resultado con un visor de imágenes; debería comenzar Si necesita encontrar la extensión o el tipo de archivo, una vez que se guarda como un archivo, puede abrirlo con cualquier editor hexadecimal y el tipo de archivo estará disponible a partir de la información del encabezado.

Su pregunta es un poco confusa, por lo que no estoy seguro de que el código anterior sea exactamente lo que quiere, pero debería acercarlo mucho más.

EDIT:

Este es el código VB que toma la matriz de bytes, lo carga en un objeto MemoryStream, y luego crea un objeto de imagen de la corriente. Este pequeño código funcionaba bien y mostraba la imagen en un recuadro en mi formulario.

Dim img As Image 
    Dim str As New MemoryStream(varBytes) 
    img = Image.FromStream(str) 
    PictureBox1.Image = img 

Si el equivalente C# de esto no está funcionando para ti, entonces es probable que en cómo la imagen se almacena en la base de datos de MS Access el problema.

EDIT:

Si la imagen en su base de datos se almacena como un 'paquete' y no un 'datos binarios Long', entonces usted tendrá que quitar la información del encabezado que MS Access agrega. He estado jugando con el tipo de almacenamiento de imágenes 'Paquete' con un archivo .jpg simple. El encabezado en este caso es mucho más largo que 78 bytes. En este caso, en realidad es 234 bytes, y MS Access también agregó cierta información al final del archivo original; unos 292 bytes en este caso.

Parece que su enfoque original fue correcto, solo tendrá que determinar cuántos bytes se deben quitar de la parte frontal y posterior de la matriz de bytes para su situación.

Lo determiné para mi archivo comparando el archivo de imagen original y el archivo exportado desde la base de datos (no a un objeto Stream, vea mi primer código) en un editor hexadecimal. Una vez que descubrí cuánta información (encabezado y pie de página) había agregado MS Access, supe cuántos bytes necesitaban ser eliminados.

EDIT:

El tamaño de la cabecera añadida por MS Access cuando la imagen se almacena como 'paquete' varía dependiendo del tipo de archivo y la ubicación original (información de ruta completa) de la imagen cuando fue arrojado a la base de datos de MS Access. Entonces, incluso para el mismo tipo de archivo, puede tener una cantidad diferente de bytes para quitar del encabezado de cada archivo. Esto hace que sea mucho más difícil, porque entonces tendrá que escanear la matriz de bytes hasta que encuentre la información normal de inicio de archivo para ese tipo de archivo, y luego quitar todo lo anterior.

Todo este dolor de cabeza es una de las razones por las que es mejor almacenar imágenes como BLOB 'Long binary data' en una base de datos. La recuperación es mucho más fácil. No sé si tienes la opción de hacer esto, pero si es así, sería una buena idea.

+0

Pero cuando intento instanciar un objeto de tipo Imagen, pasando una matriz de bytes (varBytes en su ejemplo) como parámetro de constructor, Obtengo el error: El parámetro no es válido. Por supuesto, esta es una matriz de bytes válida (de longitud de aproximadamente 3000 bytes, dependiendo del tamaño de la imagen). – Dariusz

+0

Gracias parece que no hay una solución para obtener la longitud del encabezado OleObject. Gracias por su apoyo. – Dariusz

1

No creo que su problema sea con la base de datos. Las excepciones de "parámetro no válido" cuando se trata de imágenes pueden ser un dolor total ya que las he tratado anteriormente. No tienen muy claro cuál es el problema.

¿Cómo exactamente se colocó la imagen en la base de datos? Puede haber un problema al escribir la imagen en la base de datos incluso antes de intentar extraerla. Además, ¿qué tipo de archivo es la imagen?

EDIT Aquí hay algunos ejemplos de código que he usado antes para obtener una imagen de una matriz de bytes.

 //takes an array of bytes and converts them to an image. 
    private Image getImageFromBytes(byte[] myByteArray) 
    {    
     System.IO.MemoryStream newImageStream = new System.IO.MemoryStream(myByteArray, 0, myByteArray.Length); 
     return Image.FromStream(newImageStream, true); 
    } 
+0

NOTA: Todo esto supone que está recuperando valores válidos de su llamada a la base de datos. – Aaron

Cuestiones relacionadas