为现有图像处理程序添加读取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. css绘制特殊图形,meida查询,display inline-box间隙问题以及calc()函数

    本文同时发表于本人个人网站 www.yaoxiaowen.com 距离上一篇文章已经一个月了,相比于写代码,发现写文章的确是更需要坚持的事情.言归正传,梳理一下这一个月来,在写ife任务时,有必要记录 ...

  2. Kafka 解析

    Kafak采用硬盘顺序写入和内存映射文件技术提示性能.即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存.所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/ ...

  3. mac os 下的sublime --- 快捷键

    mac os 下的sublime ---列模式 http://www.oschina.net/question/249672_161413 触控板也可以的:左手同时按住 Option 和触控板左下角 ...

  4. 【转载】如何破解受保护的excel密码

    [工具] 1.电脑一台(安装有Microsoft Excel) 2.受保护excel一个 [步骤] 1.首先,打开受保护的Excel表格,按"ALT"+"F11" ...

  5. C++学习笔记 知识集锦(一)

    1.内存管理的开销 2.函数调用框架 3.类为什么要定义在头文件 4.C++的组合 5.在类的外部定义成员函数 6.bool类型为什么可以当做int类型 7.无符号保留原则 8.C++类型检查 9.何 ...

  6. C#操作Mongodb的心得

    Mongodb是一个强大的文档型数据库,采用BSON的数据格式.本文主要采用其官方的C#驱动来操作其表中的集合.驱动版本为1.1.0,下载地址为: http://mongodb.github.io/m ...

  7. BeanUtils

    BeanUtils包的使用   BeanUtils工具包是由Apache公司所开发,主要是方便程序员对Bean类能够进行简便的操作. 在使用BeanUtils工具包之前我们需要的Jar包有以下几种: ...

  8. iOS之在webView中引入本地html,image,js,css文件的方法 - sky//////////////////////////////////////ZZZZZZZZZZZZZZZ

    iOS之在webView中引入本地html,image,js,css文件的方法   2014-12-08 20:00:16CSDN-sky_2016-点击数:10292     项目需求 最近开发的项 ...

  9. People Tools catalog tables.

    People Tools catalog tables. Projects PSPROJECTDEFN — Project header table PSPROJECTITEM — Definitio ...

  10. docker-compose编写(英文)

    原文地址:https://docker.github.io/compose/compose-file/ Compose file reference The Compose file is a YAM ...