¿Cómo mostrar archivos jpeg y leer exif en vc? (código)
Resumen: Este artículo describe un método relativamente simple para mostrar imágenes en JPEG, GIF y otros estándares de formato en Visual C++ 6.0, y proporciona una explicación detallada del proceso de implementación.
Palabras clave: Imagen, JPEG, GIF, Microsoft Visual C++ 6.0
1. Introducción
El estándar de compresión de imágenes JPEG es naturalmente un estándar de compresión de imágenes con pérdida, pero Debido a la insensibilidad de la visión humana, la calidad de la imagen después de la compresión básicamente no ha cambiado y pronto se volvió ampliamente reconocida con una tasa de compresión más alta. Aunque el formato GIF sólo admite 256 colores, tiene una alta tasa de compresión para imágenes con menos colores, superando incluso el estándar JPEG, y ha sido ampliamente reconocido. Sin embargo, como herramienta de desarrollo importante para muchos programadores, la biblioteca MFC de Microsoft Visual C++ 6.0 sólo tiene un buen soporte para archivos de mapa de bits BMP sin ningún tipo de compresión. Puede leer, mostrar, almacenar e incluso crear un bloque de memoria. Dado que las imágenes en formato BMP no han sido sometidas a ninguna compresión, ocuparán una gran cantidad de espacio ya sea que se utilicen como archivos externos del programa o como recursos internos del programa. En particular, estos últimos aumentarán considerablemente la duración del programa. archivo ejecutable. Se puede ver que si puede utilizar imágenes comprimidas en formato JPEG o GIF con mejor relación de compresión para reemplazar la aplicación de archivos BMP en VC, sin duda será muy atractivo.
2. Ideas de diseño
Aunque existen algunos controles Active X para operar y procesar imágenes en otros formatos como JPEG y GIF, generalmente no son muy convenientes de usar después de los experimentos. y exploración, hemos resumido un método simple para lograr las funciones anteriores con la ayuda del método OLE de la interfaz COM. Ahora lo presentamos de la siguiente manera para beneficio de los lectores:
A continuación usaremos el. Interfaz COM de IPicture, de la siguiente manera: Es necesario tener cierto conocimiento de esta interfaz de imagen: esta interfaz administra principalmente objetos de imagen y sus atributos. Los objetos de imagen proporcionan una abstracción independiente del lenguaje para mapas de bits, iconos y primitivas. Al igual que los objetos de fuente estándar, el sistema también proporciona implementaciones estándar de objetos de imagen. Sus interfaces principales son IPicture e IPictureDisp, esta última se deriva de la interfaz IDispatch para acceder a las propiedades de la imagen mediante automatización. Los objetos de imagen también admiten la interfaz externa IPropertyNotifySink para que los usuarios puedan tomar decisiones cuando cambian las propiedades de la imagen. El objeto de imagen también admite la interfaz IPersistStream, por lo que puede guardarse y cargarse desde un objeto de instancia de la interfaz IStream, y la interfaz IStream también admite la lectura y escritura de datos de objetos de flujo.
Podemos utilizar la función OleLoadPicture para cargar imágenes desde un flujo que contiene datos de imágenes. Esta función simplifica la creación de objetos de imagen basados en secuencias al crear un nuevo objeto de imagen e inicializarlo con el contenido de la secuencia.
Su prototipo de función es:
STDAPI OleLoadPicture( IStream * pStream, //Puntero al flujo que contiene datos de imagen
LONG lSize, //Bytes leídos del flujo Número
BOOL fRunmode, //Valor inicial correspondiente al atributo de imagen
REFIID riid, //Identificador de interfaz involucrado, que describe el tipo de puntero de interfaz a devolver
VOID ppvObj / / La dirección de la variable de puntero de interfaz utilizada en rrid);
3. Implementación específica
Antes de mostrar la imagen, primero debe obtener la ruta de almacenamiento del archivo de imagen. El cuadro de diálogo de apertura de archivos se utiliza para seleccionar el archivo de imagen. El nombre del archivo se almacena en la variable de tipo CString m_sPath:
CFileDialog dlg(TRUE,"jpg","*.jpg",
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
"Archivo JPEG (*.jpg)|*.jpg|Archivo GIF (*.gif)|*.gif||",NULL); p>
if(dlg.DoModal()==IDOK)
{
m_sPath=dlg.GetPathName();
Invalidate(); >
}
Para simplificar, el código para la visualización gráfica se escribe directamente en OnDraw en la clase de vista. Primero, abra el archivo, determine la disponibilidad del archivo y coloque el contenido del archivo en el. interfaz de flujo en el objeto IStream pStm:
IStream *pStm;
CFileStatus fstatus
archivo CFile
LONG cb;
……
if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,fstatus)&& ((cb = fstatus.m_size) != -1 ))
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
LPVOID pvData = NULL
if (hGlobal ! = NULL)
{
if ((pvData = GlobalLock(hGlobal)) != NULL)
{
archivo.ReadHuge (pvData, cb);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);
}
Luego, llame directamente a la función OleLoadPicture para cargar la imagen desde la secuencia:
IPicture *pPic
……
OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic));
Dado que esta función a veces causa fallas, se debe usar la macro SUCCEEDED para hacer algunas cosas. trabajo de protección adecuado El siguiente trabajo de visualización de imágenes solo puede continuar si los datos se cargan correctamente:
if(SUCCEEDED(OleLoadPicture(pStm,fst)
atus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))
{
OLE_XSIZE_HIMETRIC hmWidth
OLE_YSIZE_HIMETRIC hmHeight; > pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight
doble fX,fY
……
<; p> fX = (doble)pDC->GetDeviceCaps(HORZRES)*(doble)hmWidth/((doble)pDC->GetDeviceCaps(HORZSIZE)*100.0);fY = (doble)pDC-> GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0
if(FAILED(pPic->Render(*pDC,0,0,(DWORD) )fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL))) {
AfxMessageBox("¡Error al renderizar la imagen!");
pPic->); Release ();
}
else
AfxMessageBox("¡Error al cargar la imagen desde la transmisión!"); p >
Entre ellos, el trabajo de visualización se completa principalmente con la función Render del objeto de interfaz IPicture. Esta función se utiliza principalmente para dibujar la parte especificada de la imagen en la ubicación especificada en el entorno del dispositivo especificado. El prototipo es el siguiente:
HRESULT Render( HDC hdc, //Control del entorno del dispositivo para renderizar imágenes
long x, //Coordenada horizontal en hdc
long y, //coordenada vertical en hdc
long cx, //ancho de la imagen
long cy, //alto de la imagen
OLE_XPOS_HIMETRIC xSrc, //Horizontal desplazamiento en la imagen de origen
OLE_YPOS_HIMETRIC ySrc, //Desplazamiento vertical en la imagen de origen
OLE_XSIZE_HIMETRIC cxSrc, //El número de copias horizontales en la imagen de origen
OLE_YSIZE_HIMETRIC cySrc, //El número de copias verticales en la imagen de origen
LPCRECT prcWBounds //Puntero al identificador del entorno del dispositivo primitivo de destino
Resumen:
Hasta ahora, el código anterior ha podido mostrar imágenes estándar como JPEG y GIF en el área de cliente del programa. Sin embargo, para imágenes en formato GIF con múltiples cuadros de imágenes (es decir, animaciones), actualmente. Solo puede mostrar el primer cuadro. Si desea mostrar completamente todo el proceso de animación GIF, necesita el soporte de un control Active X externo.
PD: Este artículo está citado de Tianji.com. También hay un buen lugar para recomendarle un programador. Vaya a "CSDN" con más frecuencia, jaja.
También hay tres formas de leer la información EXIF de las imágenes.
Esta clase construye dos estructuras, MetadataDetail y Metadata. La primera se utiliza para almacenar tres tipos de información. un determinado elemento en el formato EXIF sirve como una conversión intermedia. Uno es la información del índice hexadecimal, el otro es el código de información sin procesar y el otro es la información de visualización.
Esta última estructura almacena todos los elementos de información EXIF de una imagen. Hay dos métodos LookupEXIFValue y GetEXIFMetaData. El primero maneja la visualización correspondiente de elementos especiales y el segundo lee información relevante de la imagen y la completa en la estructura MetaData.
usando System;
usando System.Drawing;
usando System.Drawing.Imaging;
usando System.Collections; p>
p>
usando System.ComponentModel;
espacio de nombres Test.Com
{
///
/ // Función: Obtener información EXIF de la imagen
/// Autor: Rexsp
/// Fecha de creación: 2004-03-20
///
clase pública EXIFMetaData
{
#constructor de región
///
/// Constructor
///
public EXIFMetaData()
{
} p>
#endregion
#estructura de conversión de datos de región
///
/// estructura de datos de conversión
///
public struct MetadataDetail
{
cadena pública Hex;//cadena hexadecimal
cadena pública RawValueAsString;//cadena de valor original
cadena pública DisplayValue;//cadena de valor de visualización
}
#endregion
#región Estructura del elemento EXIF
///
/// Estructura: almacena información del elemento EXIF
// /
public struct Metadata
{
public MetadataDetail EquipmentMake;
public MetadataDetail CameraModel;
public MetadataDetail ExposureTime ;//Tiempo de exposición
public MetadataDetail Fstop;
public MetadataDetail DatePictureToken;
public MetadataDetail ShutterSpeed;//Velocidad de obturación
public MetadataDetail MeteringMode;//Modo de exposición
public MetadataDetail Flash;//Flash
public MetadataDetail XResolution;
public MetadataDetail YResolution; p>
public MetadataDetail ImageWidth; //Ancho de la foto
public MetadataDet
ail ImageHeight;//Altura de la foto
public MetadataDetail FNumber;//valor f, número de apertura
public MetadataDetail ExposureProg;//programa de exposición
public MetadataDetail SpectralSense ;//
public MetadataDetail ISOSpeed;// sensibilidad ISO
public MetadataDetail OECF;//
public MetadataDetail Ver;// versión EXIF p >
public MetadataDetail CompConfig;//Configuración de color
public MetadataDetail CompBPP;//Relación de compresión
public MetadataDetail Aperture;//Valor de apertura
public MetadataDetail Brightness;//Valor de brillo Ev
public MetadataDetail ExposureBias;//Compensación de exposición
public MetadataDetail MaxAperture;//Valor máximo de apertura
public MetadataDetail SubjectDist ; //Distancia del sujeto
public MetadataDetail LightSource;//Balance de blancos
public MetadataDetail FocalLength;//Longitud focal
public MetadataDetail FPXVer;//FlashPix versión
p>public MetadataDetail ColorSpace;// espacio de color
public MetadataDetail Interop;//
public MetadataDetail FlashEnergy;//
público MetadataDetail SpatialFR; //
público MetadataDetail FocalXRes;//
público MetadataDetail FocalYRes;//
público MetadataDetail FocalResUnit;//
public MetadataDetail ExposureIndex;// Índice de exposición
public MetadataDetail SensingMethod;// Método de detección
public MetadataDetail SceneType;//
public MetadataDetail CfaPattern;/ /
}
#endregion
#region Buscar valor del elemento EXIF
cadena pública LookupEXIFValue(cadena Descripción, cadena Valor)
{
string DescripciónValor = null;
switch(Descripción)
{
case "MeteringMode":
#region MeteringMode
{
switch(Valor)
{
case "0":
DescripciónValor = "Desconocido";break;
case "1":
DescriptionValue = "Promedio";break;
case "2":
DescriptionValue = "Centro Promedio ponderado";break;
case "3":
DescripciónValor = "Spot";break;
case "4":
DescriptionValue = "Multi-segmento";break;
case "5":
DescriptionValue = "Multi-segmento";break;
case " 6":
DescriptionValue = "Partial";break;
case "255":
DescriptionValue = "Otro";break;
}
}
#endregion
break;
case "ResolutionUnit":
#region Unidad de resolución
{
switch(Valor)
{
case "1":
DescripciónValor = " Sin unidades";break;
case "2":
DescripciónValor = "Pulgadas";break;
case "3":
DescripciónValor = "Centímetro";romper;
}
}
#endregion
romper;
//Omitir N líneas de código similar
}
return DescripciónValor;
}
#endregion
#region Obtener la información EXIF de la imagen
metadatos públicos GetEXIFMetaData(string PhotoName)
{
// Crear una instancia de la imagen
System.Drawing.Image MiImagen = System.Dr
awing.Image.FromFile(PhotoName);
// Crea una matriz de números enteros para almacenar el ID de la matriz de propiedades en la imagen
int[] MyPropertyIdList = MyImage.PropertyIdList;
//Crea una instancia de una matriz de propiedades de imagen cerrada
PropertyItem[] MyPropertyItemList = new PropertyItem[MyPropertyIdList.Length];
//Crea una instancia de imagen EXIT información Estructurar objeto y asignar un valor inicial
#region Crear un objeto de estructura de instancia de imagen EXIT información y asignar un valor inicial
Metadatos MyMetadata = new Metadata();
MyMetadata.EquipmentMake.Hex = "10f";
MyMetadata.CameraModel.Hex = "110";
MyMetadata.DatePictureTaken.Hex = "9003" ;
MyMetadata.ExposureTime.Hex = "829a";
MyMetadata.Fstop.Hex = "829d";
MyMetadata.ShutterSpeed.Hex = "9201 ";
MyMetadata.MeteringMode.Hex = "9207";
MyMetadata.Flash.Hex = "9209";
MyMetadata.FNumber.Hex = " 829d"; //
MyMetadata.ExposureProg.Hex = ""; //
MyMetadata.SpectralSense.Hex = "8824"; //
MyMetadata .ISOSpeed.Hex = "8827"; //
MyMetadata.OECF.Hex = "8828"; //
MyMetadata.Ver.Hex = "9000"; /p>
MyMetadata.CompConfig.Hex = "9101"; //
MyMetadata.CompBPP.Hex = "9102" //
MyMetadata.Aperture.Hex = "9202"; / /
MyMetadata.Brightness.Hex = "9203"; //
MyMetadata.ExposureBias.Hex = "9204"; //
> MyMetadata.MaxAperture.Hex = "9205"; //
MyMetadata.SubjectDist.Hex = "9206"; //
MyMetadata.LightSource.Hex = "9208"; /
MyMetadata.FocalLength.Hex = "920a"; //
MyMetadata.FPXVer.Hex = "a000"; //
> MyMetadata.ColorSpace.Hex = "a001"; //
MyMetadata.FocalXRes.Hex = "a20e"; //
MyMetadata.FocalYRes.Hex = "a20f"; /
MyMetadata.FocalResUnit.Hex = "a210"; //
MyMetadata.ExposureIndex.Hex = "a215"; //
MyMetadata.SensingMethod. Hex = "a217"; //
MyMetadata.SceneType.Hex = "a301";
MyMetadata.CfaPattern.Hex = "a302";
# endregion
// codificación ASCII
System.Text.ASCIIEncoding Valor = new System.Text.ASCIIEncoding();
int index = 0;
int MyPropertyIdListCount=MyPropertyIdList.Length;
if(MyPropertyIdListCount!=0)
{
foreach (int MyPropertyId in MyPropertyIdList)
{
string hexVal = "";
MyPropertyItemList[index] = MyImage.GetPropertyItem(MyPropertyId);
#region Inicializa cada valor de propiedad
string myPropertyIdString=MyImage.GetPropertyItem(MyPropertyId).Id.ToString("x");
switch(myPropertyIdString)
{
case "10f":
{
MyMetadata.EquipmentMake.RawValueAsString =BitConverter.ToString(MyImage.GetPropertyItem (MyPropertyId).Value);
MyMetadata .EquipmentMake.DisplayValue = Value.GetString(MyPropertyItemList[index].Value);
break;
}
case "110":
{
MyMetadata.CameraModel.RawValueAsString =BitConverter.ToString(MyImage.GetPropertyItem(MyPropertyId).Value);
MyMetadata.CameraModel.DisplayValue =Value.Ge
tString(MyPropertyItemList[index].Value);
break;
}
case "9003":
{
MyMetadata.DatePictureTaken.RawValueAsString =BitConverter.ToString(MyImage.GetPropertyItem(MyPropertyId).Value);
MyMetadata.DatePictureTaken.DisplayValue =Value.GetString(MyPropertyItemList[index].Value);
break;
}
//Omitir N líneas de código similar
}
#endregion p >
index++;
}
}
MyMetadata.XResolution.DisplayValue = MyImage.HorizontalResolution.ToString();
MyMetadata.YResolution.DisplayValue = MyImage.VerticalResolution.ToString();
MyMetadata.ImageHeight.DisplayValue = MyImage.Height.ToString();
MyMetadata.ImageWidth.DisplayValue = MyImage Ancho.ToString();
MyImage.Dispose();
devolver MyMetadata;
}
#endregion
}
}
Entonces está la cuestión de llamar. Con esta clase, ¿cómo leo la información EXIF de la imagen? El código es el siguiente:
EXIFMetaData em = new EXIFMetaData();
string filePath=Server.MapPath("Test.jpg");//Puedes pasar la imagen dinámicamente ruta aquí p>
EXIFMetaData.Metadata m = em.GetEXIFMetaData(filePath);//Esta es la llamada, pasando la ruta absoluta de la imagen
cadena exif = m.Ver.DisplayValue ;
cadena de cámara = m.CameraModel.DisplayValue;
cadena de modelo = m.CameraModel.DisplayValue;
cadena de apertura = m.Aperture.DisplayValue;
string obturador = m.ShutterSpeed.DisplayValue;
cadena sensible = m.ExposureIndex.DisplayValue;
Este código ha sido probado y funciona correctamente.