PRB: Las dimensiones de dibujo son incoherentes con la propiedad Image.Size cuando utiliza el método DrawImageUnscaled()

Seleccione idioma Seleccione idioma
Id. de artículo: 317174 - Ver los productos a los que se aplica este artículo
Este artículo se publicó anteriormente con el número E317174
Este artículo se ha archivado. Se ofrece "tal cual" y no se volverá a actualizar.
Expandir todo | Contraer todo

Síntomas

Al usar el método DrawImageUnscaled() en .NET Framework o un método DrawImage() sin los parámetros de dimensión en GDI+, los resultados del dibujo pueden parecer incoherentes con las dimensiones de la imagen que indica la propiedad Image.Size.

Causa

Este comportamiento se produce porque la propiedad Image.Size de .NET Framework o los métodos Image.Width() e Image.Height() de GDI+ devuelven las dimensiones de la imagen en píxeles.

Sin embargo, de forma predeterminada, los métodos de dibujo de imágenes "sin escala" de la clase Graphics dibujan la imagen como si se debiera dibujar con su tamaño lógico (determinado por su resolución interna). Este comportamiento predeterminado de los métodos de dibujo de imágenes sin escala se debe a su diseño, de modo que cumplen el propósito de GDI+ de no tener en cuenta la resolución.

Este resultado puede ser muy confuso, ya que la dimensión resultante en píxeles de la imagen que dibuja la clase Graphics no coincide con la dimensión en píxeles que indica la clase Image.

Considere el siguiente código de ejemplo de C#, que demuestra una oportunidad de confusión:
protected override void OnPaint(PaintEventArgs pea)
{
    Pen     pen = new Pen(Color.Black);
    Size    ImageSize;

    ImageSize = image.Size;
    int x = 50;
    int y = 50;

    pea.Graphics.PageUnit = GraphicsUnit.Pixel;
    // Dibujar el desplazamiento de una línea desde el origen de la imagen
    // La longitud de la línea es la misma que la dimensión de la imagen
    pea.Graphics.DrawLine(pen, x, y-5,x+ImageSize.Width-1, y-5);
    pea.Graphics.DrawLine(pen, x-5, y, x-5, y+ImageSize.Height-1);
    // Dibujar la imagen
    pea.Graphics.DrawImageUnscaled(image, x, y);
}
El propósito de este código, si se supone que los resultados de DrawImageUnscaled() son coherentes con las dimensiones de ImageSize, debería ser dibujar dos líneas negras junto a la parte superior y lateral de la imagen. Se supone que la longitud de estas líneas debería ser la misma que las dimensiones de la imagen.

Sin embargo, en la mayor parte de las imágenes, observará una discrepancia entre las dimensiones de las líneas y las de la imagen. Para comprender el motivo, considere el caso de una imagen específica.

Una imagen tiene una dimensión definida de forma inherente que está compuesta por el número de píxeles a lo largo de los ejes horizontal y vertical. La resolución de la imagen se suele expresar también en puntos por pulgada (ppi). El valor en ppi relaciona el tamaño en píxeles de la imagen con su tamaño lógico , medido en un esquema temporal y espacial real.

Por ejemplo, es posible que una imagen con un tamaño en píxeles de 600 por 300 puntos se pueda definir con un valor en ppi de 300. Por lo tanto, el tamaño lógico de la imagen es de 2 pulgadas por 1 pulgada (su tamaño físico, quizás el de una fotografía).

Si se muestra en el monitor de un equipo con un tamaño en ppi de 100, puede usar dos sistemas para dibujar la imagen:
  • Mostrarla como de 600 por 300 píxeles, lo que implica 6 pulgadas por 3 pulgadas en una pantalla de 100 ppi.

    O bien,
  • Usar el valor de 300 ppi en la imagen para convertir su tamaño en píxeles como 2 pulgadas por 1 pulgada en la pantalla de 100 ppi.
El tamaño de la imagen que devuelve Image.Size o los métodos Width() y Height() de la clase Image indica que la imagen tiene 600 píxeles por 300 píxeles. Esto es correcto si los métodos DrawImage o DrawImageUnscaled usan el primero de los dos sistemas para dibujar la imagen.

Sin embargo, el segundo sistema se utiliza para conservar el tamaño lógico de la imagen de 2 pulgadas por 1 pulgada en la pantalla de 100 ppi. En consecuencia, la imagen dibujada en realidad ocuparía un campo de píxeles de 200 por 100 píxeles. La imagen sigue estando en su tamaño lógico sin escala de 2 pulgadas por 1 pulgada, pero sus dimensiones en píxeles en realidad se han reducido.

Si el tamaño en ppi de la pantalla es de 300, los dos sistemas son equivalentes porque 600 por 300 píxeles en una pantalla de 300 ppi equivalen a 2 pulgadas por 1 pulgada.

Es recomendable usar el valor del tamaño lógico de una imagen, definido por su tamaño en ppi, porque de esta forma se mantiene la coherencia en el tamaño de la imagen cuando la ve un usuario. GDI+ está diseñado para ser independiente de la resolución, lo que motiva el comportamiento de los dos métodos GDI+ anteriores además de que en .NET Framework se use de forma predeterminada el tamaño lógico cuando una imagen se dibuja sin escala.

Solución

Si necesita conocer las dimensiones en píxeles de una imagen, puede determinar el tamaño en píxeles del mismo modo que el método DrawImage dibuja la imagen. Para determinar las dimensiones en píxeles del tamaño lógico de la imagen, realice la conversión de unidades de las dimensiones de la imagen con el tamaño en ppi de la imagen y el del objeto Graphics.

En el siguiente ejemplo de código de C# se demuestra cómo hacerlo:
protected override void OnPaint(PaintEventArgs pea)
{
    Pen     pen = new Pen(Color.Black);
    Size    ImageSize;
    int cx;
    int cy;

    ImageSize = image.Size;

    // Calcular las dimensiones de la imagen en píxeles a partir de su tamaño lógico
    cx = (int)((float)ImageSize.Width/image.HorizontalResolution * pea.Graphics.DpiX);
    cy = (int)((float)ImageSize.Height/image.VerticalResolution * pea.Graphics.DpiY);
    int x = 50;
    int y = 50;

    pea.Graphics.PageUnit = GraphicsUnit.Pixel;
    // Dibujar el desplazamiento de una línea desde el origen de la imagen
    // La longitud de la línea debe ser la misma que la dimensión de la imagen
    pea.Graphics.DrawLine(pen, x, y-5,x+cx-1, y-5);
    pea.Graphics.DrawLine(pen, x-5, y, x-5, y+cy-1);
    // Dibujar la imagen
    pea.Graphics.DrawImageUnscaled(image, x, y);
}

Estado

Este comportamiento es una característica del diseño de la aplicación.

Más información

Aunque es importante que el código pueda expresar correctamente el tamaño de la imagen resultante dibujada por las versiones sin escala del método DrawImage, también es importante dibujar la imagen a su tamaño en píxeles.

Puede dibujar la imagen a su tamaño en píxeles mediante uno de los métodos DrawImage que pueden escalar la imagen a la dimensión de destino que desee, expresada en píxeles.

En el siguiente ejemplo de código de C# se demuestra cómo se puede hacer esto:
protected override void OnPaint(PaintEventArgs pea)
{
    Pen     pen = new Pen(Color.Black);
    Size    ImageSize;

    ImageSize = image.Size;
    int x = 50;
    int y = 50;

    pea.Graphics.PageUnit = GraphicsUnit.Pixel;
    // Dibujar el desplazamiento de una línea desde el origen de la imagen
    // La longitud de la línea debe ser la misma que la dimensión de la imagen
    pea.Graphics.DrawLine(pen, x, y-5,x+ImageSize.Width-1, y-5);
    pea.Graphics.DrawLine(pen, x-5, y, x-5, y+ImageSize.Height-1);
    // Dibujar la imagen confinada a sus límites en píxeles
    pea.Graphics.DrawImage(image, x, y, ImageSize.Width, ImageSize.Height);
}
NOTA: en todos los ejemplos de código de C# incluidos en este artículo, se supone que el objeto Image, que el código consulta y dibuja, y cuyo símbolo es "image" está definido en el formato de C#. También se supone que el objeto Image ya se ha iniciado con una imagen.

Propiedades

Id. de artículo: 317174 - Última revisión: lunes, 24 de febrero de 2014 - Versión: 2.0
La información de este artículo se refiere a:
  • Microsoft GDI+ 1.0
  • Microsoft .NET Framework Software Development Kit 1.0
Palabras clave: 
kbnosurvey kbarchive kbgdipimaging kbgrpdsgdi kbprb KB317174

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com