测试环境:Linux Fedora16 +Windows
打开图片的工具:UltraEdit
截图工具:FSCaptrue
源码下载:https://download.csdn.net/download/psy6653/10291445
写Exif信息前,图片的相关数据,以下是图片开始的数据排布;
图片以0xFF 0xD8开始,0xFF 0xE0就是图片下一个数据块开始的标示,0x00 0x10表示该数据块的长度,长度包括标示(0xFF 0xE0)2个字节;
以下是图片结束的数据排布,注意,从0开始算结束地址为0x0003515c,但数据大小是0x0003515d个字节
根据我们程序的打印信息,可知
写入的Exif信息数据大小:1162个字节_十六进制:0x48a
原始图片数据的大小:(217435+2)个字节(开始的0xFF 0xD8的2个字节)__十六进制:0x3515d
输出图片数据大小:(218597+2)个字节(开始的0xFF 0xD8的2个字节)__十六进制:0x355e7
0x48a + 0x3515d = 0x355e7
在JPG图片写数据开始的位置:
在JPG图片写数据结束的位置:
结束的地址为0x000048b,写入数据的大小0x000048b-2+1=0x48a;减去0xFF 0xD8两个字节,地址从0开始计算,所以写入数据的总大小还要加1;后面0xFF 0xE0开始的数据就是图片原始的数据;
在JPG图片结束的位置:
与程序计算的一致;
效果如下:
写入数据之前,Windows解析图片的效果如下:
写入数据后,Windows解析图片的效果如下:
当然也可以写入自己构造的数据,用VC编写软件把数据按自己的构造的格式解析出来(PC报告软件的制作);
如果exif信息的数据量太大,就需要分块写入,并需要区分不同块的数据。如果需要源码,可以用我在本平台上传的资源(https://download.csdn.net/download/psy6653/10291445),JPEG的Exif信息读写的C语言实现,文件其中包含
————-1.将缓冲区数据添加到JPEG图片中
————-2.将JPEG图片X数据提取到缓冲区中
————-3.将文件里的数据添加到JPEG图片中
————-4.将JPEG图片X数据提取出来,生成新的数据文件
————-5.将缓冲区里的数据添加到JPEG图片中,生成新的JPEGX图片
————-6.将文件里的数据添加到JPEG图片中,生成新的JPEGX图片
以下是本案例的源码,exif信息有冗余的自己可以修改;
程序代码
#ifndef __EXIFPARAM_H__
#define __EXIFPARAM_H__
#endif
typedef unsigned char UCHAR;
typedef unsigned long ULONG;
typedef unsigned int UINT;
typedef unsigned long DWORD;
typedef unsigned int UINT32;
typedef int INT32;
typedef unsigned char UINT8;
typedef enum {
FALSE, TRUE} BOOL;
typedef struct tagExifFileInfo
{
char Make[32];
char Model[32];
char Version[32];
char DateTime[32];
char CopyRight[32];
UINT Height;
UINT Width;
UINT Orientation;
UINT ColorSpace;
UINT Process;
UINT Flash;
UINT FocalLengthNum;
UINT FocalLengthDen;
UINT ExposureTimeNum;
UINT ExposureTimeDen;
UINT FNumberNum;
UINT FNumberDen;
UINT ApertureFNumber;
int SubjectDistanceNum;
int SubjectDistanceDen;
UINT CCDWidth;
int ExposureBiasNum;
int ExposureBiasDen;
int WhiteBalance;
UINT MeteringMode;
int ExposureProgram;
UINT ISOSpeedRatings[2];
UINT FocalPlaneXResolutionNum;
UINT FocalPlaneXResolutionDen;
UINT FocalPlaneYResolutionNum;
UINT FocalPlaneYResolutionDen;
UINT FocalPlaneResolutionUnit;
UINT XResolutionNum;
UINT XResolutionDen;
UINT YResolutionNum;
UINT YResolutionDen;
UINT RUnit;
int BrightnessNum;
int BrightnessDen;
char UserComments[150];
UCHAR GpsLatitudeRef;
UCHAR GpsLatitude[20];
UCHAR GpsLongitudeRef;
UCHAR GpsLongitude[20];
UCHAR GpsAltitude[10];
}ExifFileInfo;
makeExif.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "exifparam.h"
#define IN
#define OUT
#define UCHAR unsigned char
#define SATIR
#define EXIF_FILE_SIZE 28800
#define MAX_JPG_THUMBNAIL_WIDTH 320
#define MAX_JPG_THUMBNAIL_HEIGHT 240
#define MAX_FILE_THUMB_SIZE (MAX_JPG_THUMBNAIL_WIDTH * MAX_JPG_THUMBNAIL_HEIGHT)
static const int APP1HeaderLen = 0x0C;
static UCHAR APP1Marker[] = {
0xFF, 0xE1};
static UCHAR SATTag[] = {
'S', 'A', 'T', 'I', 'R', 0x0};
static UCHAR MAX_APP1_LEN[] = {
0xFF, 0xFE};
static const int MAX_DATA_LEN = 0xFFF4;
UCHAR ExifHeader[6]=
{
0x45,0x78,0x69,0x66,0x00,0x00
};
UCHAR TIFFHeader[8]=
{
0x49,0x49,0x2A,0x00,0x08,0x00,0x00,0x00
};
typedef union BytesOfShort
{
UCHAR b[2];
unsigned short s;
} BytesOfShort_t;
enum EXTRACT_DATE_JOB_STATE{
EXTRACT_START=0,
READ_EXIF_HEADER=1,
READ_CHECK_SAT_HEADER,
COPY_REMAINING_DATA,
EXTRACT_END
};
static int makeExifFile ( char *ExifOut, UINT *totalLen ,ExifFileInfo *exifFileInfo)
{
UCHAR *ExifInitialCount;
UCHAR *tempExif = ( UCHAR * ) ExifOut;
INT32 ExifSize;
UINT santemp;
UCHAR * startoftiff;
UCHAR * IFD1OffsetAddress;
UCHAR APP1Marker[2]= {
0xff,0xe1};
UCHAR ExifLen[4]={
0};
UCHAR Nentries[2]={
8,0};
UCHAR SubIFDNentries[2]={
18,0};
UCHAR IFD1Nentries[2]={
6,0};
UCHAR EndOfEntry[4]={
0};
//VARIABLES FOR THE MAKE OF THE CAMERA
UCHAR maketag[2]={
0xf,0x1};
UCHAR makeformat[2]={
0x2,0x0};
UCHAR Ncomponent[4]={
32,0x0,0x0,0x0};
char make[32];
UCHAR makeoffchar[4];
UCHAR * offset;
//VARIABLES FOR THE MODEL OF THE CAMERA
UCHAR modeltag[2]={
0x10,0x1};
UCHAR modelformat[2]={
0x2,0x0};
UCHAR NcomponentModel[4]={
32,0x0,0x0,0x0};
char model[32];
UCHAR modeloffchar[4];
//VARIABLES FOR THE ORIENTATION OF THE CAMERA
UCHAR orientationtag[2]={
0x12,0x1};
UCHAR orientationformat[2]={
0x3,0x0};
UCHAR NcomponentOrientation[4]={
0x1,0x0,0x0,0x0};
UINT Orientation[1];
UCHAR Orient[4] = {
0};
//VARIABLES FOR THE JPEG PROCESS
UCHAR Processtag[2]={
0x00,0x02};
UCHAR Processformat[2]={
0x3,0x0};
UCHAR NcomponentProcess[4]={
0x1,0x0,0x0,0x0};
UINT Process[1];
UCHAR Proc[4] = {
0};
//VARIABLES FOR THE X-RESOLUTION OF THE IMAGE
UCHAR XResolutiontag[2]={
0x1A,0x1};
UCHAR XResolutionformat[2]={
0x5,0x0};
UCHAR NcomponentXResolution[4]={
0x1,0x0,0x0,0x0};
UINT XResolutionNum[1];//={0x00000048};
UINT XResolutionDen[1];//={0x00000001};
UCHAR XResolutionoffchar[4];
UCHAR XResolutionNumChar[4];
UCHAR XResolutionDenChar[4];
//VARIABLES FOR THE Y-RESOLUTION OF THE IMAGE
UCHAR YResolutiontag[2]={
0x1B,0x1};
UCHAR YResolutionformat[2]={
0x5,0x0};
UCHAR NcomponentYResolution[4]={
0x1,0x0,0x0,0x0};
UINT YResolutionNum[1];//={0x00000048};
UINT YResolutionDen[1];//={0x00000001};
UCHAR YResolutionoffchar[4];
UCHAR YResolutionNumChar[4];
UCHAR YResolutionDenChar[4];
//VARIABLES FOR THE RESOLUTION UNIT OF THE CAMERA
UCHAR RUnittag[2]={
0x28,0x1};
UCHAR RUnitformat[2]={
0x3,0x0};
UCHAR NcomponentRUnit[4]={
0x1,0x0,0x0,0x0};
UINT RUnit[1];
UCHAR RUnitChar[4] = {
0};
//VARIABLES FOR THE VERSION NO OF THE SOFTWARE
UCHAR Versiontag[2]={
0x31,0x1};
UCHAR Versionformat[2]={
0x2,0x0};
UCHAR NcomponentVersion[4]={
32,0x0,0x0,0x0};
char Version[32];//="version 1.2";
UCHAR Versionoffchar[4];
//VARIABLES FOR THE DATE/TIME
UCHAR DateTimetag[2]={
0x32,0x1};
UCHAR DateTimeformat[2]={
0x2,0x0};
UCHAR NcomponentDateTime[4]={
20,0,0,0};
UCHAR DateTime[32];//="2006:6:09 15:17:32";
char DateTimeClose[1]={
0};
UCHAR DateTimeoffchar[4];
//VARIABLES FOR THE COPYRIGHT
UCHAR CopyRighttag[2]={
0x98,0x82};
UCHAR CopyRightformat[2]={
0x2,0x0};
UCHAR NcomponentCopyRight[4]={
32,0x0,0x0,0x0};
char CopyRight[32];
UCHAR CopyRightoffchar[4];
//VARIABLES FOR THE OFFSET TO SUBIFD
UCHAR SubIFDOffsettag[2]={
0x69,0x87};
UCHAR SubIFDOffsetformat[2]={
0x4,0x0};
UCHAR NcomponentSubIFDOffset[4]={
0x1,0x0,0x0,0x0};
UCHAR SubIFDOffsetChar[4] = {
0};
//VARIABLES FOR THE EXPOSURE TIME
UCHAR ExposureTimetag[2]={
0x9A,0x82};
UCHAR ExposureTimeformat[2]={
0x5,0x0};
UCHAR NcomponentExposureTime[4]={
0x1,0x0,0x0,0x0};
UINT ExposureTimeNum[1];
UINT ExposureTimeDen[1];
UCHAR ExposureTimeoffchar[4];
UCHAR ExposureTimeNumChar[4];
UCHAR ExposureTimeDenChar[4];
//VARIABLES FOR THE FNUMBER
UCHAR FNumbertag[2]={
0x9D,0x82};
UCHAR FNumberformat[2]={
0x5,0x0};
UCHAR NcomponentFNumber[4]={
0x1,0x0,0x0,0x0};
UINT FNumberNum[1];
UINT FNumberDen[1];
UCHAR FNumberoffchar[4];
UCHAR FNumberNumChar[4];
UCHAR FNumberDenChar[4];
//VARIABLES FOR THE EXPOSURE PROGRAM OF THE CAMERA
UCHAR ExposureProgramtag[2]={
0x22,0x88};
UCHAR ExposureProgramformat[2]={
0x3,0x0};
UCHAR NcomponentExposureProgram[4]={
0x1,0x0,0x0,0x0};
UINT ExposureProgram[1];
UCHAR ExposureProgramChar[4] = {
0};
//VARIABLES FOR THE ISO SPEED RATINGS OF THE CAMERA
UCHAR ISOSpeedRatingstag[2]={
0x27,0x88};
UCHAR ISOSpeedRatingsformat[2]={
0x3,0x0};
UCHAR NcomponentISOSpeedRatings[4]={
0x2,0x0,0x0,0x0};
unsigned short ISOSpeedRatings[2];
UCHAR ISOSpeedRatingsChar[4] = {
0};
//VARIABLES FOR THE BRIGHTNESS OF THE IMAGE
UCHAR Brightnesstag[2]={
0x03,0x92};
UCHAR Brightnessformat[2]={
0xA,0x0};
UCHAR NcomponentBrightness[4]={
0x1,0x0,0x0,0x0};
int BrightnessNum[1];
int BrightnessDen[1];
UCHAR Brightnessoffchar[4];
UCHAR BrightnessNumChar[4];
UCHAR BrightnessDenChar[4];
//VARIABLES FOR THE EXPOSURE Bias
UCHAR ExposureBiastag[2]={
0x04,0x92};
UCHAR ExposureBiasformat[2]={
0xA,0x0};
UCHAR NcomponentExposureBias[4]={
0x1,0x0,0x0,0x0};
int ExposureBiasNum[