?? exif.c
字號:
/*-----------------------------------------------------------------------------\
@ModuleName :: EXIF.c
@Description :: EXIF 2.1 Wrapper for JPEG bitstream
For more info on EXIF refer EXIF 2.1 specification
Assumptions :
EXIF Writer
1. Image JPEG
2. No thumbnail
3. Support all Mandatory tags and few optional tags.
4. Make provision to extend support for thumbnails, other optional tags.
5. Generates Big Endian Data
EXIF Reader
1. Parse all tags.
2. Evaluate all mandatory tags and the few optional tags supported by EXIF writer.
3. Make provision to extend evaluation for thumbnails, other optional tags.
4. Will parse both Big and Little Endian Exif Files
@Copyright :: Copyright 2001- Texas Instruments, Inc.
@History ::
-------------------------------------------------------------------------------
Dec. 26, 2001 Kedar C (kedarc@ti.com) Start
\-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------\
@Modification :: Added Thumbnail to EXIF Wrapper
May. 23, 2002 Manoj Gopalakrishnan
\-------------------------------------------------------------------------------*/
/* include files */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <demo/exif.h>
/* global variables */
/* size of each EXIF data format type */
int EXIFTypeSize[] = {
0, 1, 1, 2, 4, 8,
0, 1, 0, 4, 8
};
/* Module Routines */
/*-----------------------------------------------------------------------------\
@RoutineName :: EXIFInitParams
@Description ::
Init EXIF Configuration structure
@Parameters ::
EXIFParams *prmExif :: The EXIF Configuration structure
Uint8 *jpegAddr :: The JPEG Image Address
Uint32 size :: The size of JPEG Image
@Return ::
E_PASS, success
E_DEVICE, failure
\-----------------------------------------------------------------------------*/
STATUS EXIFInitParams( EXIFParams *prmExif, Uint8 *jpegAddr, Uint32 size,Uint8 *thumbAddr, Uint32 thumbSize) {
prmExif->bswap = FALSE; /* by default big Endian code is generated */
prmExif->make = (Uint8*)malloc( strlen(EXIF_MAKE) + 1 );
strcpy((char*)prmExif->make, EXIF_MAKE);
prmExif->model = (Uint8*)malloc( strlen(EXIF_MODEL) + 1 );
strcpy((char*)prmExif->model, EXIF_MODEL);
prmExif->copyright = (Uint8*)malloc( strlen(EXIF_COPYRIGHT) + 1 );
strcpy((char*)prmExif->copyright, EXIF_COPYRIGHT);
prmExif->software = (Uint8*)malloc( strlen(EXIF_SOFTWARE) + 1 );
strcpy((char*)prmExif->software, EXIF_SOFTWARE);
prmExif->XRes = EXIF_XRES;
prmExif->YRes = EXIF_YRES;
prmExif->ResUnit = EXIF_RES_UNIT;
prmExif->YCbCrPosition = EXIF_YCrCb_POS;
prmExif->EXIFVersion = EXIF_VERSION; /* '0210' */
prmExif->CompConf = EXIF_COMP_CONF;
prmExif->ColorSpace = EXIF_COLOR_SPACE;
{ /* calculate height and width of the main image */
Uint8 *ptr;
Uint16 word16;
ptr=jpegAddr+2;
word16=get_word16(ptr);
while( word16!=0xFFC0 && word16!=0xFFDA
&& (Uint32)(ptr-jpegAddr) < size && ( word16 & 0xFF00 )==0xFF00
) {
ptr += (2+get_word16(ptr+2) );
word16=get_word16(ptr);
}
if(word16==0xFFC0) {
prmExif->PixXDim = get_word16(ptr + 7);
prmExif->PixYDim = get_word16(ptr + 5);
} else {
prmExif->PixXDim = 0;
prmExif->PixYDim = 0;
}
}
prmExif->thumbPresent=TRUE;
prmExif->thumbAddr=thumbAddr;
prmExif->thumbSize=thumbSize;
prmExif->IFD1OffsetField=0;
prmExif->compression=6;
prmExif->thumbDataOffsetField=0;
return E_PASS;
}
/*-----------------------------------------------------------------------------\
@RoutineName :: EXIFShowParams
@Description ::
Displays EXIF Configuration structure on stdout
@Parameters ::
EXIFParams *prmExif :: The EXIF Configuration structure
@Return ::
E_PASS, success
E_DEVICE, failure
\-----------------------------------------------------------------------------*/
STATUS EXIFShowParams( EXIFParams *prmExif) {
printf("\n");
printf("\nEXIF Parameters :");
printf("\n===================");
printf("\nMake : %s", prmExif->make );
printf("\nModel : %s", prmExif->model);
printf("\nCopyright : %s", prmExif->copyright);
printf("\nSoftware : %s", prmExif->software);
printf("\nExif Version : %c.%c", (char)(prmExif->EXIFVersion >> 16), (char)(prmExif->EXIFVersion >> 8) );
printf("\nImage Width : %d", prmExif->PixXDim);
printf("\nImage Height : %d", prmExif->PixYDim);
printf("\nX Resolution : %ld pixels/unit", prmExif->XRes);
printf("\nY Resolution : %ld pixels/unit", prmExif->YRes);
printf("\nResolution Unit : ");
switch(prmExif->ResUnit) {
case 2 :
printf("inches");
break;
case 3 :
printf("centimeters");
break;
default :
printf("Unknown");
break;
}
printf("\nYCbCr Positioning : ");
switch(prmExif->YCbCrPosition) {
case 1 :
printf("center");
break;
case 2 :
printf("co-site");
break;
default :
printf("Unknown");
break;
}
printf("\nColor Space : ");
switch(prmExif->ColorSpace) {
case 1 :
printf("sRGB");
break;
case 0xFFFF :
printf("Uncalibrated");
break;
default :
printf("Unknown");
break;
}
printf("\nComponent Config : %x %x %x %x", (Uint8)(prmExif->CompConf >> 24 ),
(Uint8)(prmExif->CompConf >> 16 ),
(Uint8)(prmExif->CompConf >> 8 ),
(Uint8)(prmExif->CompConf )
);
if(prmExif->thumbPresent){
printf("\nThumbnail present" );
printf("\nThumbnail offset from start of APP1 marker : %ld B",prmExif->thumbDataOffset+TIFF_HEADER_OFFSET);
printf("\nThumbnail size : %ld B",prmExif->thumbSize);
}else{
printf("\nNo Thumbnail" );
}
return 1;
}
/*-----------------------------------------------------------------------------\
@RoutineName :: EXIFFreeParams
@Description ::
Free EXIF Configuration structure fields
@Parameters ::
EXIFParams *prmExif :: The EXIF Configuration structure
@Return ::
E_PASS, success
E_DEVICE, failure
\-----------------------------------------------------------------------------*/
STATUS EXIFFreeParams( EXIFParams *prmExif) {
if( prmExif->make != NULL )
free( prmExif->make);
if( prmExif->model != NULL )
free( prmExif->model);
if( prmExif->copyright != NULL )
free( prmExif->copyright);
if( prmExif->software != NULL )
free( prmExif->software);
return E_PASS;
}
/*-----------------------------------------------------------------------------\
@RoutineName :: EXIFMakeHeader
@Description ::
Creates the EXIF header based on the EXIF configuration structure
@Parameters ::
EXIFParams *prmExif :: The EXIF Configuration structure
Uint8 *exifHeader :: The Address where the Header will stored
Uint32 *exifSize :: The Size of the EXIF header
@Return ::
E_PASS, success
E_DEVICE, failure
\-----------------------------------------------------------------------------*/
STATUS EXIFMakeHeader( EXIFParams *prmExif, Uint8 *exifHeader, Uint32 *exifSize) {
WordStream exif ;
Uint32 app1_size_ptr;
exif.addr = exifHeader;
exif.ix = 0;
/* generate APP1 and TIFF header */
/* APP1 Header */
put_word16( &exif, EXIF_APP1_TAG ); /* 0xFFE1 */
app1_size_ptr = exif.ix;
put_word16( &exif, 0 ); /* size, will be filled at the end */
put_word32( &exif, MAKE_TAG('E','x','i','f')); /* 'Exif' */
put_word16( &exif, 0 ); /* 0x0000 */
/* TIFF Header */
put_word16(&exif, ( 'M' << 8 ) + 'M' ); /* 'MM' */
put_word16(&exif, 0x002a ); /* TIFF tag 0x002a */
put_word32(&exif, 0x00000008 ); /* 0x00000008 */
/* generate IFD0 */
EXIFMakeIFD0(prmExif, &exif );
/* generate IFD EXIF */
EXIFMakeIFDExif(prmExif, &exif );
/* update the IFD1 offset field in IFD0 */
{
Uint32 temp;
temp=exif.ix;
exif.ix=prmExif->IFD1OffsetField;
put_word32(&exif,temp-TIFF_HEADER_OFFSET);
exif.ix=temp;
}
EXIFMakeIFD1(prmExif,&exif);
/* update the Thumbnail data offset field in IFD1 */
{
Uint32 temp;
temp=exif.ix;
exif.ix=prmExif->thumbDataOffsetField;
put_word32(&exif,temp-TIFF_HEADER_OFFSET);
prmExif->thumbDataOffset=temp-TIFF_HEADER_OFFSET;
exif.ix=temp;
}
memcpy((exif.addr+exif.ix),prmExif->thumbAddr,prmExif->thumbSize);
exif.ix+=prmExif->thumbSize;
/* calculate APP1 size */
{
Uint32 size;
size = exif.ix;
exif.ix = app1_size_ptr;
put_word16(&exif, size - 2);
exif.ix = size;
}
*exifSize = exif.ix;
return E_PASS;
}
/*-----------------------------------------------------------------------------\
@RoutineName :: EXIFMakeIFD0
@Description ::
Creates the EXIF IFD0 based on the EXIF configuration structure
@Parameters ::
EXIFParams *prmExif :: The EXIF Configuration structure
WordStream *exif :: The EXIF Header data stream
@Return ::
E_PASS, success
E_DEVICE, failure
\-----------------------------------------------------------------------------*/
STATUS EXIFMakeIFD0(EXIFParams *prmExif, WordStream *exif ) {
Uint16 tag_count;
WordStream data;
tag_count = 9;
put_word16(exif, tag_count );
/* point 'data' to IFD0 Value Area */
data.addr = exif->addr + TIFF_HEADER_OFFSET; /* Points to TIFF header */
data.ix =
exif->ix /* offset into data stream */
+ tag_count*12 /* tag array size */
- TIFF_HEADER_OFFSET /* offset of TIFF header from APP1 marker */
+ 4 /* skip over next IFD offset field */
;
/* Tag 1 */
ExifMakeTag(exif, EXIF_MAKE_TAG, EXIF_ASCII, strlen((char*)prmExif->make)+1, data.ix);
put_str(&data, prmExif->make);
/* Tag 2 */
ExifMakeTag(exif, EXIF_MODEL_TAG, EXIF_ASCII, strlen((char*)prmExif->model)+1, data.ix);
put_str(&data, prmExif->model);
/* Tag 3 */
ExifMakeTag(exif, EXIF_XRES_TAG, EXIF_RATIONAL, 1, data.ix);
put_word32(&data, prmExif->XRes);
put_word32(&data, 1);
/* Tag 4 */
ExifMakeTag(exif, EXIF_YRES_TAG, EXIF_RATIONAL, 1, data.ix);
put_word32(&data, prmExif->YRes);
put_word32(&data, 1);
/* Tag 5 */
ExifMakeTag(exif, EXIF_RES_UNIT_TAG, EXIF_SHORT, 1, prmExif->ResUnit << 16);
/* Tag 6 */
ExifMakeTag(exif, EXIF_SOFTWARE_TAG, EXIF_ASCII, strlen((char*)prmExif->software)+1, data.ix);
put_str(&data, prmExif->software);
/* Tag 7 */
ExifMakeTag(exif, EXIF_YCBCR_POSITION_TAG, EXIF_SHORT, 1, prmExif->YCbCrPosition << 16);
/* Tag 8 */
ExifMakeTag(exif, EXIF_COPYRIGHT_TAG, EXIF_ASCII, strlen((char*)prmExif->copyright)+1, data.ix);
put_str(&data, prmExif->copyright);
/* Tag 9 */
ExifMakeTag(exif, EXIF_EXIF_IFD_PTR_TAG, EXIF_LONG, 1, data.ix );
/* store IFD1 offset to be filled later*/ //added by Manoj
prmExif->IFD1OffsetField = exif->ix;
/* put next IFD offset */
put_word32(exif, 0);
/* calculate offset into exif header */
exif->ix = data.ix + TIFF_HEADER_OFFSET;
return E_PASS;
}
/*-----------------------------------------------------------------------------\
@RoutineName :: EXIFMakeIFDExif
@Description ::
Creates the EXIF sub IFD ( EXIF specific IFD ) based on the EXIF configuration structure
@Parameters ::
EXIFParams *prmExif :: The EXIF Configuration structure
WordStream *exif :: The EXIF Header data stream
@Return ::
E_PASS, success
E_DEVICE, failure
\-----------------------------------------------------------------------------*/
STATUS EXIFMakeIFDExif(EXIFParams *prmExif, WordStream *exif ) {
Uint16 tag_count;
WordStream data;
tag_count = 5;
put_word16(exif, tag_count );
/* point 'data' to IFD0 Value Area */
data.addr = exif->addr + TIFF_HEADER_OFFSET; /* Points to TIFF header */
data.ix =
exif->ix /* offset into data stream */
+ tag_count*12 /* tag array size */
- TIFF_HEADER_OFFSET /* offset of TIFF header from APP1 marker */
+ 4 /* skip over next IFD offset field */
;
/* Tag 1 */
ExifMakeTag(exif, EXIF_EXIF_VERSION_TAG, EXIF_UNDEFINED, 4, prmExif->EXIFVersion);
/* Tag 2 */
ExifMakeTag(exif, EXIF_COMP_CONF_TAG, EXIF_UNDEFINED, 4, prmExif->CompConf);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -