Skip to content

Commit d0ccc00

Browse files
committed
allow Exif tag identification by name
1 parent 3be5a2c commit d0ccc00

File tree

2 files changed

+66
-39
lines changed

2 files changed

+66
-39
lines changed

src/gpujpeg_encoder.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ gpujpeg_encoder_print_options() {
760760
"] - whether is the input image should be vertically flipped (prior encode)\n");
761761
printf("\t" GPUJPEG_ENC_OPT_CHANNEL_REMAP "=XYZ[W] - input channel mapping, eg. '210F' for GBRX,\n"
762762
"\t\t'210' for GBR; special placeholders 'F' and 'Z' to set a channel to all-ones or all-zeros\n");
763-
printf("\t" GPUJPEG_ENC_OPT_EXIF_TAG "=<ID>:<type>=<value> - custom EXIF tag\n");
763+
printf("\t" GPUJPEG_ENC_OPT_EXIF_TAG "=<key>=<value>|help - custom EXIF tag (use help for syntax)\n");
764764
}
765765

766766
/* Documented at declaration */

src/gpujpeg_exif.c

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "gpujpeg_exif.h"
3131

3232
#include <assert.h>
33+
#include <ctype.h>
3334
#include <stdint.h>
3435
#include <stdlib.h>
3536
#include <string.h>
@@ -98,20 +99,21 @@ enum exif_tiff_tag {
9899
const struct exif_tiff_tag_info_t {
99100
uint16_t id;
100101
enum exif_tag_type type;
102+
const char *name;
101103
} exif_tiff_tag_info[] = {
102-
[ETIFF_XRESOLUTION] = {0x11A, ET_RATIONAL},
103-
[ETIFF_YRESOLUTION] = {0x11B, ET_RATIONAL},
104-
[ETIFF_RESOLUTION_UNIT] = {0x128, ET_SHORT },
105-
[ETIFF_SOFTWARE] = {0x131, ET_ASCII },
106-
[ETIFF_YCBCR_POSITIONING] = {0x213, ET_SHORT },
107-
[ETIFF_EXIF_IFD_POINTER] = {0x8769, ET_LONG },
104+
[ETIFF_XRESOLUTION] = {0x11A, ET_RATIONAL, "XResolution" },
105+
[ETIFF_YRESOLUTION] = {0x11B, ET_RATIONAL, "YResolution" },
106+
[ETIFF_RESOLUTION_UNIT] = {0x128, ET_SHORT, "ResolutionUnit" },
107+
[ETIFF_SOFTWARE] = {0x131, ET_ASCII, "Sofware" },
108+
[ETIFF_YCBCR_POSITIONING] = {0x213, ET_SHORT, "YCbCrPositioning" },
109+
[ETIFF_EXIF_IFD_POINTER] = {0x8769, ET_LONG, "iExif IFD Pointer"},
108110
// Exif SubIFD
109-
[EEXIF_EXIF_VERSION] = {0x9000, ET_UNDEFINED },
110-
[EEXIF_COMPONENTS_CONFIGURATION] = {0x9101, ET_UNDEFINED },
111-
[EEXIF_FLASHPIX_VERSION] = {0xA000, ET_UNDEFINED },
112-
[EEXIF_COLOR_SPACE] = {0xA001, ET_SHORT },
113-
[EEXIF_PIXEL_X_DIMENSION] = {0xA002, ET_SHORT }, // type can be also LONG
114-
[EEXIF_PIXEL_Y_DIMENSION] = {0xA003, ET_SHORT }, // ditto
111+
[EEXIF_EXIF_VERSION] = {0x9000, ET_UNDEFINED, "ExifVersion" },
112+
[EEXIF_COMPONENTS_CONFIGURATION] = {0x9101, ET_UNDEFINED, "ComponentConfiguration"},
113+
[EEXIF_FLASHPIX_VERSION] = {0xA000, ET_UNDEFINED, "FlashPixVersion" },
114+
[EEXIF_COLOR_SPACE] = {0xA001, ET_SHORT, "ColorSpace" },
115+
[EEXIF_PIXEL_X_DIMENSION] = {0xA002, ET_SHORT, "PixelXDimension" }, // type can be also LONG
116+
[EEXIF_PIXEL_Y_DIMENSION] = {0xA003, ET_SHORT, "PixelYDimension" }, // ditto
115117
};
116118

117119
// misc constants
@@ -373,39 +375,64 @@ gpujpeg_writer_write_exif(struct gpujpeg_encoder* encoder)
373375
bool
374376
gpujpeg_exif_add_tag(struct gpujpeg_exif_tags** exif_tags, const char* cfg)
375377
{
376-
char *endptr = (char *) cfg;
377-
long tag_id = strtol(cfg, &endptr, 0);
378-
if (*endptr != ':') {
379-
ERROR_MSG("Error parsing Exif tag ID or missing type!\n");
378+
if (strcmp(cfg, "help") == 0) {
379+
printf("Exif value syntax:\n"
380+
"\t" GPUJPEG_ENC_OPT_EXIF_TAG "=<ID>:<type>=<value>\n"
381+
"\t" GPUJPEG_ENC_OPT_EXIF_TAG "=<name>=<value>\n"
382+
"\t\tname must be a tag name known to GPUJPEG\n");
380383
return false;
381384
}
382-
endptr += 1;
383385

386+
char *endptr = (char *) cfg;
387+
long tag_id = 0;
384388
enum exif_tag_type type = ET_NONE;
385-
for (unsigned i = ET_NONE + 1; i < ET_END; ++i) {
386-
if ( exif_tag_type_info[i].name == NULL) { // unset/invalid type
387-
continue;
389+
390+
if (!isdigit(*endptr)) {
391+
for (unsigned i = 0; i < ARR_SIZE(exif_tiff_tag_info); ++i) {
392+
size_t len = strlen(exif_tiff_tag_info[i].name);
393+
if ( strncasecmp(endptr, exif_tiff_tag_info[i].name, len) == 0 ) {
394+
tag_id = exif_tiff_tag_info[i].id;
395+
type = exif_tiff_tag_info[i].type;
396+
endptr += len;
397+
}
388398
}
389-
size_t len = strlen(exif_tag_type_info[i].name);
390-
if (strncasecmp(endptr, exif_tag_type_info[i].name, len) == 0 ) {
391-
type = i;
392-
endptr += len;
393-
break;
399+
if (*endptr != '=') {
400+
ERROR_MSG("[Exif] Wrong tag name or missing value!\n");
401+
return false;
402+
}
403+
} else {
404+
tag_id = strtol(cfg, &endptr, 0);
405+
if (*endptr != ':') {
406+
ERROR_MSG("Error parsing Exif tag ID or missing type!\n");
407+
return false;
408+
}
409+
endptr += 1;
410+
for ( unsigned i = ET_NONE + 1; i < ET_END; ++i ) {
411+
if ( exif_tag_type_info[i].name == NULL ) { // unset/invalid type
412+
continue;
413+
}
414+
size_t len = strlen(exif_tag_type_info[i].name);
415+
if ( strncasecmp(endptr, exif_tag_type_info[i].name, len) == 0 ) {
416+
type = i;
417+
endptr += len;
418+
break;
419+
}
420+
}
421+
if ( type == ET_NONE ) {
422+
ERROR_MSG("Error parsing Exif tag type!\n");
423+
return false;
424+
}
425+
if ( *endptr != '=' ) {
426+
ERROR_MSG("Error parsing Exif - missing value!\n");
427+
return false;
428+
}
429+
unsigned numeric_unsigned = T_NUMERIC | T_UNSIGNED;
430+
if ( (exif_tag_type_info[type].type_flags & numeric_unsigned) != numeric_unsigned ) {
431+
ERROR_MSG("Only unsigned integers currently supported!\n");
432+
return false;
394433
}
395434
}
396-
if (type == ET_NONE) {
397-
ERROR_MSG("Error parsing Exif tag type!\n");
398-
return false;
399-
}
400-
if (*endptr != '=') {
401-
ERROR_MSG("Error parsing Exif - missing value!\n");
402-
return false;
403-
}
404-
unsigned numeric_unsigned = T_NUMERIC | T_UNSIGNED;
405-
if ((exif_tag_type_info[type].type_flags & numeric_unsigned) != numeric_unsigned) {
406-
ERROR_MSG("Only unsigned integers currently supported!\n");
407-
return false;
408-
}
435+
409436
endptr += 1;
410437
unsigned long long val = strtoull(endptr, &endptr, 0);
411438
if (*endptr != '\0') {

0 commit comments

Comments
 (0)