2010-03-24 10 views
5

Estoy tratando de escribir un método para reducir el tamaño de cualquier imagen. Se llama el 50% cada vez pero he encontrado un problema. A veces, termino con un tamaño de archivo más grande mientras que la imagen es realmente solo la mitad de lo que era. Me estoy ocupando de DPI y PixelFormat. ¿Qué más me estoy perdiendo?A veces, la reducción de un mapa de bits genera un archivo más grande. ¿Por qué?

Gracias por su tiempo.

public Bitmap ResizeBitmap(Bitmap origBitmap, int nWidth, int nHeight) 
{ 
    Bitmap newBitmap = new Bitmap(nWidth, nHeight, origBitmap.PixelFormat); 

    newBitmap.SetResolution(
     origBitmap.HorizontalResolution, 
     origBitmap.VerticalResolution); 

    using (Graphics g = Graphics.FromImage((Image)newBitmap)) 
    { 
     g.InterpolationMode = InterpolationMode.HighQualityBicubic; 

     g.DrawImage(origBitmap, 0, 0, nWidth, nHeight); 
    } 

    return newBitmap; 
} 

http://imgur.com/lY9BN.png

http://imgur.com/KSka0.png

Editar: Aquí está el código que falta:

int width = (int)(bitmap.Width * 0.5f); 
int height = (int)(bitmap.Height * 0.5f); 
Bitmap resizedBitmap = ResizeBitmap(bitmap, width, height); 
resizedBitmap.Save(newFilename); 

Edición 2: Sobre la base de sus comentarios, esta es la solución I he encontrado:

private void saveAsJPEG(string savingPath, Bitmap bitmap, long quality) 
{ 
    EncoderParameter parameter = new EncoderParameter(Encoder.Compression, quality); 
    ImageCodecInfo encoder = getEncoder(ImageFormat.Jpeg); 
    if (encoder != null) 
    { 
     EncoderParameters encoderParams = new EncoderParameters(1); 
     encoderParams.Param[0] = parameter; 
     bitmap.Save(savingPath, encoder, encoderParams); 
    } 
} 

private ImageCodecInfo getEncoder(ImageFormat format) 
{ 

    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); 
    foreach (ImageCodecInfo codec in codecs) 
     if (codec.FormatID == format.Guid) 
      return codec; 

    return null; 
} 
+0

Compresión? Los bits/píxel comprimidos son diferentes. – graphicdivine

+0

Publica tu código de exportación de C# JPEG. También supongo que es un problema de compresión. – futureelite7

+0

Ah, acabo de agregar el código que falta –

Respuesta

6

Probablemente esté guardando la imagen jpeg con una relación de compresión baja (alta calidad).

+0

Mi suposición también. – mafu

+0

Bueno, no elijo ninguna relación de compresión. ¿Hay alguna manera de usar la misma relación de compresión que en la imagen original? Gracias. –

+2

@ Matías - por lo que recuerdo, la relación de compresión no se almacena en el encabezado, de modo que la información se pierde una vez que haya guardado el archivo. – ChrisF

1

yo diría que va a guardar como un archivo JPEG de alta calidad (menos compresión == más espacio)

2

El problema no se encuentra en el código que envió, pero donde se guarda el JPEG. ¿Qué relación de compresión estás usando?

1

Aparentemente sus mapas de bits se guardan como archivos JPEG, y sabiendo cómo le gusta hacer las cosas por usted, es probable que ahorre con un nivel de compresión predeterminado que es bastante bajo. El jpeg original debe tener un nivel de compresión decente en él. Incluso si fuera el mismo nivel de compresión, la forma en que funciona el formato jpeg puede significar que ha encontrado una imagen de fluke que dosifica la hinchazón a una resolución más baja.

Sin embargo, un mapa de bits tiene un tamaño exacto, si tiene diez píxeles de ancho y diez de alto, tiene 100 píxeles, digamos 16 bits (2 bytes) de 200 bytes, más un poco de encabezado.

baje la resolución a 5 por 5, tiene 50 bytes más un poco de encabezado, aunque debería tener la misma cantidad de encabezado.

4

La recompresión de una imagen JPEG es algo que debe evitar. Pero el verdadero problema aquí es el InterpolationMode, uno de alta calidad produce una gran cantidad de píxeles sutilmente sombreados, lo que dificulta la compresión de la imagen. Usar InterpolationMode.NearestNeighbor debería evitar eso, pero a costa de obtener una imagen de menor calidad.

+0

Lo he intentado, y el tamaño del archivo es aún más grande que la imagen original. –

+0

@ Matías: ¿qué sucede cuando comienzas con un PNG para evitar el ruido debido a la primera compresión? –

+0

¿Qué quieres decir? Mis imágenes de origen siempre son JPEG, lo siento, no lo mencioné antes. –

1

Pruebe este código para guardar el JPEG que tiene. Le permitirá establecer la calidad de compresión. Experimente y vea si esto ayuda a su problema de tamaño:

private void saveJpeg(string path, Bitmap img, long quality) 
{ 
    EncoderParameter parameter = new EncoderParameter(Encoder.Quality, quality); 
    ImageCodecInfo encoder = this.getEncoderInfo("image/jpeg"); 
    if (encoder != null) 
    { 
     EncoderParameters encoderParams = new EncoderParameters(1); 
     encoderParams.Param[0] = parameter; 
     img.Save(path, encoder, encoderParams); 
    } 
} 

private ImageCodecInfo getEncoderInfo(string mimeType) 
{ 
    ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); 
    for (int i = 0; i < imageEncoders.Length; i++) 
    { 
     if (imageEncoders[i].MimeType == mimeType) 
     { 
      return imageEncoders[i]; 
     } 
    } 
    return null; 
} 
+0

¿Qué es getEncoderInfo? –

+0

Lo siento, me olvidé por completo de ese método. Ahora debería estar completo (aunque supongo que ya es demasiado tarde :)) – Jefim

+0

¡Gracias, funciona genial! –

1

Parece que el original es la salida de una cámara digital. Creo que los productores de cámaras usan algoritmos de compresión súper optimizados patentados, mientras que una biblioteca común puede tener una implementación menos efectiva. (Y, por supuesto, probablemente no esté utilizando el mismo nivel de compresión que la cámara.)

Además, la cámara utiliza los datos brutos (posiblemente realizando algún preprocesamiento "mágico" primero) desde sus sensores como entrada. Mientras que cuando lo vuelve a comprimir, la entrada tiene artefactos de compresión y cambio de escala que pueden hacer que la compresión sea menos efectiva.

En realidad creo que si comprime una imagen varias veces con el mismo algoritmo jpg en el misma nivel, podría crecer en tamaño debido a los artefactos de las compresiones anteriores añade "detalles" que es más difícil de comprimir (y se vuelve más feo también).

(El algoritmo de compresión de la cámara también se puede optimizar para el hecho de que la entrada es siempre una foto, mientras que un algoritmo de propósito general puede hacer algunas cosas menos eficaz para trabajar razonablemente bien tanto para fotos y línea de arte mixta imágenes que contienen fotos y elementos gráficos generados.)

+0

JPEG nunca funciona bien en la línea de arte, a menos que suba los niveles de calidad al máximo. Sin embargo, tienes razón de que los fabricantes de cámaras pueden optimizar sus algoritmos JPEG. Cuando Sigma salió con su sensor Foveon, descubrieron que el algoritmo que estaban utilizando estaba perdiendo parte de los detalles que su nuevo sensor proporcionaba frente a la competencia, y tuvieron que adaptarlo. –

+0

Por supuesto, no es bueno para el arte lineal (¡use png, etc. para eso!). De hecho, estaba pensando en imágenes mixtas con muchos tipos diferentes de gráficos. (He actualizado mi respuesta) –

Cuestiones relacionadas