[libcamera-devel] [RFC v1 PATCH] android: jpeg: exif: Set timezone information

Umang Jain email at uajain.com
Wed Sep 23 11:13:40 CEST 2020


Hi,

On 9/22/20 9:56 PM, Umang Jain wrote:
> Get timezone information from the timestamp, although the resolution
> for EXIF_TAG_TIME_ZONE_OFFSET is fairly limited (per-hour only).
>
> Experimentation with 'exiftool', commandline utility to read/write
> exif metadata on images, resulted in rounding off the hours if the
> minutes came out to >= 30. Hence, the behaviour is inspired from
> exiftool itself. For e.g.,
>
> Timezone      Tag's value
>   +1015     =>     10
>   +0945     =>     10
>   -1145     =>    -12
>
> The EXIF specification defines three other tags (OffsetTime,
> OffsetTimeOriginal, OffsetTimeDigitized), in the EXIF IFD.
> These are not supported by libexif yet.
>
> Signed-off-by: Umang Jain <email at uajain.com>
> ---
>   src/android/jpeg/exif.cpp | 31 +++++++++++++++++++++++++++++++
>   src/android/jpeg/exif.h   |  1 +
>   2 files changed, 32 insertions(+)
>
> ---
>
> Hi Laurent/Kieran,
>
> Can you soft review(or test) this patch to see if anything
> is wrong with it?
> The reason I am asking, because I cannot make it work :(
> exiftool with a captured frame shows empty Timezone Offset tag as:
> ```
> Time Zone Offset                :
> ```
>
> exif tool shows nothing.
>
> I made sure a valid value being generated for timezone
> offset in setTimeStamp().
> I also checked the case where it might be preset using
> exif_data_fix and not been able to re-set again.
> But no, that doesn't seem the problem in my testing.
>
>
> diff --git a/src/android/jpeg/exif.cpp b/src/android/jpeg/exif.cpp
> index c0dbfcc..9c23cfb 100644
> --- a/src/android/jpeg/exif.cpp
> +++ b/src/android/jpeg/exif.cpp
> @@ -7,6 +7,8 @@
>   
>   #include "exif.h"
>   
> +#include <stdlib.h>
> +
>   #include "libcamera/internal/log.h"
>   
>   using namespace libcamera;
> @@ -135,6 +137,16 @@ void Exif::setShort(ExifIfd ifd, ExifTag tag, uint16_t item)
>   	exif_entry_unref(entry);
>   }
>   
> +void Exif::setSShort(ExifIfd ifd, ExifTag tag, int16_t item)
> +{
> +	ExifEntry *entry = createEntry(ifd, tag);
> +	if (!entry)
> +		return;
> +
> +	exif_set_sshort(entry->data, EXIF_BYTE_ORDER_INTEL, item);
Getting to bottom of this in the morning, exif_set_sshort seems to 
convert its passed int16_t value to character. I don't know what's the 
logic behind this [1] (apart from EXIF's quirky-ness), but this simply 
doesn't look right then. So..
> +	exif_entry_unref(entry);
> +}
> +
>   void Exif::setLong(ExifIfd ifd, ExifTag tag, uint32_t item)
>   {
>   	ExifEntry *entry = createEntry(ifd, tag);
> @@ -196,6 +208,25 @@ void Exif::setTimestamp(time_t timestamp)
>   	setString(EXIF_IFD_0, EXIF_TAG_DATE_TIME, EXIF_FORMAT_ASCII, ts);
>   	setString(EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII, ts);
>   	setString(EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_FORMAT_ASCII, ts);
> +
> +	/*
> +	 * If possible, query and set timezone information via
> +	 * EXIF_TAG_TIME_ZONE_OFFSET. There is only per-hour resolution for tag
> +	 * hence, round up hours if minutes >= 30.
> +	 */
> +	int r = strftime(str, sizeof(str), "%z", &tm);
> +	if (r > 0) {
> +		int16_t timezone = atoi(str);
> +		int16_t hour = timezone / 100;
> +		int16_t min = timezone % 100;;
Complier should have errored out on ;; , but it didn't.
Rectified locally on noticing.
> +
> +		if (min <= -30)
> +			hour--;
> +		else if (min >= 30)
> +			hour++;
> +
> +		setSShort(EXIF_IFD_0, EXIF_TAG_TIME_ZONE_OFFSET, hour);
Instead of setSShort call, if we use setString, things seems to get 
moving. Something like:
setString(EXIF_IFD_0, EXIF_TAG_TIME_ZONE_OFFSET, EXIF_FORMAT_ASCII, "6");

got parsed correctly by exiftool and exif commandline utilities.

[1]: 
https://github.com/libexif/libexif/blob/master/libexif/exif-utils.c#L107-L121 

> +	}
>   }
>   
>   void Exif::setOrientation(int orientation)
> diff --git a/src/android/jpeg/exif.h b/src/android/jpeg/exif.h
> index f04cefc..9c9cc3b 100644
> --- a/src/android/jpeg/exif.h
> +++ b/src/android/jpeg/exif.h
> @@ -37,6 +37,7 @@ private:
>   			       unsigned long components, unsigned int size);
>   
>   	void setShort(ExifIfd ifd, ExifTag tag, uint16_t item);
> +	void setSShort(ExifIfd ifd, ExifTag tag, int16_t item);
>   	void setLong(ExifIfd ifd, ExifTag tag, uint32_t item);
>   	void setString(ExifIfd ifd, ExifTag tag, ExifFormat format,
>   		       const std::string &item);



More information about the libcamera-devel mailing list