diff --git a/apps/rpicam_still.cpp b/apps/rpicam_still.cpp index 7134c7b7..5721edcd 100644 --- a/apps/rpicam_still.cpp +++ b/apps/rpicam_still.cpp @@ -166,8 +166,10 @@ static void event_loop(RPiCamStillApp &app) bool output = !options->output.empty() || options->datetime || options->timestamp; // output requested? bool keypress = options->keypress || options->signal; // "signal" mode is much like "keypress" mode unsigned int still_flags = RPiCamApp::FLAG_STILL_NONE; - if (options->encoding == "rgb" || options->encoding == "png") + if (options->encoding == "rgb24" || options->encoding == "png") still_flags |= RPiCamApp::FLAG_STILL_BGR; + if (options->encoding == "rgb48") + still_flags |= RPiCamApp::FLAG_STILL_BGR48; else if (options->encoding == "bmp") still_flags |= RPiCamApp::FLAG_STILL_RGB; if (options->raw) diff --git a/core/rpicam_app.cpp b/core/rpicam_app.cpp index ac3e5cfb..ffddb249 100644 --- a/core/rpicam_app.cpp +++ b/core/rpicam_app.cpp @@ -525,6 +525,10 @@ void RPiCamApp::ConfigureStill(unsigned int flags) configuration_->at(0).pixelFormat = libcamera::formats::BGR888; else if (flags & FLAG_STILL_RGB) configuration_->at(0).pixelFormat = libcamera::formats::RGB888; + else if (flags & FLAG_STILL_BGR48) + configuration_->at(0).pixelFormat = libcamera::formats::BGR161616; + else if (flags & FLAG_STILL_RGB48) + configuration_->at(0).pixelFormat = libcamera::formats::RGB161616; else configuration_->at(0).pixelFormat = libcamera::formats::YUV420; if ((flags & FLAG_STILL_BUFFER_MASK) == FLAG_STILL_DOUBLE_BUFFER) diff --git a/core/rpicam_app.hpp b/core/rpicam_app.hpp index 4b10c63c..2653f144 100644 --- a/core/rpicam_app.hpp +++ b/core/rpicam_app.hpp @@ -111,12 +111,14 @@ class RPiCamApp // Some flags that can be used to give hints to the camera configuration. static constexpr unsigned int FLAG_STILL_NONE = 0; - static constexpr unsigned int FLAG_STILL_BGR = 1; // supply BGR images, not YUV - static constexpr unsigned int FLAG_STILL_RGB = 2; // supply RGB images, not YUV - static constexpr unsigned int FLAG_STILL_RAW = 4; // request raw image stream - static constexpr unsigned int FLAG_STILL_DOUBLE_BUFFER = 8; // double-buffer stream - static constexpr unsigned int FLAG_STILL_TRIPLE_BUFFER = 16; // triple-buffer stream - static constexpr unsigned int FLAG_STILL_BUFFER_MASK = 24; // mask for buffer flags + static constexpr unsigned int FLAG_STILL_BGR = 1; // supply BGR 24bpp images, not YUV + static constexpr unsigned int FLAG_STILL_BGR48 = 2; // supply BGR 48bpp images, not YUV + static constexpr unsigned int FLAG_STILL_RGB = 4; // supply RGB images, not YUV + static constexpr unsigned int FLAG_STILL_RGB48 = 8; // supply RGB 48bpp images, not YUV + static constexpr unsigned int FLAG_STILL_RAW = 16; // request raw image stream + static constexpr unsigned int FLAG_STILL_DOUBLE_BUFFER = 32; // double-buffer stream + static constexpr unsigned int FLAG_STILL_TRIPLE_BUFFER = 64; // triple-buffer stream + static constexpr unsigned int FLAG_STILL_BUFFER_MASK = 96; // mask for buffer flags static constexpr unsigned int FLAG_VIDEO_NONE = 0; static constexpr unsigned int FLAG_VIDEO_RAW = 1; // request raw image stream diff --git a/core/still_options.hpp b/core/still_options.hpp index 6d125bd4..1d1fbe74 100644 --- a/core/still_options.hpp +++ b/core/still_options.hpp @@ -39,7 +39,7 @@ struct StillOptions : public Options ("thumb", value(&thumb)->default_value("320:240:70"), "Set thumbnail parameters as width:height:quality, or none") ("encoding,e", value(&encoding)->default_value("jpg"), - "Set the desired output encoding, either jpg, png, rgb, bmp or yuv420") + "Set the desired output encoding, either jpg, png, rgb/rgb24, rgb48, bmp or yuv420") ("raw,r", value(&raw)->default_value(false)->implicit_value(true), "Also save raw file in DNG format") ("latest", value(&latest), @@ -88,8 +88,10 @@ struct StillOptions : public Options encoding = "jpg"; else if (strcasecmp(encoding.c_str(), "yuv420") == 0) encoding = "yuv420"; - else if (strcasecmp(encoding.c_str(), "rgb") == 0) - encoding = "rgb"; + else if (strcasecmp(encoding.c_str(), "rgb") == 0 || strcasecmp(encoding.c_str(), "rgb24") == 0) + encoding = "rgb24"; + else if (strcasecmp(encoding.c_str(), "rgb48") == 0) + encoding = "rgb48"; else if (strcasecmp(encoding.c_str(), "png") == 0) encoding = "png"; else if (strcasecmp(encoding.c_str(), "bmp") == 0) diff --git a/image/yuv.cpp b/image/yuv.cpp index 7f03a5f9..d9a24ea6 100644 --- a/image/yuv.cpp +++ b/image/yuv.cpp @@ -115,7 +115,7 @@ static void yuyv_save(std::vector> const &mem, StreamIn static void rgb_save(std::vector> const &mem, StreamInfo const &info, std::string const &filename, StillOptions const *options) { - if (options->encoding != "rgb") + if (options->encoding != "rgb24" && options->encoding != "rgb48") throw std::runtime_error("encoding should be set to rgb"); FILE *fp = filename == "-" ? stdout : fopen(filename.c_str(), "w"); if (!fp) @@ -123,9 +123,12 @@ static void rgb_save(std::vector> const &mem, StreamInf try { uint8_t *ptr = (uint8_t *)mem[0].data(); + unsigned int wr_stride = 3 * info.width; + if (options->encoding == "rgb48") + wr_stride *= 2; for (unsigned int j = 0; j < info.height; j++, ptr += info.stride) { - if (fwrite(ptr, 3 * info.width, 1, fp) != 1) + if (fwrite(ptr, wr_stride, 1, fp) != 1) throw std::runtime_error("failed to write file " + filename); } if (fp != stdout) @@ -146,7 +149,8 @@ void yuv_save(std::vector> const &mem, StreamInfo const yuyv_save(mem, info, filename, options); else if (info.pixel_format == libcamera::formats::YUV420) yuv420_save(mem, info, filename, options); - else if (info.pixel_format == libcamera::formats::BGR888 || info.pixel_format == libcamera::formats::RGB888) + else if (info.pixel_format == libcamera::formats::BGR888 || info.pixel_format == libcamera::formats::RGB888 || + info.pixel_format == libcamera::formats::BGR161616 || info.pixel_format == libcamera::formats::RGB161616) rgb_save(mem, info, filename, options); else throw std::runtime_error("unrecognised YUV/RGB save format"); diff --git a/utils/test.py b/utils/test.py index 2b0a426d..3fc66f08 100755 --- a/utils/test.py +++ b/utils/test.py @@ -199,10 +199,12 @@ def check_metadata_txt(file, preamble): def test_still(exe_dir, output_dir): + platform = get_platform() executable = os.path.join(exe_dir, 'rpicam-still') output_jpg = os.path.join(output_dir, 'test.jpg') output_png = os.path.join(output_dir, 'test.png') output_bmp = os.path.join(output_dir, 'test.bmp') + output_rgb48 = os.path.join(output_dir, 'test.rgb') output_dng = os.path.join(output_dir, 'test.dng') output_metadata = os.path.join(output_dir, 'metadata.json') output_metadata_txt = os.path.join(output_dir, 'metadata.txt') @@ -256,6 +258,15 @@ def test_still(exe_dir, output_dir): check_time(time_taken, 1.2, 10, "test_still: bmp test") check_size(output_png, 1024, "test_still: bmp test") + if platform == 'pisp': + # "rgb48 test". Writes a 16bpp RGB raw image. + print(" 48bpp test") + retcode, time_taken = run_executable( + [executable, '-t', '1000', '-e', 'rgb48', '-o', output_rgb48], logfile) + check_retcode(retcode, "test_still: rgb48 test") + check_time(time_taken, 1.2, 10, "test_still: rgb48 test") + check_size(output_rgb48, 1024 * 1024, "test_still: rgb48 test") + # "dng test". Write a dng along with the jpg. print(" dng test") retcode, time_taken = run_executable(