3939// these as float/double arrays and handles the conversion; we just pass
4040// the values as double
4141
42+ // libtiff error/warning handlers — replacing whatever else in the
43+ // process may have installed (e.g. ImageMagick's, which crashes on
44+ // NULL exception context). these just log to stderr and never abort
45+ static void _dt_dng_tiff_warning (const char * module ,
46+ const char * fmt , va_list ap )
47+ {
48+ if (darktable .unmuted & DT_DEBUG_IMAGEIO )
49+ {
50+ fprintf (stderr , "%11.4f [imageio_dng] warning: %s: " ,
51+ dt_get_wtime () - darktable .start_wtime ,
52+ module ? module : "(none)" );
53+ vfprintf (stderr , fmt , ap );
54+ fprintf (stderr , "\n" );
55+ }
56+ }
57+
58+ static void _dt_dng_tiff_error (const char * module ,
59+ const char * fmt , va_list ap )
60+ {
61+ fprintf (stderr , "%11.4f [imageio_dng] error: %s: " ,
62+ dt_get_wtime () - darktable .start_wtime ,
63+ module ? module : "(none)" );
64+ vfprintf (stderr , fmt , ap );
65+ fprintf (stderr , "\n" );
66+ }
67+
68+ static void _install_dng_tiff_handlers (void )
69+ {
70+ TIFFSetWarningHandler (_dt_dng_tiff_warning );
71+ TIFFSetErrorHandler (_dt_dng_tiff_error );
72+ }
73+
4274// map the dcraw 2x2 CFA filters word to 4 single-byte channel indices
4375// for the DNG CFAPattern tag: 0=R, 1=G, 2=B, following DNG spec §A.3.1
4476static void _cfa_bytes_from_filters (uint32_t filters , uint8_t out [4 ])
@@ -160,6 +192,8 @@ int dt_imageio_dng_write_cfa_bayer(const char *filename,
160192 if (!filename || !cfa || !img || width <= 0 || height <= 0 )
161193 return 1 ;
162194
195+ _install_dng_tiff_handlers ();
196+
163197#ifdef _WIN32
164198 wchar_t * wfilename = g_utf8_to_utf16 (filename , -1 , NULL , NULL , NULL );
165199 TIFF * tif = TIFFOpenW (wfilename , "wl" );
@@ -184,10 +218,11 @@ int dt_imageio_dng_write_cfa_bayer(const char *filename,
184218 g_unlink (filename );
185219 return 1 ;
186220 }
187- // libtiff entered INSUBIFD mode when the IFD0 carrying TIFFTAG_SUBIFD
188- // was written; subsequent TIFFSetField + scanline writes populate
189- // the SubIFD without an explicit TIFFCreateDirectory call (whose
190- // return-value convention changed between libtiff versions)
221+ // re-register default tag info on some libtiff builds CFA/DNG
222+ // extension tags would be lost across the IFD write, breaking
223+ // CFAREPEATPATTERNDIM / CFAPATTERN. return value differs across
224+ // libtiff versions; not checked
225+ TIFFCreateDirectory (tif );
191226 }
192227
193228 // raw payload IFD: single IFD when no preview, otherwise SubIFD0
@@ -299,6 +334,8 @@ int dt_imageio_dng_write_linear(const char *filename,
299334 if (!filename || !rgb || !img || width <= 0 || height <= 0 )
300335 return 1 ;
301336
337+ _install_dng_tiff_handlers ();
338+
302339#ifdef _WIN32
303340 wchar_t * wfilename = g_utf8_to_utf16 (filename , -1 , NULL , NULL , NULL );
304341 TIFF * tif = TIFFOpenW (wfilename , "wl" );
@@ -321,7 +358,9 @@ int dt_imageio_dng_write_linear(const char *filename,
321358 g_unlink (filename );
322359 return 1 ;
323360 }
324- // libtiff is in INSUBIFD mode after IFD0 was written with TIFFTAG_SUBIFD
361+ // re-initialize directory state so DNG extension tag info is
362+ // available on the SubIFD (see comment in write_cfa_bayer)
363+ TIFFCreateDirectory (tif );
325364 }
326365
327366 // baseline TIFF tags, 3 samples per pixel (demosaicked)
0 commit comments