2011-01-12 07:42:14 +00:00
|
|
|
#include "exifwriter.h"
|
|
|
|
|
|
|
|
#include "jhead.h"
|
2011-02-18 15:49:31 +00:00
|
|
|
#define LOG_TAG "ExifWriterCamera"
|
2011-03-30 21:06:24 +00:00
|
|
|
//#define LOG_NDEBUG 0
|
2011-01-12 07:42:14 +00:00
|
|
|
|
|
|
|
#include <utils/Log.h>
|
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#define TAG_ORIENTATION 0x0112
|
|
|
|
#define TAG_MAKE 0x010F
|
|
|
|
#define TAG_MODEL 0x0110
|
|
|
|
|
|
|
|
|
2011-02-07 16:00:58 +00:00
|
|
|
float *float2degminsec( float deg )
|
2011-01-12 07:42:14 +00:00
|
|
|
{
|
2011-02-18 15:49:31 +00:00
|
|
|
float *res = malloc( sizeof(float)*3 );
|
|
|
|
res[0] = floorf( deg );
|
|
|
|
float min = ( deg - res[0] ) * 60.;
|
|
|
|
res[1] = floorf( min );
|
|
|
|
res[2] = ( min - res[1] ) * 60.;
|
|
|
|
return res;
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2011-02-07 16:00:58 +00:00
|
|
|
// original source from
|
2011-01-12 07:42:14 +00:00
|
|
|
// http://stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions
|
|
|
|
//
|
2011-02-07 16:00:58 +00:00
|
|
|
char * float2rationnal( float src )
|
2011-01-12 07:42:14 +00:00
|
|
|
{
|
2011-02-18 15:49:31 +00:00
|
|
|
long m[2][2];
|
|
|
|
float x, startx;
|
|
|
|
long maxden = 1000;
|
|
|
|
long ai;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
startx = x = src;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("float2rationnal: Convertir %f", src);
|
|
|
|
|
2011-01-12 07:42:14 +00:00
|
|
|
/* initialize matrix */
|
|
|
|
m[0][0] = m[1][1] = 1;
|
|
|
|
m[0][1] = m[1][0] = 0;
|
|
|
|
|
|
|
|
/* loop finding terms until denom gets too big */
|
|
|
|
while (m[1][0] * ( ai = (long)x ) + m[1][1] <= maxden) {
|
|
|
|
long t;
|
|
|
|
t = m[0][0] * ai + m[0][1];
|
|
|
|
m[0][1] = m[0][0];
|
|
|
|
m[0][0] = t;
|
|
|
|
t = m[1][0] * ai + m[1][1];
|
|
|
|
m[1][1] = m[1][0];
|
|
|
|
m[1][0] = t;
|
|
|
|
if(x==(float)ai) break; // AF: division by zero
|
|
|
|
x = 1/(x - (float) ai);
|
|
|
|
if(x>(float)0x7FFFFFFF) break; // AF: representation failure
|
2011-02-07 16:00:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-12 07:42:14 +00:00
|
|
|
|
|
|
|
/* now remaining x is between 0 and 1/ai */
|
|
|
|
/* approx as either 0 or 1/m where m is max that will fit in maxden */
|
|
|
|
/* first try zero */
|
|
|
|
|
|
|
|
/* now try other possibility */
|
|
|
|
ai = (maxden - m[1][1]) / m[1][0];
|
|
|
|
m[0][0] = m[0][0] * ai + m[0][1];
|
|
|
|
m[1][0] = m[1][0] * ai + m[1][1];
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
char *res = (char *)malloc( 256 * sizeof(char) );
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
snprintf( res, 256, "%ld/%ld", m[0][0], m[1][0] );
|
|
|
|
return res;
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|
|
|
|
|
2011-02-07 16:00:58 +00:00
|
|
|
char * coord2degminsec( float src )
|
2011-01-12 07:42:14 +00:00
|
|
|
{
|
2011-02-18 15:49:31 +00:00
|
|
|
char *res = (char *)malloc( 256 * sizeof(char) );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("coord2degminsec: Convertir %f", src);
|
2011-02-18 15:49:31 +00:00
|
|
|
float *dms = float2degminsec( fabs(src) );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("coord2degminsec: paso1 (float) %f %f %f", dms[0], dms[1], dms[2]);
|
2011-02-18 15:49:31 +00:00
|
|
|
strcpy( res, float2rationnal(dms[0]) );
|
|
|
|
strcat( res , "," );
|
|
|
|
strcat( res , float2rationnal(dms[1]) );
|
|
|
|
strcat( res , "," );
|
|
|
|
strcat( res , float2rationnal(dms[2]) );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("coord2degminsec: Convertido en %s", res);
|
2011-02-18 15:49:31 +00:00
|
|
|
free( dms );
|
|
|
|
return res;
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|
|
|
|
|
2011-03-30 21:06:24 +00:00
|
|
|
static void dump_to_file(const char *fname,
|
|
|
|
uint8_t *buf, uint32_t size)
|
|
|
|
{
|
|
|
|
int nw, cnt = 0;
|
|
|
|
uint32_t written = 0;
|
|
|
|
|
|
|
|
LOGV("opening file [%s]\n", fname);
|
|
|
|
int fd = open(fname, O_RDWR | O_CREAT);
|
|
|
|
if (fd < 0) {
|
|
|
|
LOGE("failed to create file [%s]: %s", fname, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGV("writing %d bytes to file [%s]\n", size, fname);
|
|
|
|
while (written < size) {
|
|
|
|
nw = write(fd,
|
|
|
|
buf + written,
|
|
|
|
size - written);
|
|
|
|
if (nw < 0) {
|
|
|
|
LOGE("failed to write to file [%s]: %s",
|
|
|
|
fname, strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
written += nw;
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
LOGV("done writing %d bytes to file [%s] in %d passes\n",
|
|
|
|
size, fname, cnt);
|
|
|
|
close(fd);
|
|
|
|
}
|
2011-01-12 07:42:14 +00:00
|
|
|
|
|
|
|
void writeExif( void *origData, void *destData , int origSize , uint32_t *resultSize, int orientation,camera_position_type *pt ) {
|
2011-02-18 15:49:31 +00:00
|
|
|
const char *filename = "/data/temp.jpg";
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
dump_to_file( filename, (uint8_t *)origData, origSize );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("WRITE EXIF Filename %s", filename);
|
2011-02-18 15:49:31 +00:00
|
|
|
chmod( filename, S_IRWXU );
|
|
|
|
ResetJpgfile();
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-01-12 07:42:14 +00:00
|
|
|
|
|
|
|
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
|
|
|
ImageInfo.FlashUsed = -1;
|
|
|
|
ImageInfo.MeteringMode = -1;
|
|
|
|
ImageInfo.Whitebalance = -1;
|
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
int gpsTag = 0;
|
2011-01-12 07:42:14 +00:00
|
|
|
if( pt != NULL ) {
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("EXIF ADD GPS DATA ........");
|
2011-02-18 15:49:31 +00:00
|
|
|
gpsTag = 6;
|
|
|
|
} else{
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("EXIF NO GPS ........");
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|
2011-02-07 16:00:58 +00:00
|
|
|
|
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
ExifElement_t *t = (ExifElement_t *)malloc( sizeof(ExifElement_t)*(3+gpsTag) );
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
ExifElement_t *it = t;
|
|
|
|
// Store file date/time.
|
|
|
|
(*it).Tag = TAG_ORIENTATION;
|
|
|
|
(*it).Format = FMT_USHORT;
|
|
|
|
(*it).DataLength = 1;
|
|
|
|
unsigned short v;
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("EXIF Orientation %d º", orientation);
|
2011-02-18 15:49:31 +00:00
|
|
|
if( orientation == 90 ) {
|
|
|
|
(*it).Value = "6";
|
|
|
|
} else if( orientation == 180 ) {
|
|
|
|
(*it).Value = "3";
|
2011-01-12 07:42:14 +00:00
|
|
|
} else {
|
2011-02-18 15:49:31 +00:00
|
|
|
(*it).Value = "1";
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|
2011-02-18 15:49:31 +00:00
|
|
|
(*it).GpsTag = FALSE;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
it++;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
(*it).Tag = TAG_MAKE;
|
|
|
|
(*it).Format = FMT_STRING;
|
|
|
|
(*it).Value = "HTC";
|
|
|
|
(*it).DataLength = 8;
|
|
|
|
(*it).GpsTag = FALSE;
|
2011-01-12 07:42:14 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
it++;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
(*it).Tag = TAG_MODEL;
|
|
|
|
(*it).Format = FMT_STRING;
|
|
|
|
(*it).Value = "Tattoo with CyanogenMOD";
|
|
|
|
(*it).DataLength = 18;
|
|
|
|
(*it).GpsTag = FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
if( pt != NULL ) {
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("pt->latitude == %f", pt->latitude );
|
|
|
|
LOGV("pt->longitude == %f", pt->longitude );
|
|
|
|
LOGV("pt->altitude == %d", pt->altitude );
|
2011-02-18 15:49:31 +00:00
|
|
|
|
|
|
|
it++;
|
|
|
|
(*it).Tag = 0x01;
|
|
|
|
(*it).Format = FMT_STRING;
|
|
|
|
if( pt->latitude > 0 ) {
|
|
|
|
(*it).Value = "N";
|
|
|
|
} else {
|
|
|
|
(*it).Value = "S";
|
|
|
|
}
|
|
|
|
(*it).DataLength = 2;
|
|
|
|
(*it).GpsTag = TRUE;
|
|
|
|
|
|
|
|
it++;
|
|
|
|
char *mylat = coord2degminsec( pt->latitude );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("writeExif: La latitud queda en: %s", mylat);
|
2011-02-18 15:49:31 +00:00
|
|
|
|
|
|
|
(*it).Tag = 0x02;
|
|
|
|
(*it).Format = FMT_URATIONAL;
|
|
|
|
(*it).Value = mylat;
|
|
|
|
(*it).DataLength = 3;
|
|
|
|
(*it).GpsTag = TRUE;
|
|
|
|
free( mylat );
|
|
|
|
|
|
|
|
it++;
|
|
|
|
(*it).Tag = 0x03;
|
|
|
|
(*it).Format = FMT_STRING;
|
|
|
|
if( (*pt).longitude > 0 ) {
|
|
|
|
(*it).Value = "E";
|
|
|
|
} else {
|
|
|
|
(*it).Value = "W";
|
|
|
|
}
|
|
|
|
(*it).DataLength = 2;
|
|
|
|
(*it).GpsTag = TRUE;
|
|
|
|
|
|
|
|
it++;
|
|
|
|
char *mylong = coord2degminsec( (*pt).longitude );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("writeExif: La longitud queda en: %s", mylong);
|
2011-02-18 15:49:31 +00:00
|
|
|
|
|
|
|
(*it).Tag = 0x04;
|
|
|
|
(*it).Format = FMT_URATIONAL;
|
|
|
|
(*it).Value = mylong;
|
|
|
|
(*it).DataLength = 3;
|
|
|
|
(*it).GpsTag = TRUE;
|
|
|
|
|
|
|
|
free( mylong );
|
|
|
|
|
|
|
|
it++;
|
|
|
|
(*it).Tag = 0x05;
|
|
|
|
(*it).Format = FMT_USHORT;
|
|
|
|
if( (*pt).altitude > 0 ) {
|
|
|
|
(*it).Value = "0";
|
|
|
|
} else {
|
|
|
|
(*it).Value = "1";
|
|
|
|
}
|
|
|
|
(*it).DataLength = 1;
|
|
|
|
(*it).GpsTag = TRUE;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
it++;
|
|
|
|
char *myalt = float2rationnal( fabs( (*pt).altitude ) );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("writeExif: La altitud queda en: %s", myalt);
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
(*it).Tag = 0x06;
|
|
|
|
(*it).Format = FMT_SRATIONAL;
|
|
|
|
(*it).Value = myalt;
|
|
|
|
(*it).DataLength = 1;
|
|
|
|
(*it).GpsTag = TRUE;
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
free( myalt );
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
if (stat(filename, &st) >= 0) {
|
|
|
|
ImageInfo.FileDateTime = st.st_mtime;
|
|
|
|
ImageInfo.FileSize = st.st_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
strncpy(ImageInfo.FileName, filename, PATH_MAX);
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("Image EXIF Filename %s", filename);
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-01-12 07:42:14 +00:00
|
|
|
ReadMode_t ReadMode;
|
|
|
|
ReadMode = READ_METADATA;
|
|
|
|
ReadMode |= READ_IMAGE;
|
|
|
|
int res = ReadJpegFile(filename, (ReadMode_t)ReadMode );
|
2011-03-30 21:06:24 +00:00
|
|
|
LOGV("READ EXIF Filename %s", filename);
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-01-12 07:42:14 +00:00
|
|
|
create_EXIF( t, 3, gpsTag);
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
WriteJpegFile(filename);
|
|
|
|
chmod( filename, S_IRWXU );
|
|
|
|
DiscardData();
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
FILE *src;
|
|
|
|
src = fopen( filename, "r");
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
fseek( src, 0L, SEEK_END );
|
|
|
|
(*resultSize) = ftell(src);
|
|
|
|
fseek( src, 0L, SEEK_SET );
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
int read = fread( destData, 1, (*resultSize), src );
|
2011-02-07 16:00:58 +00:00
|
|
|
|
2011-02-18 15:49:31 +00:00
|
|
|
unlink( filename );
|
2011-01-12 07:42:14 +00:00
|
|
|
}
|