为现有图像处理程序添加读取exif的功能

exif是图片的重要参数,在使用过程中很关键的一点是exif的数据能够和图片一起存在。exif的相关功能在操作系统中就集成了,在csharp中也似乎有了实现。但是使用mfc来实现这个功能,的确费了我的一些时间。下面是我的实现方式。
读取exif,参考了网络资料
添加cexif.h和cexif.cpp,添加入现有程序
在需要读取的地方添加相关代码
 
FILE* hFile=fopen(FilePathName.c_str(),"rb");
if (hFile){
memset(&m_exifinfo,0,sizeof(EXIFINFO));
Cexif exif(&m_exifinfo);
exif.DecodeExif(hFile);
fclose(hFile);
if (m_exifinfo.IsExif)
{
string cameramaker = m_exifinfo.CopyRight;//获得CopyRight
vector<string> vecParams;
if ("@@" == cameramaker.substr(0,2)) //确认为带参数图片
{
cameramaker = cameramaker.substr(2,cameramaker.length()-2);
SplitString(cameramaker,vecParams,"|");//保存各参数到vecParams中去
//updateGuides给的是图像真实像素值
if (vecParams.size()<13)
return;
m_freal2screen = Str2RealPixF(vecParams[12]);//获得之前保存的比值
if (m_freal2screen<0)
return;
UpdateGuides(Str2RealPix(vecParams[0]),Str2RealPix(vecParams[1]),Str2RealPix(vecParams[2]),Str2RealPix(vecParams[3]),Str2RealPix(vecParams[4]),Str2RealPix(vecParams[5]),Str2RealPix(vecParams[6]),Str2RealPix(vecParams[7]),Str2RealPix(vecParams[8]),Str2RealPix(vecParams[9]),Str2RealPix(vecParams[10]),Str2RealPix(vecParams[11]));
}
}
else
MessageBox("没有找到矢量数据信息!","EXIF",MB_OK);
}
fclose(hFile);

  

 
但是这里的exif读取的信息不实很全
同时找到另一个代码,但是版本比较老,只能在vc6下面运行
这个时候,我需要考虑的就是写入的数据是否够长的问题。我进行了边界测试
经过测试,在这种模式下是没有问题的
对原有代码进行初步修改就可以。考虑到还是现有集成的比较好用,还是用集成好的。但是集成好的版本没有 版权这个段?这个如何办了?
反思一想,问题不就出现在位置信息吗?我将正确的版权信息覆盖掉make信息,问题解决。
最后提供我修改完成的带版权信息的exif.c。
解决问题的思路很重要。

附全部代码

/*
* File: exif.cpp
* Purpose: cpp EXIF reader
* 16/Mar/2003 <ing.davide.pizzolato@libero.it>
* based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
*/
#include "stdafx.h"
#include "Exif.h" ////////////////////////////////////////////////////////////////////////////////
Cexif::Cexif(EXIFINFO* info)
{
if (info) {
m_exifinfo = info;
freeinfo = false;
} else {
m_exifinfo = new EXIFINFO;
memset(m_exifinfo,,sizeof(EXIFINFO));
freeinfo = true;
} m_szLastError[]='\0';
ExifImageWidth = MotorolaOrder = ;
SectionsRead=;
memset(&Sections, , MAX_SECTIONS * sizeof(Section_t));
}
////////////////////////////////////////////////////////////////////////////////
Cexif::~Cexif()
{
for(int i=;i<MAX_SECTIONS;i++) if(Sections[i].Data) free(Sections[i].Data);
if (freeinfo) delete m_exifinfo;
}
////////////////////////////////////////////////////////////////////////////////
bool Cexif::DecodeExif(FILE * hFile)
{
int a;
int HaveCom = ; a = fgetc(hFile); if (a != 0xff || fgetc(hFile) != M_SOI){
return ;
} for(;;){
int itemlen;
int marker = ;
int ll,lh, got;
unsigned char * Data; if (SectionsRead >= MAX_SECTIONS){
strcpy(m_szLastError,"Too many sections in jpg file");
return ;
} for (a=;a<;a++){
marker = fgetc(hFile);
if (marker != 0xff) break; if (a >= ){
printf("too many padding unsigned chars\n");
return ;
}
} if (marker == 0xff){
// 0xff is legal padding, but if we get that many, something's wrong.
strcpy(m_szLastError,"too many padding unsigned chars!");
return ;
} Sections[SectionsRead].Type = marker; // Read the length of the section.
lh = fgetc(hFile);
ll = fgetc(hFile); itemlen = (lh << ) | ll; if (itemlen < ){
strcpy(m_szLastError,"invalid marker");
return ;
} Sections[SectionsRead].Size = itemlen; Data = (unsigned char *)malloc(itemlen);
if (Data == NULL){
strcpy(m_szLastError,"Could not allocate memory");
return ;
}
Sections[SectionsRead].Data = Data; // Store first two pre-read unsigned chars.
Data[] = (unsigned char)lh;
Data[] = (unsigned char)ll; got = fread(Data+, , itemlen-,hFile); // Read the whole section.
if (got != itemlen-){
strcpy(m_szLastError,"Premature end of file?");
return ;
}
SectionsRead += ; switch(marker){ case M_SOS: // stop before hitting compressed data
// If reading entire image is requested, read the rest of the data.
/*if (ReadMode & READ_IMAGE){
int cp, ep, size;
// Determine how much file is left.
cp = ftell(infile);
fseek(infile, 0, SEEK_END);
ep = ftell(infile);
fseek(infile, cp, SEEK_SET); size = ep-cp;
Data = (uchar *)malloc(size);
if (Data == NULL){
strcpy(m_szLastError,"could not allocate data for entire image");
return 0;
} got = fread(Data, 1, size, infile);
if (got != size){
strcpy(m_szLastError,"could not read the rest of the image");
return 0;
} Sections[SectionsRead].Data = Data;
Sections[SectionsRead].Size = size;
Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
SectionsRead ++;
HaveAll = 1;
}*/
return ; case M_EOI: // in case it's a tables-only JPEG stream
printf("No image in jpeg!\n");
return ; case M_COM: // Comment section
if (HaveCom){
// Discard this section.
free(Sections[--SectionsRead].Data);
Sections[SectionsRead].Data=;
}else{
process_COM(Data, itemlen);
HaveCom = ;
}
break; case M_JFIF:
// Regular jpegs always have this tag, exif images have the exif
// marker instead, althogh ACDsee will write images with both markers.
// this program will re-create this marker on absence of exif marker.
// hence no need to keep the copy from the file.
free(Sections[--SectionsRead].Data);
Sections[SectionsRead].Data=;
break; case M_EXIF:
// Seen files from some 'U-lead' software with Vivitar scanner
// that uses marker 31 for non exif stuff. Thus make sure
// it says 'Exif' in the section before treating it as exif.
if (memcmp(Data+, "Exif", ) == ){
m_exifinfo->IsExif = process_EXIF((unsigned char *)Data+, itemlen);
}else{
// Discard this section.
free(Sections[--SectionsRead].Data);
Sections[SectionsRead].Data=;
}
break; case M_SOF0:
case M_SOF1:
case M_SOF2:
case M_SOF3:
case M_SOF5:
case M_SOF6:
case M_SOF7:
case M_SOF9:
case M_SOF10:
case M_SOF11:
case M_SOF13:
case M_SOF14:
case M_SOF15:
process_SOFn(Data, marker);
break;
default:
// Skip any other sections.
//if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);
break;
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Process a EXIF marker
Describes all the drivel that most digital cameras include...
--------------------------------------------------------------------------*/
bool Cexif::process_EXIF(unsigned char * CharBuf, unsigned int length)
{
m_exifinfo->FlashUsed = ;
/* If it's from a digicam, and it used flash, it says so. */
m_exifinfo->Comments[] = '\0'; /* Initial value - null string */ ExifImageWidth = ; { /* Check the EXIF header component */
static const unsigned char ExifHeader[] = "Exif\0\0";
if (memcmp(CharBuf+, ExifHeader,)){
strcpy(m_szLastError,"Incorrect Exif header");
return ;
}
} if (memcmp(CharBuf+,"II",) == ){
MotorolaOrder = ;
}else{
if (memcmp(CharBuf+,"MM",) == ){
MotorolaOrder = ;
}else{
strcpy(m_szLastError,"Invalid Exif alignment marker.");
return ;
}
} /* Check the next two values for correctness. */
if (Get16u(CharBuf+) != 0x2a){
strcpy(m_szLastError,"Invalid Exif start (1)");
return ;
} int FirstOffset = Get32u(CharBuf+);
if (FirstOffset < || FirstOffset > ){
// I used to ensure this was set to 8 (website I used indicated its 8)
// but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002)
strcpy(m_szLastError,"Suspicious offset of first IFD value");
return ;
} unsigned char * LastExifRefd = CharBuf; /* First directory starts 16 unsigned chars in. Offsets start at 8 unsigned chars in. */
if (!ProcessExifDir(CharBuf+, CharBuf+, length-, m_exifinfo, &LastExifRefd))
return ; /* This is how far the interesting (non thumbnail) part of the exif went. */
// int ExifSettingsLength = LastExifRefd - CharBuf; /* Compute the CCD width, in milimeters. */
if (m_exifinfo->FocalplaneXRes != ){
m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);
} return ;
}
//--------------------------------------------------------------------------
// Get 16 bits motorola order (always) for jpeg header stuff.
//--------------------------------------------------------------------------
int Cexif::Get16m(void * Short)
{
return (((unsigned char *)Short)[] << ) | ((unsigned char *)Short)[];
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Convert a 16 bit unsigned value from file's native unsigned char order
--------------------------------------------------------------------------*/
int Cexif::Get16u(void * Short)
{
if (MotorolaOrder){
return (((unsigned char *)Short)[] << ) | ((unsigned char *)Short)[];
}else{
return (((unsigned char *)Short)[] << ) | ((unsigned char *)Short)[];
}
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Convert a 32 bit signed value from file's native unsigned char order
--------------------------------------------------------------------------*/
long Cexif::Get32s(void * Long)
{
if (MotorolaOrder){
return ((( char *)Long)[] << ) | (((unsigned char *)Long)[] << )
| (((unsigned char *)Long)[] << ) | (((unsigned char *)Long)[] << );
}else{
return ((( char *)Long)[] << ) | (((unsigned char *)Long)[] << )
| (((unsigned char *)Long)[] << ) | (((unsigned char *)Long)[] << );
}
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Convert a 32 bit unsigned value from file's native unsigned char order
--------------------------------------------------------------------------*/
unsigned long Cexif::Get32u(void * Long)
{
return (unsigned long)Get32s(Long) & 0xffffffff;
}
//////////////////////////////////////////////////////////////////////////////// /* Describes format descriptor */
static const int BytesPerFormat[] = {,,,,,,,,,,,,};
#define NUM_FORMATS 12 #define FMT_BYTE 1
#define FMT_STRING 2
#define FMT_USHORT 3
#define FMT_ULONG 4
#define FMT_URATIONAL 5
#define FMT_SBYTE 6
#define FMT_UNDEFINED 7
#define FMT_SSHORT 8
#define FMT_SLONG 9
#define FMT_SRATIONAL 10
#define FMT_SINGLE 11
#define FMT_DOUBLE 12 /* Describes tag values */ #define TAG_EXIF_VERSION 0x9000
#define TAG_EXIF_OFFSET 0x8769
#define TAG_INTEROP_OFFSET 0xa005 //2016年11月25日15:55:46 修改TAG_MAKE
#define TAG_MAKE 0x010F
#define TAG_CP 0x8298
#define TAG_MODEL 0x0110 #define TAG_ORIENTATION 0x0112
#define TAG_XRESOLUTION 0x011A
#define TAG_YRESOLUTION 0x011B
#define TAG_RESOLUTIONUNIT 0x0128 #define TAG_EXPOSURETIME 0x829A
#define TAG_FNUMBER 0x829D #define TAG_SHUTTERSPEED 0x9201
#define TAG_APERTURE 0x9202
#define TAG_BRIGHTNESS 0x9203
#define TAG_MAXAPERTURE 0x9205
#define TAG_FOCALLENGTH 0x920A #define TAG_DATETIME_ORIGINAL 0x9003
#define TAG_USERCOMMENT 0x9286 #define TAG_SUBJECT_DISTANCE 0x9206
#define TAG_FLASH 0x9209 #define TAG_FOCALPLANEXRES 0xa20E
#define TAG_FOCALPLANEYRES 0xa20F
#define TAG_FOCALPLANEUNITS 0xa210
#define TAG_EXIF_IMAGEWIDTH 0xA002
#define TAG_EXIF_IMAGELENGTH 0xA003 /* the following is added 05-jan-2001 vcs */
#define TAG_EXPOSURE_BIAS 0x9204
#define TAG_WHITEBALANCE 0x9208
#define TAG_METERING_MODE 0x9207
#define TAG_EXPOSURE_PROGRAM 0x8822
#define TAG_ISO_EQUIVALENT 0x8827
#define TAG_COMPRESSION_LEVEL 0x9102 #define TAG_THUMBNAIL_OFFSET 0x0201
#define TAG_THUMBNAIL_LENGTH 0x0202 /*--------------------------------------------------------------------------
Process one of the nested EXIF directories.
--------------------------------------------------------------------------*/
bool Cexif::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP )
{
int de;
int a;
int NumDirEntries;
unsigned ThumbnailOffset = ;
unsigned ThumbnailSize = ; NumDirEntries = Get16u(DirStart); if ((DirStart++NumDirEntries*) > (OffsetBase+ExifLength)){
strcpy(m_szLastError,"Illegally sized directory");
return ;
} for (de=;de<NumDirEntries;de++){
int Tag, Format, Components;
unsigned char * ValuePtr;
/* This actually can point to a variety of things; it must be
cast to other types when used. But we use it as a unsigned char-by-unsigned char
cursor, so we declare it as a pointer to a generic unsigned char here.
*/
int BytesCount;
unsigned char * DirEntry;
DirEntry = DirStart++*de; Tag = Get16u(DirEntry);
Format = Get16u(DirEntry+);
Components = Get32u(DirEntry+); if ((Format-) >= NUM_FORMATS) {
/* (-1) catches illegal zero case as unsigned underflows to positive large */
strcpy(m_szLastError,"Illegal format code in EXIF dir");
return ;
} BytesCount = Components * BytesPerFormat[Format]; if (BytesCount > ){
unsigned OffsetVal;
OffsetVal = Get32u(DirEntry+);
/* If its bigger than 4 unsigned chars, the dir entry contains an offset.*/
if (OffsetVal+BytesCount > ExifLength){
/* Bogus pointer offset and / or unsigned charcount value */
strcpy(m_szLastError,"Illegal pointer offset value in EXIF.");
return ;
}
ValuePtr = OffsetBase+OffsetVal;
}else{
/* 4 unsigned chars or less and value is in the dir entry itself */
ValuePtr = DirEntry+;
} if (*LastExifRefdP < ValuePtr+BytesCount){
/* Keep track of last unsigned char in the exif header that was
actually referenced. That way, we know where the
discardable thumbnail data begins.
*/
*LastExifRefdP = ValuePtr+BytesCount;
} /* Extract useful components of tag */
switch(Tag){ case TAG_MAKE:
strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, );
break;
case TAG_CP:
strncpy(m_exifinfo->CopyRight, (char*)ValuePtr,MAX_COMMENT-);
break;
case TAG_MODEL:
strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, );
break; case TAG_EXIF_VERSION:
strncpy(m_exifinfo->Version,(char*)ValuePtr, );
break; case TAG_DATETIME_ORIGINAL:
strncpy(m_exifinfo->DateTime, (char*)ValuePtr, );
break; case TAG_USERCOMMENT:
// Olympus has this padded with trailing spaces. Remove these first.
for (a=BytesCount;;){
a--;
if (((char*)ValuePtr)[a] == ' '){
((char*)ValuePtr)[a] = '\0';
}else{
break;
}
if (a == ) break;
} /* Copy the comment */
if (memcmp(ValuePtr, "ASCII",) == ){
for (a=;a<;a++){
char c;
c = ((char*)ValuePtr)[a];
if (c != '\0' && c != ' '){
strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, );
break;
}
} }else{
strncpy(m_exifinfo->Comments, (char*)ValuePtr, );
}
break; case TAG_FNUMBER:
/* Simplest way of expressing aperture, so I trust it the most.
(overwrite previously computd value if there is one)
*/
m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_APERTURE:
case TAG_MAXAPERTURE:
/* More relevant info always comes earlier, so only
use this field if we don't have appropriate aperture
information yet.
*/
if (m_exifinfo->ApertureFNumber == ){
m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0)*0.5);
}
break; case TAG_BRIGHTNESS:
m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_FOCALLENGTH:
/* Nice digital cameras actually save the focal length
as a function of how farthey are zoomed in.
*/ m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_SUBJECT_DISTANCE:
/* Inidcates the distacne the autofocus camera is focused to.
Tends to be less accurate as distance increases.
*/
m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_EXPOSURETIME:
/* Simplest way of expressing exposure time, so I
trust it most. (overwrite previously computd value
if there is one)
*/
m_exifinfo->ExposureTime =
(float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_SHUTTERSPEED:
/* More complicated way of expressing exposure time,
so only use this value if we don't already have it
from somewhere else.
*/
if (m_exifinfo->ExposureTime == ){
m_exifinfo->ExposureTime = (float)
(/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0)));
}
break; case TAG_FLASH:
if ((int)ConvertAnyFormat(ValuePtr, Format) & ){
m_exifinfo->FlashUsed = ;
}else{
m_exifinfo->FlashUsed = ;
}
break; case TAG_ORIENTATION:
m_exifinfo->Orientation = (int)ConvertAnyFormat(ValuePtr, Format);
if (m_exifinfo->Orientation < || m_exifinfo->Orientation > ){
strcpy(m_szLastError,"Undefined rotation value");
m_exifinfo->Orientation = ;
}
break; case TAG_EXIF_IMAGELENGTH:
case TAG_EXIF_IMAGEWIDTH:
/* Use largest of height and width to deal with images
that have been rotated to portrait format.
*/
a = (int)ConvertAnyFormat(ValuePtr, Format);
if (ExifImageWidth < a) ExifImageWidth = a;
break; case TAG_FOCALPLANEXRES:
m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_FOCALPLANEYRES:
m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_RESOLUTIONUNIT:
switch((int)ConvertAnyFormat(ValuePtr, Format)){
case : m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */
case : m_exifinfo->ResolutionUnit = 1.0f; break;
case : m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/
case : m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/
case : m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/
}
break; case TAG_FOCALPLANEUNITS:
switch((int)ConvertAnyFormat(ValuePtr, Format)){
case : m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */
case : m_exifinfo->FocalplaneUnits = 1.0f; break;
case : m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/
case : m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/
case : m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/
}
break; // Remaining cases contributed by: Volker C. Schoech <schoech(at)gmx(dot)de> case TAG_EXPOSURE_BIAS:
m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);
break; case TAG_WHITEBALANCE:
m_exifinfo->Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_METERING_MODE:
m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_EXPOSURE_PROGRAM:
m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_ISO_EQUIVALENT:
m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
if ( m_exifinfo->ISOequivalent < ) m_exifinfo->ISOequivalent *= ;
break; case TAG_COMPRESSION_LEVEL:
m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_XRESOLUTION:
m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);
break;
case TAG_YRESOLUTION:
m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_THUMBNAIL_OFFSET:
ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
break; case TAG_THUMBNAIL_LENGTH:
ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
break; } if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){
unsigned char * SubdirStart;
SubdirStart = OffsetBase + Get32u(ValuePtr);
if (SubdirStart < OffsetBase ||
SubdirStart > OffsetBase+ExifLength){
strcpy(m_szLastError,"Illegal subdirectory link");
return ;
}
ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
continue;
}
} {
/* In addition to linking to subdirectories via exif tags,
there's also a potential link to another directory at the end
of each directory. This has got to be the result of a
committee!
*/
unsigned char * SubdirStart;
unsigned Offset;
Offset = Get16u(DirStart++*NumDirEntries);
if (Offset){
SubdirStart = OffsetBase + Offset;
if (SubdirStart < OffsetBase
|| SubdirStart > OffsetBase+ExifLength){
strcpy(m_szLastError,"Illegal subdirectory link");
return ;
}
ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
}
} if (ThumbnailSize && ThumbnailOffset){
if (ThumbnailSize + ThumbnailOffset <= ExifLength){
/* The thumbnail pointer appears to be valid. Store it. */
m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
m_exifinfo->ThumbnailSize = ThumbnailSize;
}
} return ;
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------------------------------------------
Evaluate number, be it int, rational, or float from directory.
--------------------------------------------------------------------------*/
double Cexif::ConvertAnyFormat(void * ValuePtr, int Format)
{
double Value;
Value = ; switch(Format){
case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
case FMT_BYTE: Value = *(unsigned char *)ValuePtr; break; case FMT_USHORT: Value = Get16u(ValuePtr); break;
case FMT_ULONG: Value = Get32u(ValuePtr); break; case FMT_URATIONAL:
case FMT_SRATIONAL:
{
int Num,Den;
Num = Get32s(ValuePtr);
Den = Get32s(+(char *)ValuePtr);
if (Den == ){
Value = ;
}else{
Value = (double)Num/Den;
}
break;
} case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break;
case FMT_SLONG: Value = Get32s(ValuePtr); break; /* Not sure if this is correct (never seen float used in Exif format)
*/
case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
case FMT_DOUBLE: Value = *(double *)ValuePtr; break;
}
return Value;
}
////////////////////////////////////////////////////////////////////////////////
void Cexif::process_COM (const unsigned char * Data, int length)
{
int ch;
char Comment[MAX_COMMENT+];
int nch;
int a; nch = ; if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure. for (a=;a<length;a++){
ch = Data[a]; if (ch == '\r' && Data[a+] == '\n') continue; // Remove cr followed by lf. if ((ch>=0x20) || ch == '\n' || ch == '\t'){
Comment[nch++] = (char)ch;
}else{
Comment[nch++] = '?';
}
} Comment[nch] = '\0'; // Null terminate //if (ShowTags) printf("COM marker comment: %s\n",Comment); strcpy(m_exifinfo->Comments,Comment);
}
////////////////////////////////////////////////////////////////////////////////
void Cexif::process_SOFn (const unsigned char * Data, int marker)
{
int data_precision, num_components; data_precision = Data[];
m_exifinfo->Height = Get16m((void*)(Data+));
m_exifinfo->Width = Get16m((void*)(Data+));
num_components = Data[]; if (num_components == ){
m_exifinfo->IsColor = ;
}else{
m_exifinfo->IsColor = ;
} m_exifinfo->Process = marker; //if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
// ImageInfo.Width, ImageInfo.Height, num_components, data_precision);
}
//////////////////////////////////////////////////////////////////////////////// //#include "stdafx.h"
/*
* File: exif.h
* Purpose: cpp EXIF reader
* 16/Mar/2003 <ing.davide.pizzolato@libero.it>
* based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
*/
//2016年11月25日 jsxyhelu 修改添加版权信息
#if !defined(__exif_h)
#define __exif_h #include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <malloc.h> #define MAX_COMMENT 65535
#define MAX_SECTIONS 20 typedef struct tag_ExifInfo {
char Version [];
char CameraMake [];
char CameraModel [];
char DateTime [];
char CopyRight [MAX_COMMENT];
int Height, Width;
int Orientation;
int IsColor;
int Process;
int FlashUsed;
float FocalLength;
float ExposureTime;
float ApertureFNumber;
float Distance;
float CCDWidth;
float ExposureBias;
int Whitebalance;
int MeteringMode;
int ExposureProgram;
int ISOequivalent;
int CompressionLevel;
float FocalplaneXRes;
float FocalplaneYRes;
float FocalplaneUnits;
float Xresolution;
float Yresolution;
float ResolutionUnit;
float Brightness;
char Comments[MAX_COMMENT]; unsigned char * ThumbnailPointer; /* Pointer at the thumbnail */
unsigned ThumbnailSize; /* Size of thumbnail. */ bool IsExif;
} EXIFINFO; //--------------------------------------------------------------------------
// JPEG markers consist of one or more 0xFF unsigned chars, followed by a marker
// code unsigned char (which is not an FF). Here are the marker codes of interest
// in this program. (See jdmarker.c for a more complete list.)
//-------------------------------------------------------------------------- #define M_SOF0 0xC0 // Start Of Frame N
#define M_SOF1 0xC1 // N indicates which compression process
#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
#define M_SOF3 0xC3
#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
#define M_SOF6 0xC6
#define M_SOF7 0xC7
#define M_SOF9 0xC9
#define M_SOF10 0xCA
#define M_SOF11 0xCB
#define M_SOF13 0xCD
#define M_SOF14 0xCE
#define M_SOF15 0xCF
#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
#define M_EOI 0xD9 // End Of Image (end of datastream)
#define M_SOS 0xDA // Start Of Scan (begins compressed data)
#define M_JFIF 0xE0 // Jfif marker
#define M_EXIF 0xE1 // Exif marker
#define M_COM 0xFE // COMment class Cexif
{ typedef struct tag_Section_t{
unsigned char* Data;
int Type;
unsigned Size;
} Section_t; public:
EXIFINFO* m_exifinfo;
char m_szLastError[];
Cexif(EXIFINFO* info = NULL);
~Cexif();
bool DecodeExif(FILE* hFile);
protected:
bool process_EXIF(unsigned char * CharBuf, unsigned int length);
void process_COM (const unsigned char * Data, int length);
void process_SOFn (const unsigned char * Data, int marker);
int Get16u(void * Short);
int Get16m(void * Short);
long Get32s(void * Long);
unsigned long Get32u(void * Long);
double ConvertAnyFormat(void * ValuePtr, int Format);
bool ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
EXIFINFO * const pInfo, unsigned char ** const LastExifRefdP);
int ExifImageWidth;
int MotorolaOrder;
Section_t Sections[MAX_SECTIONS];
int SectionsRead;
bool freeinfo;
}; #endif

为现有图像处理程序添加读写exif的功能的更多相关文章

  1. 基于qml创建最简单的图像处理程序(2)-使用c++&qml进行图像处理

     <基于qml创建最简单的图像处理程序>系列课程及配套代码基于qml创建最简单的图像处理程序(1)-基于qml创建界面http://www.cnblogs.com/jsxyhelu/p/8 ...

  2. 【4opencv】为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍

            基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题.对于c++语系的程序员来说,一般来说有QT/MFC两种考虑.QT的确功能强大,特别是QML编写andr ...

  3. 为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍

            基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题.对于c++语系的程序员来说,一般来说有QT/MFC两种考虑.QT的确功能强大,特别是QML编写andr ...

  4. C#/VB.NET 替换 PDF 文件上的现有图像

    我们都知道对PDF文件进行修改和编辑不是一件容易的事.但有时当我们想用新的图像来替换PDF文件上的现有图像时,该怎么办呢?别担心,本文将向您展示如何在 C#/VB.NET 中替换 PDF 文件中的现有 ...

  5. 基于qml创建最简单的图像处理程序(3)-使用opencv&qml进行图像处理

    <基于qml创建最简单的图像处理程序>系列课程及配套代码基于qml创建最简单的图像处理程序(1)-基于qml创建界面http://www.cnblogs.com/jsxyhelu/p/83 ...

  6. 基于qml创建最简单的图像处理程序(1)-基于qml创建界面

    <基于qml创建最简单的图像处理程序>系列课程及配套代码基于qml创建最简单的图像处理程序(1)-基于qml创建界面http://www.cnblogs.com/jsxyhelu/p/83 ...

  7. 向SQL Server 现有表中添加新列并添加描述.

    注: sql server 2005 及以上支持. 版本估计是不支持(工作环境2005,2008). 工作需要, 需要向SQL Server 现有表中添加新列并添加描述. 从而有个如下存储过程. (先 ...

  8. MFC读写EXIF信息,图片非占用

    MFC读写EXIF信息 读取有类库可以直接调用,网络上有直接可以用的:但是写Exif的资料非常少,我花了一点时间研究收集,终于成功. 将相关的资料共享.主要是借助gdi+,需要注意的地方很多   // ...

  9. 当重装eclipse后,给现有web项目添加tomcat的构建路径

    在eclipse“首选项”-“service environment”中配置好tomcat后,给现有web项目添加构建路径: 1.选中一个web项目右键选中“构建路径”-“配置构建路径”

随机推荐

  1. PHP preg_replace使用例子

    将 qwer://xxx/545/0 替换为 qwer://trading_system_xxx/0/545 $str = '<a href="qwer://xxx/545/0&quo ...

  2. 使用Qt5.7.0 VS2015版本生成兼容XP的可执行程序 good(从VS2012 update1开始支持xp和c++11)

    一.直接使用VS2012/VS2013/VS2015生成XP兼容的可执行程序 Visual Studio刚发布时没打补丁,称为RTM版,之后会陆续发布补丁,进行bug修复和功能增强.VS2010及之前 ...

  3. Emmet使用

    emmet官方文档 [翻译]Emmet (ZenCoding) 缩写语法 <!-- ul>li.item$*5 --> <ul> <li class="i ...

  4. asp.net 重定向的三种方法

    1.Server.Transfer("URL"): 服务器停止解析本页,保存此页转向前的数据后,再使页面转向到newPage.aspx, 并将转向前数据加上newPage.aspx ...

  5. ruby -检查数据类型

    HashObj={","language"=>"zh","make"=>"Apple"," ...

  6. JMeter学习-030-JMeter性能测试常用之事务控制器实例

    通常进行性能测试时,我们一般仅考虑主要的数据返回,不考虑页面渲染所需要的数据(例如:css.js.图片等).但当我们需要衡量打开一个页面(页面渲染完成)的性能时,我们就需要考虑完成页面渲染所需要的图片 ...

  7. ACM集训的1B。。。。黑色星期五。。。。2333333

    题目: 印象中有好多个13号是星期五,13号在星期五比在其他日子少吗?为了回答这个问题,写一个程序,要求计算每个月的十三号落在周一到周日的次数.给出N年的一个周期,要求计算1900年1月1日至1900 ...

  8. java解析XML(转载)

    使用Dom4j解析XML dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的 ...

  9. New line

    The concepts of line feed (LF) and carriage return (CR) are closely associated, and can be either co ...

  10. Java网络编程之流——readline()方法的bug

    readline()方法有一个隐含的bug,它不一定会把一个回车看作行的结束.相反,readline()只识别换行或回车/换行对.当在流中检测到回车时,readline()会在继续之前等待,查看下一个 ...