From patchwork Mon Aug 24 20:46:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Umang Jain X-Patchwork-Id: 9379 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 C961FBD87C for ; Mon, 24 Aug 2020 20:46:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 96C76616B1; Mon, 24 Aug 2020 22:46:59 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=uajain.com header.i=@uajain.com header.b="Jxmu8Zua"; dkim-atps=neutral Received: from o1.f.az.sendgrid.net (o1.f.az.sendgrid.net [208.117.55.132]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BF8036170D for ; Mon, 24 Aug 2020 22:46:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=uajain.com; h=from:subject:in-reply-to:references:mime-version:to:cc: content-transfer-encoding:content-type; s=s1; bh=YE4ixvv5qRUxZRpkzwRMQjRGzw1v2wLVdDrVfoglVxU=; b=Jxmu8ZuahkLGINPfdBtt59EJd4FiXmBKz0IvNmEF331Is+Bvb9uwfFjKGjYXaiEdoqVJ icKVJ9H++77+NjBPnbGE48S6JgKQ2U/SyypHAOGvg8NCuhAoJwbbyBjbY7ZcMbpfh7j4S1 sdB6Au7EHTPhXgIYQUeMSgPsb1jT1v97M= Received: by filterdrecv-p3iad2-56dbc8bd54-l59qx with SMTP id filterdrecv-p3iad2-56dbc8bd54-l59qx-19-5F44273F-13 2020-08-24 20:46:55.37874524 +0000 UTC m=+17350.726504245 Received: from mail.uajain.com (unknown) by ismtpd0007p1hnd1.sendgrid.net (SG) with ESMTP id 8QH9Ia16Sci7ACwjKjgQcQ for ; Mon, 24 Aug 2020 20:46:55.011 +0000 (UTC) From: Umang Jain Date: Mon, 24 Aug 2020 20:46:55 +0000 (UTC) Message-Id: <20200824204646.16866-4-email@uajain.com> In-Reply-To: <20200824204646.16866-1-email@uajain.com> References: <20200824204646.16866-1-email@uajain.com> Mime-Version: 1.0 X-SG-EID: 1Q40EQ7YGir8a9gjSIAdTjhngY657NMk9ckeo4dbHZDiOpywc/L3L9rFqlwE4KPcZj5z9XHfwy1Ge6f/0y1LYyVXr4TmHaUM1xCQSxitCYfrtK45qesLCVSSmeChF10FbpdTiZRXDISHkwM5Ty/eOSQHFDEHh2zvkwNkeclaO6aO/tSQy6EZ/e1UnnUWa2cgNyPSFnvUzWTDMOMBqZr5pRhmahjoirHSXYJgZORMmLZVQcHJ9vikeaeC9hgLIPMe8kHhHHEFCDiVm4MQTH7z3g== To: libcamera-devel@lists.libcamera.org Subject: [libcamera-devel] [PATCH 3/3] android: Support initial set of EXIF metadata tags 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" Support a initial set of EXIF metadata tags namely: Make, Model, Height, Width, Orientation and Timestamp. Each tag is set by a convenient high level helper API defined in exif.h. Signed-off-by: Umang Jain --- src/android/camera_device.cpp | 8 +++++++ src/android/jpeg/encoder_libjpeg.cpp | 12 ++++++++++ src/android/jpeg/exif.cpp | 34 ++++++++++++++++++++++++++++ src/android/jpeg/exif.h | 8 +++++++ 4 files changed, 62 insertions(+) diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index bc5690e..fcf378a 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -1435,6 +1435,14 @@ void CameraDevice::requestComplete(Request *request) } Exif exif; + /* + * \todo Discuss setMake String, maybe vendor ID? + * KB suggested to leave it to "libcamera" for now. + * setModel should use the 'model' property of the camera. + */ + exif.setMake("Libcamera"); + exif.setModel("cameraModel"); + exif.setOrientation(orientation_); int jpeg_size = encoder->encode(buffer, mapped.maps()[0], &exif); if (jpeg_size < 0) { diff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp index 0cd93b6..f84def9 100644 --- a/src/android/jpeg/encoder_libjpeg.cpp +++ b/src/android/jpeg/encoder_libjpeg.cpp @@ -213,7 +213,19 @@ int EncoderLibJpeg::encode(const FrameBuffer *source, else compressRGB(&frame); + exif->setWidth(compress_.image_width); + exif->setHeight(compress_.image_height); + exif->setTimestamp(source->metadata().timestamp); + + Span exif_data = exif->generate(); + jpeg_finish_compress(&compress_); + if (exif->size()) + /* Store Exif data in the JPEG_APP1 data block. */ + jpeg_write_marker(&compress_, JPEG_APP0 + 1, + static_cast(exif_data.data()), + exif_data.size()); + return size; } diff --git a/src/android/jpeg/exif.cpp b/src/android/jpeg/exif.cpp index f6a9f5c..b7591d5 100644 --- a/src/android/jpeg/exif.cpp +++ b/src/android/jpeg/exif.cpp @@ -160,6 +160,40 @@ int Exif::setString(ExifIfd ifd, ExifTag tag, ExifFormat format, const std::stri return 0; } +int Exif::setHeight(uint16_t height) +{ + setShort(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, height); + setLong(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION, height); + + return 0; +} + +int Exif::setWidth(uint16_t width) +{ + setShort(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width); + setLong(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION, width); + + return 0; +} + +int Exif::setTimestamp(const time_t timestamp) +{ + std::string ts(std::ctime(×tamp)); + int ret = setString(EXIF_IFD_0, EXIF_TAG_DATE_TIME, EXIF_FORMAT_ASCII, ts); + if(ret < 0) + return ret; + + ret = setString(EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII, ts); + if(ret < 0) + return ret; + + ret = setString(EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_FORMAT_ASCII, ts); + if(ret < 0) + return ret; + + return ret; +} + Span Exif::generate() { if (exif_data_) { diff --git a/src/android/jpeg/exif.h b/src/android/jpeg/exif.h index 7df83c7..6a8f5f5 100644 --- a/src/android/jpeg/exif.h +++ b/src/android/jpeg/exif.h @@ -11,6 +11,7 @@ #include +#include #include class Exif @@ -24,6 +25,13 @@ public: int setString(ExifIfd ifd, ExifTag tag, ExifFormat format, const std::string &item); int setRational(ExifIfd ifd, ExifTag tag, uint32_t numerator, uint32_t denominator); + int setHeight(uint16_t height); + int setMake(const std::string &make) { return setString(EXIF_IFD_0, EXIF_TAG_MAKE, EXIF_FORMAT_ASCII, make); } + int setModel(const std::string &model) { return setString(EXIF_IFD_0, EXIF_TAG_MODEL, EXIF_FORMAT_ASCII, model); } + int setOrientation(int orientation) { return setShort(EXIF_IFD_0, EXIF_TAG_ORIENTATION, orientation); } + int setTimestamp(const time_t timestamp); + int setWidth(uint16_t width); + libcamera::Span generate(); unsigned char *data() const { return exif_data_; } unsigned int size() const { return size_; }