Skip to content

Commit

Permalink
Added custom int and float TIFF tags
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Nov 11, 2018
1 parent 990fb03 commit a3d45e9
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 19 deletions.
18 changes: 18 additions & 0 deletions Tests/test_file_libtiff.py
Expand Up @@ -231,6 +231,24 @@ def test_additional_metadata(self):

TiffImagePlugin.WRITE_LIBTIFF = False

def test_custom_metadata(self):
custom = {
37000: 4,
37001: 4.2
}
for libtiff in [False, True]:
TiffImagePlugin.WRITE_LIBTIFF = libtiff

im = hopper()

out = self.tempfile("temp.tif")
im.save(out, tiffinfo=custom)
TiffImagePlugin.WRITE_LIBTIFF = False

reloaded = Image.open(out)
for tag, value in custom.items():
self.assertEqual(reloaded.tag_v2[tag], value)

def test_int_dpi(self):
# issue #1765
im = hopper('RGB')
Expand Down
9 changes: 4 additions & 5 deletions src/PIL/TiffImagePlugin.py
Expand Up @@ -1499,11 +1499,10 @@ def _save(im, fp, filename):
getattr(im, 'tag_v2', {}).items(),
legacy_ifd.items()):
# Libtiff can only process certain core items without adding
# them to the custom dictionary. It will segfault if it attempts
# to add a custom tag without the dictionary entry
#
# UNDONE -- add code for the custom dictionary
if tag not in TiffTags.LIBTIFF_CORE:
# them to the custom dictionary. Support has only been been added
# for int and float values
if tag not in TiffTags.LIBTIFF_CORE and not \
(isinstance(value, int) or isinstance(value, float)):
continue
if tag not in atts and tag not in blocklist:
if isinstance(value, str if py3 else unicode):
Expand Down
1 change: 1 addition & 0 deletions src/PIL/TiffTags.py
Expand Up @@ -425,6 +425,7 @@ def _populate():

# some of these are not in our TAGS_V2 dict and were included from tiff.h

# This list also exists in encode.c
LIBTIFF_CORE = {255, 256, 257, 258, 259, 262, 263, 266, 274, 277,
278, 280, 281, 340, 341, 282, 283, 284, 286, 287,
296, 297, 321, 320, 338, 32995, 322, 323, 32998,
Expand Down
46 changes: 32 additions & 14 deletions src/encode.c
Expand Up @@ -804,7 +804,13 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
PyObject *dir;
PyObject *key, *value;
Py_ssize_t pos = 0;
int status;
int key_int, status, is_core_tag, i;
// This list also exists in TiffTags.py
const int tags[32] = {
256, 257, 258, 259, 262, 263, 266, 269, 274, 277, 278, 280, 281, 340,
341, 282, 283, 284, 286, 287, 296, 297, 321, 338, 32995, 32998, 32996,
339, 32997, 330, 531, 530
};

Py_ssize_t d_size;
PyObject *keys, *values;
Expand Down Expand Up @@ -845,29 +851,41 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)

for (pos = 0; pos < d_size; pos++) {
key = PyList_GetItem(keys, pos);
key_int = (int)PyInt_AsLong(key);
value = PyList_GetItem(values, pos);
status = 0;
TRACE(("Attempting to set key: %d\n", (int)PyInt_AsLong(key)));
is_core_tag = 0;
for (i=0; i<32; i++) {
if (tags[i] == key_int) {
is_core_tag = 1;
break;
}
}
TRACE(("Attempting to set key: %d\n", key_int));
if (PyInt_Check(value)) {
TRACE(("Setting from Int: %d %ld \n", (int)PyInt_AsLong(key),PyInt_AsLong(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyInt_AsLong(value));
TRACE(("Setting from Int: %d %ld \n", key_int, PyInt_AsLong(value)));
if (is_core_tag || !ImagingLibTiffMergeFieldInfo(&encoder->state, TIFF_LONG, key_int)) {
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyInt_AsLong(value));
}
} else if (PyFloat_Check(value)) {
TRACE(("Setting from Float: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
(float)PyFloat_AsDouble(value));
TRACE(("Setting from Float: %d, %f \n", key_int, PyFloat_AsDouble(value)));
if (is_core_tag || !ImagingLibTiffMergeFieldInfo(&encoder->state, TIFF_DOUBLE, key_int)) {
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
(double)PyFloat_AsDouble(value));
}
} else if (PyBytes_Check(value)) {
TRACE(("Setting from Bytes: %d, %s \n", (int)PyInt_AsLong(key),PyBytes_AsString(value)));
TRACE(("Setting from Bytes: %d, %s \n", key_int, PyBytes_AsString(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyBytes_AsString(value));
} else if (PyTuple_Check(value)) {
Py_ssize_t len,i;
float *floatav;
int *intav;
TRACE(("Setting from Tuple: %d \n", (int)PyInt_AsLong(key)));
TRACE(("Setting from Tuple: %d \n", key_int));
len = PyTuple_Size(value);
if (len) {
if (PyInt_Check(PyTuple_GetItem(value,0))) {
Expand Down Expand Up @@ -898,13 +916,13 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
}
} else {
TRACE(("Unhandled type in tuple for key %d : %s \n",
(int)PyInt_AsLong(key),
key_int,
PyBytes_AsString(PyObject_Str(value))));
}
}
} else {
TRACE(("Unhandled type for key %d : %s \n",
(int)PyInt_AsLong(key),
key_int,
PyBytes_AsString(PyObject_Str(value))));
}
if (!status) {
Expand Down
13 changes: 13 additions & 0 deletions src/libImaging/TiffDecode.c
Expand Up @@ -402,6 +402,19 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {

}

int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key){
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
char field_name[10];
uint32 n;

const TIFFFieldInfo info[] = {
{ key, 0, 1, field_type, FIELD_CUSTOM, 1, 0, field_name }
};
n = sizeof(info) / sizeof(info[0]);

return TIFFMergeFieldInfo(clientstate->tiff, info, n);
}

int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){
// after tif_dir.c->TIFFSetField.
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
Expand Down
1 change: 1 addition & 0 deletions src/libImaging/TiffDecode.h
Expand Up @@ -45,6 +45,7 @@ typedef struct {

extern int ImagingLibTiffInit(ImagingCodecState state, int fp, int offset);
extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
extern int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key);
extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);


Expand Down

0 comments on commit a3d45e9

Please sign in to comment.