From patchwork Tue Sep 22 16:26:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9744 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id DC206C3B5C for ; Tue, 22 Sep 2020 16:26:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4961B62FD8; Tue, 22 Sep 2020 18:26:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="ozmYENnL"; dkim-atps=neutral Received: from mail.uajain.com (static.126.159.217.95.clients.your-server.de [95.217.159.126]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D9D936036A for ; Tue, 22 Sep 2020 18:26:30 +0200 (CEST) From: Umang Jain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=uajain.com; s=mail; t=1600791990; bh=eJcgU5nj7I+fnhaul8s4ybYXiwqWfU+Y2+iTU2aK1Kg=; h=From:To:Cc:Subject:In-Reply-To:References; b=ozmYENnLaX4jrqV/dq0TSGD5G3et7kaT0hNpTRFcbXufAIdPU3k2XlxX+osHQ5xLK FKegpG6Fwb6rsU5dnQRRRd7JdDZMJt4BpygVQTzT9Q9RWKpSNEURSF6hHm6IJoa0pc v5fb2q/Nz67vQvMiVjCWBbn0M2MxFwSZvUpemRt+NFR6SI6u4RFu09AYpuW5ljI3AZ 9WqwTFbJnoZXd0GlScGxyfF5dgNazlSd1QeeEXN8x3l0kTd1MsYFDrOvZHyMfaMnKh ryjEqPpNnQU7Um7OTG+Opl9fNbbLRDMtSUnDt5SkW9DggM2XB8595li5Fdbg4mcedS AGpyYvx9fyvCw== To: libcamera-devel@lists.libcamera.org Date: Tue, 22 Sep 2020 21:56:24 +0530 Message-Id: <20200922162624.32321-1-email@uajain.com> In-Reply-To: <20200909153206.7700-1-email@uajain.com> References: <20200909153206.7700-1-email@uajain.com> Mime-Version: 1.0 Subject: [libcamera-devel] [RFC v1 PATCH] android: jpeg: exif: Set timezone information X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- 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 + #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); + 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;; + + if (min <= -30) + hour--; + else if (min >= 30) + hour++; + + setSShort(EXIF_IFD_0, EXIF_TAG_TIME_ZONE_OFFSET, hour); + } } 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);