Browse Source

- bugfix, because libtiff will automatically add a missed tag, the function TIFFWriteDirectory() could overwrite data, because new IFD length exceeds old IFD length. Therefore datetime is fixed in-place without using TIFFWriteDirectory(), TIFFGetField() or TIFFSetField

tags/v0.1.2
parent
commit
984459b21d
2 changed files with 87 additions and 20 deletions
  1. +1
    -0
      src/check_datetime.h
  2. +86
    -20
      src/cleanup_datetime.c

+ 1
- 0
src/check_datetime.h View File

@@ -1,5 +1,6 @@
#ifndef _FIXIT_TIFF_CHECK_DATETIME
#define _FIXIT_TIFF_CHECK_DATETIME
#include <assert.h>
int check_datetime (const char *);
int test_plausibility (int * year, int * month, int * day, int * hour, int * min, int * sec);
#endif


+ 86
- 20
src/cleanup_datetime.c View File

@@ -10,7 +10,7 @@

#include "fixit_tiff.h"
#include "check_datetime.h"
#include "tiff_helper.h"

/** RULE0: default rule (string is correct) */
static int rule_default (const char * datestring, int * year, int * month, int * day, int * hour, int * min, int * sec) {
@@ -148,27 +148,93 @@ int cleanup_datetime(const char * filename ) {
};
/* find date-tag and fix it */
char *datetime=NULL;
uint32 count=0;
int found=TIFFGetField(tif, TIFFTAG_DATETIME, &datetime, &count);
if (1==found) { /* there exists a datetime field */
if (FLAGGED == flag_be_verbose) printf("Before correction\n-----------------\n");
if (FLAGGED == flag_be_verbose) TIFFPrintDirectory(tif, stdout, TIFFPRINT_NONE);
if (FLAGGED == flag_be_verbose) printf("c=%u datetime:'%s'\n", count, datetime);
/* should be corrected? */
char * new_datetime = correct_datestring( datetime );
/* repair */
TIFFSetField(tif, TIFFTAG_DATETIME, new_datetime);
if (FLAGGED == flag_be_verbose) printf("After correction\n-----------------\n");
if (FLAGGED == flag_be_verbose) TIFFPrintDirectory(tif, stdout, TIFFPRINT_NONE);
/* write data back, only if no flag_check_only is set */
int written = TIFFWriteDirectory(tif); /* HINT: if errorneous, use TIFFReWriteDirectory instead */
if (1 != written) {
fprintf(stderr, "something is wrong, tiffdir could not be written to file '%s'\n", filename);
exit (FIXIT_TIFF_WRITE_ERROR);
uint32 tag_counter=TIFFGetRawTagListCount(tif);
uint32 tagidx;
for (tagidx=0; tagidx < tag_counter; tagidx++) {
uint32 tag = TIFFGetRawTagListEntry( tif, tagidx );
if (tag == TIFFTAG_DATETIME) {
/* via TIFFGetRawTagListEntry we have the tag
* read, the next 2 bytes are the type, next 2 count, last 4 value/offset */
int fd = TIFFFileno( tif);
uint16 tagtype=0;
if ( read( fd, &tagtype, 2) != 2 ) {
perror ("TIFF Header read error tagtype");
exit( FIXIT_TIFF_READ_ERROR );
}
if (TIFFIsByteSwapped(tif))
TIFFSwabShort(&tagtype);
assert(TIFF_ASCII == tagtype);
uint32 bytepos_count = lseek( fd, 0, SEEK_CUR );
uint32 count=0;
if ( read( fd, &count, 4) != 4 ) {
perror ("TIFF Header read error tagcount");
exit( FIXIT_TIFF_READ_ERROR );
}
if (TIFFIsByteSwapped(tif))
TIFFSwabLong(&count);
uint32 offset=0;
if ( read( fd, &offset, 4) != 4 ) {
perror ("TIFF Header read error offset");
exit( FIXIT_TIFF_READ_ERROR );
}
if (TIFFIsByteSwapped(tif))
TIFFSwabLong(&offset);
if (FLAGGED == flag_be_verbose) printf("tag=%u tagtype=%i c=%u offset=%u\n", tag, tagtype, count, offset);
datetime = malloc( sizeof( char ) * count);
if (NULL == datetime) {
perror("Could not allocate memory for new datetime");
exit(FIXIT_TIFF_MEMORY_ALLOCATION_ERROR);
}
/* rewind to offset */
if (lseek(fd, offset, SEEK_SET) != offset) {
perror("TIFF datetime seek error to offset");
exit( FIXIT_TIFF_READ_ERROR );
}
if (read(fd, datetime, count) != count) {
perror ("TIFF datetime read error offset");
exit( FIXIT_TIFF_READ_ERROR );
}
/* repair */
char * new_datetime = correct_datestring( datetime );
if (NULL == new_datetime) {
perror("Could not allocate memory for new datetime");
exit(FIXIT_TIFF_MEMORY_ALLOCATION_ERROR);
}
/* rewind to offset */
if (lseek(fd, offset, SEEK_SET) != offset) {
perror("TIFF datetime seek error to offset");
exit( FIXIT_TIFF_READ_ERROR );
}
/* write data back, only if no flag_check_only is set */
if (write(fd, new_datetime, TIFFDATETIMELENGTH) != TIFFDATETIMELENGTH) {
perror("TIFF datetime write error");
exit(FIXIT_TIFF_WRITE_ERROR);
}
/* rewind to IFD to set count */
if (lseek(fd, bytepos_count, SEEK_SET) != bytepos_count) {
perror("TIFF datetime seek error to IFD pos");
exit( FIXIT_TIFF_READ_ERROR );
}
/* write corrected count, only if no flag_check_only is set */
count = TIFFDATETIMELENGTH;
if (TIFFIsByteSwapped(tif))
TIFFSwabLong(&count);
if (write(fd, &count, 4) != 4) {
perror("TIFF datetime write error IFD count for datetime");
exit(FIXIT_TIFF_WRITE_ERROR);
}
TIFFClose(tif);
if (FLAGGED == flag_be_verbose) {
printf("tag=%u tagtype=%i count=%u offset=%u (0x%04x)\n", tag, tagtype, count, offset, offset);
printf("old_datetime='%s'\n", datetime);
printf("new_datretime='%s'\n", new_datetime);
printf("\n");
}
free(new_datetime);
break;
}
free(new_datetime);
if (FLAGGED == flag_be_verbose) printf("After correction\n-----------------\n");
}
TIFFClose(tif);
}
if (FIXIT_TIFF_IS_VALID == check_datetime (filename)) return FIXIT_TIFF_IS_CORRECTED;
else return FIXIT_TIFF_IS_CHECKED;


Loading…
Cancel
Save