diff mbox series

[raw2rgbpnm,3/3] Add support for multi plane formats with stride

Message ID 20250312191710.1823147-4-niklas.soderlund@ragnatech.se
State New
Headers show
Series Add support for multi plane formats with strides | expand

Commit Message

Niklas Söderlund March 12, 2025, 7:17 p.m. UTC
Parsing NV16 that have a stride that is larger then the image width
results in incorrect frames, and no warning message being printed.

Fix this by extending the format information structure with how many
(concatenated) planes an image is constructed of. And by extending the
raw reader to take this information into account.

With this change it is possible to parse NV12, NV21, NV16, and NV61
frames from disk with a stride larger then the image width and have
correct frames produced.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
---
 raw2rgbpnm.c | 121 +++++++++++++++++++++++++++------------------------
 1 file changed, 65 insertions(+), 56 deletions(-)
diff mbox series

Patch

diff --git a/raw2rgbpnm.c b/raw2rgbpnm.c
index d8d4bb198498..5838bc7347e9 100644
--- a/raw2rgbpnm.c
+++ b/raw2rgbpnm.c
@@ -55,60 +55,61 @@  static const struct format_info {
 	unsigned int y_pos;
 	unsigned int cb_pos;
 	unsigned int cr_pos;
+	unsigned int planes;
 } v4l2_pix_fmt_str[] = {
-	{ V4L2_PIX_FMT_RGB332,	8,  0,  "RGB332 (8 RGB-3-3-2)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_RGB555,	16, 5,  "RGB555 (16 RGB-5-5-5)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_RGB565,	16, 0,  "RGB565 (16 RGB-5-6-5)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_BGR24,	24, 8,  "BGR24 (24 BGR-8-8-8)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_RGB24,	24, 8,  "RGB24 (24 RGB-8-8-8)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_BGR32,	32, 8,  "BGR32 (32 BGR-8-8-8-8)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_RGB32,	32, 8,  "RGB32 (32 RGB-8-8-8-8)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_GREY,	8,  8,  "GREY (8 Greyscale)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_Y10,	16, 10, "Y10 (10 Greyscale)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_Y12,	16, 12, "Y12 (12 Greyscale)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_Y16,	16, 16, "Y16 (16 Greyscale)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_UYVY,	16, 8,  "UYVY (16 YUV 4:2:2)", 1, 0, 2 },
-	{ V4L2_PIX_FMT_VYUY,	16, 8,  "VYUY (16 YUV 4:2:2)", 1, 2, 0 },
-	{ V4L2_PIX_FMT_YUYV,	16, 8,  "YUYV (16 YUV 4:2:2)", 0, 1, 3 },
-	{ V4L2_PIX_FMT_YVYU,	16, 8,  "YVYU (16 YUV 4:2:2)", 0, 3, 1 },
-	{ V4L2_PIX_FMT_YUV32,	32, 8,  "YUV32 (32-bit A/XYUV 8-8-8-8)", 1, 2, 3 },
-	{ V4L2_PIX_FMT_AYUV32,	32, 8,  "AYUV32 (32-bit AYUV 8-8-8-8)", 1, 2, 3 },
-	{ V4L2_PIX_FMT_XYUV32,	32, 8,  "XYUV32 (32-bit XYUV 8-8-8-8)", 1, 2, 3 },
-	{ V4L2_PIX_FMT_VUYA32,	32, 8,  "VUYA32 (32-bit VUYA 8-8-8-8)", 2, 1, 0 },
-	{ V4L2_PIX_FMT_VUYX32,	32, 8,  "VUYX32 (32-bit VUYX 8-8-8-8)", 2, 1, 0 },
-	{ V4L2_PIX_FMT_YUVA32,	32, 8,  "YUVA32 (32-bit YUVA 8-8-8-8)", 0, 1, 2 },
-	{ V4L2_PIX_FMT_YUVX32,	32, 8,  "YUVX32 (32-bit YUVX 8-8-8-8)", 0, 1, 2 },
-	{ V4L2_PIX_FMT_YUV411P,	12, 8,  "YUV411P (12 YUV 4:1:1 planar)", 0, 0, 1 },
-	{ V4L2_PIX_FMT_YUV420,	12, 8,  "YUV420P (12 YUV 4:2:0 planar)", 0, 0, 1 },
-	{ V4L2_PIX_FMT_YVU420,	12, 8,  "YVU420P (12 YVU 4:2:2 planar)", 0, 1, 0 },
-	{ V4L2_PIX_FMT_YUV422P,	16, 8,  "YUV422P (16 YUV 4:2:2 planar)", 0, 0, 1 },
-	{ V4L2_PIX_FMT_YVU422M,	16, 8,  "YVU422P (16 YVU 4:2:2 planar)", 0, 1, 0 },
-	{ V4L2_PIX_FMT_YUV444M,	24, 8,  "YUV444P (24 YUV 4:4:4 planar)", 0, 0, 1 },
-	{ V4L2_PIX_FMT_YVU444M,	24, 8,  "YVU444P (24 YVU 4:4:4 planar)", 0, 1, 0 },
-	{ V4L2_PIX_FMT_NV12,	12, 8,  "NV12 (12 Y/CbCr 4:2:0)", 0, 0, 1 },
-	{ V4L2_PIX_FMT_NV21,	12, 8,  "NV21 (12 Y/CrCb 4:2:0)", 0, 1, 0 },
-	{ V4L2_PIX_FMT_NV16,	16, 8,  "NV16 (16 Y/CbCr 4:2:2)", 0, 0, 1 },
-	{ V4L2_PIX_FMT_NV61,	16, 8,  "NV61 (16 Y/CrCb 4:2:2)", 0, 1, 0 },
-	{ V4L2_PIX_FMT_SBGGR8,	8,  8,  "SBGGR8 (8 BGBG.. GRGR..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGBRG8,	8,  8,  "SGBRG8 (8 GBGB.. RGRG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGRBG8,	8,  8,  "SGRBG8 (8 GRGR.. BGBG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SRGGB8,	8,  8,  "SRGGB8 (8 RGRG.. GBGB..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SBGGR10,	16, 10, "SBGGR10 (10 BGBG.. GRGR..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGBRG10,	16, 10, "SGBRG10 (10 GBGB.. RGRG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGRBG10,	16, 10, "SGRBG10 (10 GRGR.. BGBG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SRGGB10,	16, 10, "SRGGB10 (10 RGRG.. GBGB..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SBGGR12,	16, 12, "SBGGR12 (12 BGBG.. GRGR..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGBRG12,	16, 12, "SGBRG12 (12 GBGB.. RGRG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGRBG12,	16, 12, "SGRBG12 (12 GRGR.. BGBG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SRGGB12,	16, 12, "SRGGB12 (12 RGRG.. GBGB..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SBGGR14,	16, 14, "SBGGR14 (14 BGBG.. GRGR..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGBRG14,	16, 14, "SGBRG14 (14 GBGB.. RGRG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGRBG14,	16, 14, "SGRBG14 (14 GRGR.. BGBG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SRGGB14,	16, 14, "SRGGB14 (14 RGRG.. GBGB..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SBGGR16,	16, 16, "SBGGR16 (16 BGBG.. GRGR..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGBRG16,	16, 16, "SGBRG16 (16 GBGB.. RGRG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SGRBG16,	16, 16, "SGRBG16 (16 GRGR.. BGBG..)", 0, 0, 0 },
-	{ V4L2_PIX_FMT_SRGGB16,	16, 16, "SRGGB16 (16 RGRG.. GBGB..)", 0, 0, 0 },
+	{ V4L2_PIX_FMT_RGB332,	8,  0,  "RGB332 (8 RGB-3-3-2)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_RGB555,	16, 5,  "RGB555 (16 RGB-5-5-5)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_RGB565,	16, 0,  "RGB565 (16 RGB-5-6-5)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_BGR24,	24, 8,  "BGR24 (24 BGR-8-8-8)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_RGB24,	24, 8,  "RGB24 (24 RGB-8-8-8)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_BGR32,	32, 8,  "BGR32 (32 BGR-8-8-8-8)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_RGB32,	32, 8,  "RGB32 (32 RGB-8-8-8-8)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_GREY,	8,  8,  "GREY (8 Greyscale)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_Y10,	16, 10, "Y10 (10 Greyscale)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_Y12,	16, 12, "Y12 (12 Greyscale)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_Y16,	16, 16, "Y16 (16 Greyscale)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_UYVY,	16, 8,  "UYVY (16 YUV 4:2:2)", 1, 0, 2, 1 },
+	{ V4L2_PIX_FMT_VYUY,	16, 8,  "VYUY (16 YUV 4:2:2)", 1, 2, 0, 1 },
+	{ V4L2_PIX_FMT_YUYV,	16, 8,  "YUYV (16 YUV 4:2:2)", 0, 1, 3, 1 },
+	{ V4L2_PIX_FMT_YVYU,	16, 8,  "YVYU (16 YUV 4:2:2)", 0, 3, 1, 1 },
+	{ V4L2_PIX_FMT_YUV32,	32, 8,  "YUV32 (32-bit A/XYUV 8-8-8-8)", 1, 2, 3, 1 },
+	{ V4L2_PIX_FMT_AYUV32,	32, 8,  "AYUV32 (32-bit AYUV 8-8-8-8)", 1, 2, 3, 1 },
+	{ V4L2_PIX_FMT_XYUV32,	32, 8,  "XYUV32 (32-bit XYUV 8-8-8-8)", 1, 2, 3, 1 },
+	{ V4L2_PIX_FMT_VUYA32,	32, 8,  "VUYA32 (32-bit VUYA 8-8-8-8)", 2, 1, 0, 1 },
+	{ V4L2_PIX_FMT_VUYX32,	32, 8,  "VUYX32 (32-bit VUYX 8-8-8-8)", 2, 1, 0, 1 },
+	{ V4L2_PIX_FMT_YUVA32,	32, 8,  "YUVA32 (32-bit YUVA 8-8-8-8)", 0, 1, 2, 1 },
+	{ V4L2_PIX_FMT_YUVX32,	32, 8,  "YUVX32 (32-bit YUVX 8-8-8-8)", 0, 1, 2, 1 },
+	{ V4L2_PIX_FMT_YUV411P,	12, 8,  "YUV411P (12 YUV 4:1:1 planar)", 0, 0, 1, 1 },
+	{ V4L2_PIX_FMT_YUV420,	12, 8,  "YUV420P (12 YUV 4:2:0 planar)", 0, 0, 1, 1 },
+	{ V4L2_PIX_FMT_YVU420,	12, 8,  "YVU420P (12 YVU 4:2:2 planar)", 0, 1, 0, 1 },
+	{ V4L2_PIX_FMT_YUV422P,	16, 8,  "YUV422P (16 YUV 4:2:2 planar)", 0, 0, 1, 1 },
+	{ V4L2_PIX_FMT_YVU422M,	16, 8,  "YVU422P (16 YVU 4:2:2 planar)", 0, 1, 0, 1 },
+	{ V4L2_PIX_FMT_YUV444M,	24, 8,  "YUV444P (24 YUV 4:4:4 planar)", 0, 0, 1, 1 },
+	{ V4L2_PIX_FMT_YVU444M,	24, 8,  "YVU444P (24 YVU 4:4:4 planar)", 0, 1, 0, 1 },
+	{ V4L2_PIX_FMT_NV12,	12, 8,  "NV12 (12 Y/CbCr 4:2:0)", 0, 0, 1, 2 },
+	{ V4L2_PIX_FMT_NV21,	12, 8,  "NV21 (12 Y/CrCb 4:2:0)", 0, 1, 0, 2 },
+	{ V4L2_PIX_FMT_NV16,	16, 8,  "NV16 (16 Y/CbCr 4:2:2)", 0, 0, 1, 2 },
+	{ V4L2_PIX_FMT_NV61,	16, 8,  "NV61 (16 Y/CrCb 4:2:2)", 0, 1, 0, 2 },
+	{ V4L2_PIX_FMT_SBGGR8,	8,  8,  "SBGGR8 (8 BGBG.. GRGR..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGBRG8,	8,  8,  "SGBRG8 (8 GBGB.. RGRG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGRBG8,	8,  8,  "SGRBG8 (8 GRGR.. BGBG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SRGGB8,	8,  8,  "SRGGB8 (8 RGRG.. GBGB..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SBGGR10,	16, 10, "SBGGR10 (10 BGBG.. GRGR..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGBRG10,	16, 10, "SGBRG10 (10 GBGB.. RGRG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGRBG10,	16, 10, "SGRBG10 (10 GRGR.. BGBG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SRGGB10,	16, 10, "SRGGB10 (10 RGRG.. GBGB..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SBGGR12,	16, 12, "SBGGR12 (12 BGBG.. GRGR..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGBRG12,	16, 12, "SGBRG12 (12 GBGB.. RGRG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGRBG12,	16, 12, "SGRBG12 (12 GRGR.. BGBG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SRGGB12,	16, 12, "SRGGB12 (12 RGRG.. GBGB..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SBGGR14,	16, 14, "SBGGR14 (14 BGBG.. GRGR..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGBRG14,	16, 14, "SGBRG14 (14 GBGB.. RGRG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGRBG14,	16, 14, "SGRBG14 (14 GRGR.. BGBG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SRGGB14,	16, 14, "SRGGB14 (14 RGRG.. GBGB..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SBGGR16,	16, 16, "SBGGR16 (16 BGBG.. GRGR..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGBRG16,	16, 16, "SGBRG16 (16 GBGB.. RGRG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SGRBG16,	16, 16, "SGRBG16 (16 GRGR.. BGBG..)", 0, 0, 0, 1 },
+	{ V4L2_PIX_FMT_SRGGB16,	16, 16, "SRGGB16 (16 RGRG.. GBGB..)", 0, 0, 0, 1 },
 };
 
 static void *xalloc(int size)
@@ -130,14 +131,17 @@  static const struct format_info *get_format_info(__u32 f)
 	return NULL;
 }
 
-/* Read and return raw image data at given bits per pixel (bpp) depth. */
-static unsigned char *read_raw_data(char *filename, int width, int height, int bpp)
+/* Read and return image data at given width, height and format information. */
+static unsigned char *read_raw_data(char *filename, int width, int height,
+				    const struct format_info *info)
 {
 	/* Get file size */
 	unsigned int line_length;
 	unsigned int padding = 0;
 	unsigned char *b = NULL;
 	unsigned int i;
+	int bpp = info->bpp;
+
 	FILE *f = fopen(filename, "rb");
 	if (!f) error("fopen failed");
 	int r = fseek(f, 0, SEEK_END);
@@ -147,6 +151,11 @@  static unsigned char *read_raw_data(char *filename, int width, int height, int b
 	r = fseek(f, 0, SEEK_SET);
 	if (r!=0) error("fseek");
 
+	if (info->planes > 1) {
+		bpp = info->bpc;
+		height *= info->planes;
+	}
+
 	if (file_size*8 < width*height*bpp) error("out of input data");
 	if (file_size*8 > width*height*bpp) printf("warning: too large image file\n");
 	if (file_size % height == 0) {
@@ -741,7 +750,7 @@  int main(int argc, char *argv[])
 	}
 
 	/* Read, convert, and save image */
-	src = read_raw_data(file_in, width, height, info->bpp);
+	src = read_raw_data(file_in, width, height, info);
 	printf("Image size: %ix%i, bytes per pixel: %i, format: %s\n",
 	       width, height, info->bpp, info->name);
 	dst = xalloc(width*height*3);