From patchwork Wed Sep 23 19:17:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9766 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 84DD6C3B5B for ; Wed, 23 Sep 2020 19:17:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CE43762FE3; Wed, 23 Sep 2020 21:17:39 +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="fS3IpHlx"; 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 3CF5060576 for ; Wed, 23 Sep 2020 21:17:37 +0200 (CEST) From: Umang Jain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=uajain.com; s=mail; t=1600888656; bh=3VfsXSLSqom5fJbAEwHjTM0UvOegq6nooHOy3QIgMzg=; h=From:To:Cc:Subject:In-Reply-To:References; b=fS3IpHlxs8q0gJcXnI+DGnn3PqRCrn5ETqKdRsIwHUDNR1kdfS+3uHCcb3apYSh6f FaRnjOFIsyLaUndRpYouidTZlBxud7lyFyOUwjKQ8MkeeOmLfBmsxCwX/6AgoVkREm Dnrlalaa5OSzMRnAbawgxmBmxrVRyHCcwdxRF2aQkRuOqGhgjBTBziJSUj2EzGFCo2 nI1MvahRrK5vKxwQXt+ONOf579gCq1SJqk21xBkwjp2Oihkc1kVri429uccyXQwEG+ i/icu8d+g9Ti+mdFVwlpwspzwsxAhRZODzy8hBpOw/18bV12Ps2NTZ7G5y6y6+79QO +9gVM+8tIjlew== To: libcamera-devel@lists.libcamera.org Date: Thu, 24 Sep 2020 00:47:31 +0530 Message-Id: <20200923191731.11433-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 PATCH v2] 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" Hi, Again posting as a RFC but the patch is now functional as expected. Tested with few range of values (+ -) and didn't see a problem. Let me know what you think. --- Get timezone information from the timestamp, although the resolution for EXIF_TAG_TIME_ZONE_OFFSET is fairly limited (per-hour only). This commit also introduces a special case handling for this tag. In course of development, it was found that libexif does not support this tag practically but still carries it among its header files. The manual patching here turned out to be a small detail that can conveniently be removed as and when libexif's support for timezone information improves. 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 | 44 +++++++++++++++++++++++++++++++++++++++ src/android/jpeg/exif.h | 1 + 2 files changed, 45 insertions(+) diff --git a/src/android/jpeg/exif.cpp b/src/android/jpeg/exif.cpp index c0dbfcc..27d8fde 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,29 @@ 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; + /* + * Special case handling for EXIF_TAG_TIME_ZONE_OFFSET. We need to + * manually create and initialize an ExifEntry for this tag, since + * the intialization support is missing from libexif's function + * exif_entry_initialize(). + * + * \todo: Remove this special case when the above issue is fixed in + * libexif. + */ + if (tag == EXIF_TAG_TIME_ZONE_OFFSET) + entry = createEntry (ifd, tag, EXIF_FORMAT_SSHORT, 1, 2); + else + 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 +221,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);