[libcamera-devel] qcam: dng_writer: Write EXIF IFD as custom directory

Message ID 20200504070425.5972-1-laurent.pinchart@ideasonboard.com
State Accepted
Commit 3ed0fced1f22bcdb9a0f05bbbc1e3b87017ac8c2
Headers show
Series
  • [libcamera-devel] qcam: dng_writer: Write EXIF IFD as custom directory
Related show

Commit Message

Laurent Pinchart May 4, 2020, 7:04 a.m. UTC
The EXIF IFD is incorrectly chained to IFD 0 in addition to being a
referenced as a sub IFD through the EXIFIFD tag. While the libtiff API
doesn't clearly document why this happens, inspection of the
TIFFWriteDirectory() source code show that the function treats the IFD
being written as containing an image, which isn't correct for the EXIF
IFD. Use TIFFWriteCustomDirectory() instead, which fixes the problem.
The resulting DNG file can now be opened with darktable in addition to
rawtherapee.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/qcam/dng_writer.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

Comments

Niklas Söderlund May 4, 2020, 9:47 a.m. UTC | #1
Hi Laurent,

Thanks for your fix, libtiff is fun.

On 2020-05-04 10:04:25 +0300, Laurent Pinchart wrote:
> The EXIF IFD is incorrectly chained to IFD 0 in addition to being a
> referenced as a sub IFD through the EXIFIFD tag. While the libtiff API
> doesn't clearly document why this happens, inspection of the
> TIFFWriteDirectory() source code show that the function treats the IFD
> being written as containing an image, which isn't correct for the EXIF
> IFD. Use TIFFWriteCustomDirectory() instead, which fixes the problem.
> The resulting DNG file can now be opened with darktable in addition to
> rawtherapee.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>

> ---
>  src/qcam/dng_writer.cpp | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp
> index ea4616f63d8e..cbd8bed3e6d0 100644
> --- a/src/qcam/dng_writer.cpp
> +++ b/src/qcam/dng_writer.cpp
> @@ -316,9 +316,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,
>  		TIFFSetField(tif, EXIFTAG_EXPOSURETIME, exposureTime);
>  	}
>  
> -	TIFFCheckpointDirectory(tif);
> -	exifIFDOffset = TIFFCurrentDirOffset(tif);
> -	TIFFWriteDirectory(tif);
> +	TIFFWriteCustomDirectory(tif, &exifIFDOffset);
>  
>  	/* Update the IFD offsets and close the file. */
>  	TIFFSetDirectory(tif, 0);
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
Kieran Bingham May 4, 2020, 9:51 a.m. UTC | #2
Hi Laurent,

On 04/05/2020 08:04, Laurent Pinchart wrote:
> The EXIF IFD is incorrectly chained to IFD 0 in addition to being a
> referenced as a sub IFD through the EXIFIFD tag. While the libtiff API
> doesn't clearly document why this happens, inspection of the
> TIFFWriteDirectory() source code show that the function treats the IFD
> being written as containing an image, which isn't correct for the EXIF
> IFD. Use TIFFWriteCustomDirectory() instead, which fixes the problem.
> The resulting DNG file can now be opened with darktable in addition to
> rawtherapee.

Nice!

Sounds like it was more painful to fix than it should have been.

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  src/qcam/dng_writer.cpp | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp
> index ea4616f63d8e..cbd8bed3e6d0 100644
> --- a/src/qcam/dng_writer.cpp
> +++ b/src/qcam/dng_writer.cpp
> @@ -316,9 +316,7 @@ int DNGWriter::write(const char *filename, const Camera *camera,
>  		TIFFSetField(tif, EXIFTAG_EXPOSURETIME, exposureTime);
>  	}
>  
> -	TIFFCheckpointDirectory(tif);
> -	exifIFDOffset = TIFFCurrentDirOffset(tif);
> -	TIFFWriteDirectory(tif);
> +	TIFFWriteCustomDirectory(tif, &exifIFDOffset);
>  
>  	/* Update the IFD offsets and close the file. */
>  	TIFFSetDirectory(tif, 0);
>

Patch

diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp
index ea4616f63d8e..cbd8bed3e6d0 100644
--- a/src/qcam/dng_writer.cpp
+++ b/src/qcam/dng_writer.cpp
@@ -316,9 +316,7 @@  int DNGWriter::write(const char *filename, const Camera *camera,
 		TIFFSetField(tif, EXIFTAG_EXPOSURETIME, exposureTime);
 	}
 
-	TIFFCheckpointDirectory(tif);
-	exifIFDOffset = TIFFCurrentDirOffset(tif);
-	TIFFWriteDirectory(tif);
+	TIFFWriteCustomDirectory(tif, &exifIFDOffset);
 
 	/* Update the IFD offsets and close the file. */
 	TIFFSetDirectory(tif, 0);