4 de julio de 2007

Diferentes formas de obtener las dimensiones de las imágenes (ancho y alto)

Artículo original: Different ways to get Image Dimensions (width and height)
http://weblogs.foxite.com/vfpimaging/archive/2007/05/28/3862.aspx
Autor: Cesar Ch.
Traducido por: Ana María Bisbé York

Una de las preguntas más comunes que he visto en los foros de VFP relacionadas con imágenes es "¿Cómo puedo obtener las dimensiones de un archivo de imagen?"

Afortunadamente, esto es muy fácil de obtener.

A continuación muestro varias técnicas que podemos utilizar, con una breve explicación. cada desarrollador puede escoger cuál de ellas es mejor para sus necesidades. Todas las técnicas son muy sencillas de utilizar. Para usuarios GDI+, lo muestro empleando 3 bibliotecas con las que ya he trabajado. Como bono, la última muestra cómo obtenerlo con GDI+ utilizando llamadas directas a API, para los que no quieren utilizar una clase envoltorio GDI+.

Todos los ejemplos a continuación son libres. Estoy seguro de que hay otras formas de hacerlo. Señalo solamente aquellas que conozco y he probado.

1.- Cargar la imagen en un objeto Image VFP

Esta técnica trabaja con cualquier versión VFP. Cuando asociamos un archivo a la propiedad PicturuFile de un objeto Image, va a guardar las dimensiones en las propiedades Width y Height.
* Técnica 1
* Obtener las dimensiones del objeto Image 
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
LOCAL loVFPImg as Image
loVFPImg = CREATEOBJECT("Image")
loVFPImg.Picture = lcPictureFile
lnWidth = loVFPImg.Width
lnHeight = loVFPImg.Height
loVFPImg = NULL
MESSAGEBOX("Objeto Image VFP " + CHR(13) + ;
  "Dimensiones: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))

2.- Utilizar la función LOADPICTURE()

El objeto devuelto por LOADPICTURE() es una instancia de la clase StdPicture. Los valores de altura y ancho son unidades HiMetric (1 HiMetric = 0.01 milímetro).

No estoy realmente seguro de cuál es la forma correcta para utilizar esta función para obtener las dimensiones de una imagen.

Lisa Slater Nicholls publicó hace mucho tiempo una función para obtener las dimensiones; pero a mí no me ha funcionado: http://www.spacefold.com/lisa/lisa_fx4.htm#loadpicture

En una discusión en Foxite, entre Eric den Doop y Boudewijn Lutgerik: http://www.foxite.com/archives/what-mysterious-calculation-is-behind-this-0000067503.htm, Boudewijn obtuvo las dimensiones utilizando un factor diferente.

En mi caso, escogí la técnica que encontré en http://www.xtremevbtalk.com/archive/index.php/t-13097.html

¡ Pero no confío en este proceder porque parece que depende de la resolución de la pantalla !


* Técnica 2
* Obtener las dimensiones del objeto Imagen utilizando la función LOADPICT()
* Código de Lisa Slater Nicholls
* El objeto devuelto por LOADPIC() es una instancia de la clase StdPicture. 
* Los valores de altura y ancho son unidades HiMetric (1 HiMetric = 0.01 milímetro). 
* http://www.foxite.com/archives/what-mysterious-calculation-is-behind-this-0000067503.htm  
* http://www.xtremevbtalk.com/archive/index.php/t-13097.html 
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
LOCAL loLoadedPict
loLoadedPict = LOADPICTURE(lcPictureFile)
lnHeight = ROUND((loLoadedPict.Height / 26.45454545455),0)
lnWidth = ROUND((loLoadedPict.Width / 26.45454545455),0)
loLoadedPict = NULL
MESSAGEBOX("Función VFP LOADPICTURE()" + CHR(13) + ;
  "Dimensiones: " + TRANSFORM(lnWidth) + " x " + TRANSFORM(lnHeight))

3.- Obtener la información de la cabecera del archivo imagen

Las dimensiones de la imagen se almacenan en sus binarios. El siguiente código utiliza FOPEN y FREAD para extraer esa información. Puede obtener las dimensiones para las imágenes tipo BMP, GIF y JPG.
* Técnica 3
* Obtener la información de la cabecera del archivo imagen
* Los ejemplos se han adaptado a partir de las funciones de Thomas Gehrke en West-Wind Wiki:
* http://www.west-wind.com/wiki/wc.dll?wc~JpgSizeFunction  
* http://www.west-wind.com/wiki/wc.dll?wc~GifSizeFunction 
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight, lcExt
lcExt = LOWER(JUSTEXT(lcPictureFile))
DO CASE
  CASE lcExt = "bmp"
    LOCAL lnHandle, lcBytes
    lnHandle = FOPEN(lcPictureFile)
    IF m.lnHandle > -1
      * Leer los primeros 27 bytes:
      lcBytes = FREAD( m.lnHandle, 27)
      = FCLOSE( m.lnHandle)
      lnWidth = CTOBIN(SUBSTR(lcBytes,19,4),"4RS")
      lnHeight = CTOBIN(SUBSTR(lcBytes,23,4),"4RS")
    ENDIF
  CASE lcExt = "gif"
    LOCAL lnHandle, lcBytes
    lnHandle = FOPEN(lcPictureFile)
    IF m.lnHandle > -1
      * Leer los primeros 10 bytes:
      lcBytes = FREAD( m.lnHandle, 10)
      = FCLOSE( m.lnHandle)
      lnWidth = CTOBIN(SUBSTR( m.lcBytes, 7, 2),"2RS")
      lnHeight = CTOBIN(SUBSTR( m.lcBytes, 9, 2),"2RS")
    ENDIF
  CASE lcExt = "jpg"
    LOCAL lnHandle, lcBytes
    lnHandle = FOPEN(lcPictureFile)
    IF m.lnHandle > -1
      LOCAL lnFileSize, lnCounter, lcBytes
      lnFileSize = FSEEK( m.lnHandle, 0, 2)
      lnCounter = 0
      = FSEEK( m.lnHandle, 0, 0)
      FOR lnCounter = 1 TO m.lnFileSize - 2
        lcBytes = FREAD( m.lnHandle, 3)  
        IF m.lcBytes = CHR(0) + CHR(17) + CHR(8) OR ;
          m.lcBytes = CHR(0) + CHR(11) + CHR(8)
          * ¡Encontrar las marcas de bloque para las dimensiones!
          lcBytes = FREAD( m.lnHandle, 4)
          EXIT
        ELSE
          = FSEEK( m.lnHandle, -2, 1)
        ENDIF
      ENDFOR
      = FCLOSE( m.lnHandle)

      lnWidth = CTOBIN(SUBSTR( m.lcBytes, 3, 2),"2S")
      lnHeight = CTOBIN(SUBSTR( m.lcBytes, 1, 2),"2S")
    ENDIF
ENDCASE
MESSAGEBOX("Información desde la cabecera de imagen" + CHR(13) + ;
  "Dimensiones: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))

4.- Utilizar GDIPlusX

GDI+ puede brindar esta información y muchas otras, fácilmente.

El ejemplo que muestro a continuación utiliza la biblioteca GdiPlusX de VFPX.
http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home
* Técnica 4
* Obtener la información de la imagen utilizando GDI+, con GdiPlusX
* http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home  
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx","vcx")))
WITH _SCREEN.System.Drawing
  * Crear un Bitmap nuevo
  LOCAL loBmp as xfcBitmap
  loBmp = .Bitmap.FromFile(lcPictureFile)
  lnWidth = loBmp.Width
  lnHeight = loBmp.Height
  loBmp = NULL
  MESSAGEBOX("Biblioteca GDI+ - GdiPlusX" + CHR(13) + ;
    "Dimensiones: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))
ENDWITH

5.- Utilizar GPIMAGE2

El ejemplo que se muestra a continuación utiliza la biblioteca GpImage de Alexander Golovlev. En el siguiente enlace puede encontrar la versión más reciente para esta clase que contiene algunas funciones Graphics, que he agregado: http://cchalom.sites.uol.com.br/GPIMAGE
* Técnica 5
* Obtener la información de la imagen utilizando GDI+, con GpImage2
* http://cchalom.sites.uol.com.br/GPIMAGE 
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
IF Not "gpImage" $ SET("Procedure")
  SET PROCEDURE TO gpImage ADDITIVE
ENDIF
loGdip = CREATEOBJECT("gpInit")
loBmp = CREATEOBJECT("gpImage")
loBmp.Load(lcPictureFile)
lnWidth = loBmp.ImageWidth
lnHeight = loBmp.ImageHeight
loBmp = NULL
loGdip = NULL
MESSAGEBOX("GDI+ library - GpImage2" + CHR(13) + ;
  "Dimensiones: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))

6.- Utilizar _GDIPLUS.VCX

El siguiente ejemplo utiliza la biblioteca de clases Foundations (FCC) _GdiPlus.vcx de Walter Nicholls, liberada con VFP9.
* Técnica 6
* Obtener la información de la imagen utilizando GDI+, con _GdiPlus.vcx, de Walter Nicholls
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
LOCAL loBitmap as GpBitmap OF HOME() + "/FFC/_GdiPlus.vcx"
loBitmap = NEWOBJECT("GpBitmap", HOME() + "/FFC/_GdiPlus.vcx")
loBitmap.CreateFromFile(lcPictureFile)
lnWidth = loBitmap.ImageWidth
lnHeight = loBitmap.ImageHeight
loBitmap = NULL
MESSAGEBOX("Biblioteca GDI+ - FFC _GdiPlus.vcx" + CHR(13) + ;
  "Dimensiones: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))

7.- Utilizar GDIPLUS con llamadas directas a API

Si no desea utilizar ninguna clase envoltorio GDI+, he aquí un código que obtiene las dimensiones de la imagen utilizando llamadas directas de API a gdiplus.dll. Asegúrese de tener gdiplus.dll en su sistema.

Gdiplus.dll está disponible gratis y se puede instalar con Win98 y superior. Si no tiene instalado WinXP or .NET runtime entonces debe bajar esta DLL desde http://www.microsoft.com/downloads/details.aspx?FamilyID=6a63ab9c-df12-4d41-933c-be590feaa05a&DisplayLang=en o directamente desde http://download.microsoft.com/download/platformsdk/redist/3097/W98NT42KMeXP/EN-US/gdiplus_dnld.exe

Puede obtener información valiosa sobre GDIPlus en el sitio oficial de Microsoft
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/GDIPlus/GDIPlusreference/flatgraphics.asp
* Técnica 7
* Obtener información de la imagen utilizando GDI+, con lamadas directas de API
LOCAL lcPictureFile
lcPictureFile = GETPICT()

* API Declarations for GDI+
DECLARE LONG GdiplusStartup IN GDIPLUS.DLL ;
  LONG @ token, STRING @ INPUT, LONG @ OUTPUT
DECLARE LONG GdiplusShutdown IN GDIPLUS.DLL LONG token
DECLARE INTEGER GdipLoadImageFromFile IN GDIPLUS.DLL ;
  STRING wFilename, INTEGER @ nImage
DECLARE INTEGER GdipDisposeImage IN GDIPLUS.DLL INTEGER nImage
DECLARE INTEGER GdipGetImageWidth IN GDIPLUS.DLL ;
  INTEGER nImage, INTEGER @ nWidth
DECLARE INTEGER GdipGetImageHeight IN GDIPLUS.DLL ;
  INTEGER nImage, INTEGER @ nHeight

* Inicializar GDI+.
LOCAL gdiplusStartupInput, lhGdiPlusToken
gdiplusStartupInput = CHR(1) + REPLICATE(CHR(0), 15)
lhGdiPlusToken = 0
IF GdiplusStartup(@lhGdiPlusToken, @gdiplusStartupInput, 0) != 0
  RETURN .F.
ENDIF
* Cargar el objeto Picture
LOCAL lnPictHandle
lnPictHandle = 0
= GdipLoadImageFromFile( STRCONV(lcPictureFile + CHR(0),5), @lnPictHandle)
* Obtener las dimensiones de la imagen
LOCAL lnWidth, lnHeight
STORE 0 TO lnWidth, lnHeight
= GdipGetImageWidth(lnPictHandle, @lnWidth)
= GdipGetImageHeight(lnPictHandle, @lnHeight)
* Limpiar el controlador principal GDI+ 
= GdiplusShutdown(lhGdiPlusToken)
MESSAGEBOX("GDI+ con llamadas API" + CHR(13) + ;
  "Dimensiones: " + TRANSFORM(lnWidth) + " x " + TRANSFORM(lnHeight))

Espero que esto ayude

¡ Que lo disfruten !

No hay comentarios. :

Publicar un comentario