2009-02-16 11 views
21

sé cómo conseguir el tamaño (x, y) de una imagen¿Cómo puedo obtener de manera confiable las dimensiones de una imagen en .NET sin cargar la imagen?

Image.FromFile("cat.jpg").Size 

pero que requiere cargar la imagen de la memoria.

Cuando veo las imágenes en el Explorador de Windows, me muestra el tamaño.

  • ¿Cómo puedo acceder a ese tamaño?
  • ¿Es confiable para todas las imágenes? ¿Necesita el explorador de Windows haber "visto" la imagen primero para que el tamaño esté disponible? No quiero subir a un servidor y no tengo metadatos disponibles antes de cargarlo en Internet Explorer.

Editar: Cambié de tema de 'tamaño' a 'dimensiones' para aclarar qué tamaño que quería.

Respuesta

3

Hacer esto generalmente implica abrir el archivo y leer solo su encabezado (los primeros bytes) para encontrar su formato y el tamaño. No necesita leer el archivo completo para averiguar su tamaño. A veces, el tamaño está incluso en un desplazamiento específico en el archivo, por lo que encontrar el tamaño solo lee 8 bytes.

Puede usar filemon.exe para descubrir realmente qué es lo que Windows Explorer hace para encontrar el tamaño.

+0

¿Windows no explorar ir directamente al sistema operativo como preguntar cuánto espacio ha asignado la imagen en el disco ?. ¿No es un atributo de archivo? ¿O como dices es metadatos codificados? – Paxic

+0

@panix - lo siento si te confundí. quiero decir tamaño como ancho + alto y no tamaño como en bytes. –

+0

@shy ¿sabes si eso es lo que hace el explorador? ¿Puedo confiar en los metadatos que tiene Windows Explorer?Creo que esto es un poco furtivo y posiblemente poco confiable en algunos casos extremos. Por eso publiqué la pregunta –

11

Si desea obtener las dimensiones de la imagen (ancho y alto) sin cargar la imagen, debe leer alguna parte del archivo jpeg como se muestra a continuación.

Aquí es un fuera de la caja método para ti :)

public static Size GetJpegImageSize(string filename) { 
    FileStream stream=null; 
    BinaryReader rdr=null; 
    try { 
     stream=File.OpenRead(filename); 
     rdr=new BinaryReader(stream); 
     // keep reading packets until we find one that contains Size info 
     for(; ;) { 
      byte code=rdr.ReadByte(); 
      if(code!=0xFF) throw new ApplicationException(
        "Unexpected value in file "+filename); 
      code=rdr.ReadByte(); 
      switch(code) { 
       // filler byte 
       case 0xFF: 
        stream.Position--; 
        break; 
       // packets without data 
       case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: 
       case 0xD5: case 0xD6: case 0xD7: case 0xD8: case 0xD9: 
        break; 
       // packets with size information 
       case 0xC0: case 0xC1: case 0xC2: case 0xC3: 
       case 0xC4: case 0xC5: case 0xC6: case 0xC7: 
       case 0xC8: case 0xC9: case 0xCA: case 0xCB: 
       case 0xCC: case 0xCD: case 0xCE: case 0xCF: 
        ReadBEUshort(rdr); 
        rdr.ReadByte(); 
        ushort h=ReadBEUshort(rdr); 
        ushort w=ReadBEUshort(rdr); 
        return new Size(w, h); 
       // irrelevant variable-length packets 
       default: 
        int len=ReadBEUshort(rdr); 
        stream.Position+=len-2; 
        break; 
      } 
     } 
    } finally { 
     if(rdr!=null) rdr.Close(); 
     if(stream!=null) stream.Close(); 
    } 
} 

private static ushort ReadBEUshort(BinaryReader rdr) { 
    ushort hi=rdr.ReadByte(); 
    hi<<=8; 
    ushort lo=rdr.ReadByte(); 
    return (ushort)(hi|lo); 
} 

Ésta no es mi código, este ejemplo tiene algún tiempo atrás en el proyecto de código. Copié y guardé en mis fragmentos de utilidad, aunque no recuerdo el enlace.

+2

ugh! lol. Whoa eso es un montón de código. Además, estoy en un entorno web, así que también puedo tener gifs y pngs. me estoy inclinando hacia el almacenamiento en caché Image.FromFile ("cat.jpg"). Tamaño - o al menos el tiempo que tarda en leer en una imagen –

+0

Sí - abre el jpg para leer el encabezado con información de tamaño – amazedsaint

32

Puede simplemente usar Image.FromStream(Stream, bool, bool) con el 2 ° y 3 ° parámetro "falso" para evitar cargar el archivo en la memoria.

+1

Esto es exactamente lo que necesitaba; sin gestión de bytes, etc. ¡Gracias! –

+0

+1 Funciona para mí ... – takrl

4

El artículo Reading Image Headers to Get Width and Height ofrece varias posibilidades de solución:

  • multi-threading
  • lectura cabeceras de los archivos, volviendo a la carga de la imagen completa si cabecera falta
  • La creación de su propio índice para una imagen atributos
1

Desde lo alto de mi cabeza - LoadImage() tiene una anulación que especifica la devolución de llamada de progreso. ¿Tal vez pueda usar eso para cancelar la carga después de leer el encabezado?

Cuestiones relacionadas