From patchwork Mon Sep 1 14:16:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 24279 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 E28BEBEFBE for ; Mon, 1 Sep 2025 14:17:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8D49B69323; Mon, 1 Sep 2025 16:17:01 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="iAbByE51"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DD4B169323 for ; Mon, 1 Sep 2025 16:16:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756736217; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Hi9eIU1jnMUh3zOi9qd6XoTX8yK4IVT7e8jbhZK9cgw=; b=iAbByE51Jiuyq+Llyz+GhmEVRuhyY4k0ki0IfEmThaLGXsrjfNjKhPp/Y2FVKAVRSnFO3T VKxiadrXAGmi8KajNEbcdnljknEg0clK5rJr13OzG91PTRsXu9jhdN5Q9zBOcyJgzo3vns 56+wGSAKhh22C/eumwCmZ7brkeejrSE= Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-642-gZKJRV9JM6SKMJ1nLivJJA-1; Mon, 01 Sep 2025 10:16:54 -0400 X-MC-Unique: gZKJRV9JM6SKMJ1nLivJJA-1 X-Mimecast-MFC-AGG-ID: gZKJRV9JM6SKMJ1nLivJJA_1756736213 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 970531955F26; Mon, 1 Sep 2025 14:16:53 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.45.224.12]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 17DC31800280; Mon, 1 Sep 2025 14:16:50 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , "Bryan O'Donoghue" , Kieran Bingham , Pavel Machek Subject: [PATCH v2 1/1] apps: cam: Support PPM output for other RGB formats Date: Mon, 1 Sep 2025 16:16:42 +0200 Message-ID: <20250901141643.29136-2-mzamazal@redhat.com> In-Reply-To: <20250901141643.29136-1-mzamazal@redhat.com> References: <20250901141643.29136-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: FMuo2LrT-jF3lelFvAwwuWGEixCzXd3MQUMzuSrnPuQ_1756736213 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true 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" GPU ISP can produce only 32-bit output. Let's add support to the PPM writer for all the common RGB image formats so that we can store GPU ISP output as PPM files. Contingent alpha values are ignored as there is no support for the alpha channel in PPM. There is no obvious performance penalty in my environment compared to output in the raw format. Co-developed-by: Pavel Machek Signed-off-by: Milan Zamazal Signed-off-by: Pavel Machek --- src/apps/common/ppm_writer.cpp | 66 ++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/apps/common/ppm_writer.cpp b/src/apps/common/ppm_writer.cpp index 368de8bf6..9ba0216a0 100644 --- a/src/apps/common/ppm_writer.cpp +++ b/src/apps/common/ppm_writer.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -20,8 +22,56 @@ int PPMWriter::write(const char *filename, const StreamConfiguration &config, const Span &data) { - if (config.pixelFormat != formats::BGR888) { - std::cerr << "Only BGR888 output pixel format is supported (" + size_t rPos, gPos, bPos, bytesPerPixel; + switch (config.pixelFormat) { + case libcamera::formats::R8: + rPos = 0; + gPos = 0; + bPos = 0; + bytesPerPixel = 1; + break; + case libcamera::formats::RGB888: + rPos = 2; + gPos = 1; + bPos = 0; + bytesPerPixel = 3; + break; + case libcamera::formats::BGR888: + rPos = 0; + gPos = 1; + bPos = 2; + bytesPerPixel = 3; + break; + case libcamera::formats::ARGB8888: + case libcamera::formats::XRGB8888: + rPos = 2; + gPos = 1; + bPos = 0; + bytesPerPixel = 4; + break; + case libcamera::formats::RGBA8888: + case libcamera::formats::RGBX8888: + rPos = 3; + gPos = 2; + bPos = 1; + bytesPerPixel = 4; + break; + case libcamera::formats::ABGR8888: + case libcamera::formats::XBGR8888: + rPos = 0; + gPos = 1; + bPos = 2; + bytesPerPixel = 4; + break; + case libcamera::formats::BGRA8888: + case libcamera::formats::BGRX8888: + rPos = 1; + gPos = 2; + bPos = 3; + bytesPerPixel = 4; + break; + default: + std::cerr << "Only RGB output pixel formats are supported (" << config.pixelFormat << " requested)" << std::endl; return -EINVAL; } @@ -42,8 +92,18 @@ int PPMWriter::write(const char *filename, const unsigned int rowLength = config.size.width * 3; const char *row = reinterpret_cast(data.data()); + const bool transform = config.pixelFormat != formats::BGR888; + std::vector transformedRow(transform ? rowLength : 0); + for (unsigned int y = 0; y < config.size.height; y++, row += config.stride) { - output.write(row, rowLength); + if (transform) + for (unsigned int x = 0; x < config.size.width; x++) { + transformedRow[x * 3] = row[x * bytesPerPixel + rPos]; + transformedRow[x * 3 + 1] = row[x * bytesPerPixel + gPos]; + transformedRow[x * 3 + 2] = row[x * bytesPerPixel + bPos]; + } + + output.write((transform ? transformedRow.data() : row), rowLength); if (!output) { std::cerr << "Failed to write image data at row " << y << std::endl; return -EIO;