| AWARE [SYSTEMS] | Imaging expertise for the Delphi developer | |||||||
![]() |
TIFF and LibTiff Mailing List Archive | |||||||
LibTiff Mailing List
TIFF and LibTiff Mailing List Archive Contact
The TIFF Mailing List Homepage |
Thread2003.11.18 15:05 "TIFF, v3.6.0. Fetching "custom" tags", by Ross FinlaysonGoing back to the _TIFFextender variables, _TIFFextender is the
identifier of a static variable declared in tif_dir.c. It is defined as
a TIFFExtendProc. The TIFFDefaultDirectory function calls the non-null
function pointer installed at the _TIFFextender static variable. The
TIFFExtendProc function pointer is installed in the _TIFFextender static
(global) variable using the TIFFSetTagExtender function.
Then, the user implementation of the TIFFExtendProc function that is
patched into the _TIFFextender static variable, when it is called by the
TIFFDefaultDirectory function, may call TIFFMergeFieldInfo on whatever
private or "custom" tags that it wants to to be handled by TIFFGetField
and TIFFSetField. It can also call other functions on the TIFF pointer.
A problem with this is that the _TIFFextender function is called each
time the TIFFDefaultDirectory function is called, where if the
_TIFFextender function is to be used for adding the custom tag
definitions that it would be called multiple times as directories were
added from TIFFCreateDirectory calling TIFFDefaultDirectory. The
TIFFFieldInfo and the nfields members are of the TIFF struct, not the
TIFFDirectory struct.
Perhaps a better place for _TIFFextender to be called would be in
TIFFClientOpen.
The Nota Bene in _TIFFFindFieldInfo suggest that as the table of
TIFFFieldInfo pointers grows that it would be more efficient to use
binary search instead of plain search. The list of TIFFFieldInfo
pointers is already sorted by _TIFFMergeFieldInfo. I turn to a C book
around here and read about bsearch, I think it can use the same compare
function as qsort, and is also defined in stdlib.h. Yet,
_TIFFFiindFieldInfo should return the TIFFFieldInfo struct with the
greatest precision width, and specification is by the tag. The bsearch
can be implemented when the data type is not TIFF_ANY. It could be
implemented for all but I don't know if bsearch is stable.
if(dt != TIFF_ANY){
const TIFFFieldInfo key={tag, 0, 0, dt, 0, 0, 0, 0};
return( (const TIFFFieldInfo *) bsearch(
&key,
tif->tif_fieldinfo,
tif->tif_nfields,
sizeof(TIFFFieldInfo),
tagCompare);
}
Now the problem with that is that tagCompare doesn't return zero if the
tag and data type of the TIFFFieldInfo are equal.
I'd modify line 311 of tagCompare from "return(tb->field_type <
ta->field_type ? -1 : 1)" to "return(tb->field_type - ta->field_type)",
yet TIFFDataType is an enum. As enum is unsigned, maybe,
"return((int)tb->field_type - (int)ta->field_type)". Hopefully, that
won't slow the compare function to a crawl or be worthless for 99% of
the cases.
So anyways if the _TIFFextender function is to be used to add private or
custom tags definitions to the TIFF, which it does, then it should be
called from somewhere besides in TIFFDefaultDirectory. Imagine
generating a thousand page output file, with thousands of calls to
_TIFFextender, instead it should only be one.
Here I'll edit tif_dirinfo.c locally here and the output of diff follows.
Is it worthwhile to use bsearch on the array of TIFFFieldInfo structs or
is the array not worth it? It's probably worth it because the array of
info structs is all known fields.
What do you think about the _TIFFextender? I don't understand its
justification for being called from TIFFDefaultDirectory. Instead, I
think it should be called in TIFFClientOpen, around line 313 of
tif_open.c, right before TIFFClientOpen calls TIFFDefaultDirectory,
instead of line 1189 of tif_dir.c. Then, if there is to be a separate
function to extend the TIFFDefaultDirectory, then have that, too. Then,
besides _TIFFextender there could be _TIFFDirectoryExtender.
Then, I'm still trying to figure out a good way to copy each of the tags
from a read mode directory to a write mode directory.
Let me know if I'm unclear. Having a fresh pair of eyes makes a big
difference. The doxygen output really helps to browse the source code.
Ross F.
--- tif_dirinfo.c.orig Tue Nov 18 06:12:48 2003
+++ tif_dirinfo.c Tue Nov 18 06:23:53 2003
@@ -308,7 +308,7 @@
if (ta->field_tag != tb->field_tag)
return (ta->field_tag < tb->field_tag ? -1 : 1);
else
- return (tb->field_type < ta->field_type ? -1 : 1);
+ return ((int)tb->field_type - (int)ta->field_type);
}
void
@@ -419,7 +419,17 @@
(dt == TIFF_ANY || dt == last->field_type))
return (last);
/* NB: if table gets big, use sorted search (e.g. binary
search) */
- for (i = 0, n = tif->tif_nfields; i < n; i++) {
+ if(dt != TIFF_ANY){
+ TIFFFieldInfo key={0, 0, 0, 0, 0, 0, 0, 0};
+ key.field_tag=tag;
+ key.field_type=dt;
+ return( (const TIFFFieldInfo *) bsearch(
+ &key,
+ tif->tif_fieldinfo,
+ tif->tif_nfields,
+ sizeof(TIFFFieldInfo),
+ tagCompare));
+ } else for (i = 0, n = tif->tif_nfields; i < n; i++) {
const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
if (fip->field_tag == tag &&
(dt == TIFF_ANY || fip->field_type == dt))
|
|||||||