Skip to content

Commit

Permalink
rpicam_still: Add RGB/BGR 48bpp support
Browse files Browse the repository at this point in the history
Add support for 48-bpp RGB/BGR formats that can be generated by the
PiSP.  rpicam-still can select this with the "--encoding rgb48" command
line option.

Signed-off-by: Naushir Patuck <[email protected]>
  • Loading branch information
naushir committed Feb 16, 2024
1 parent d838b45 commit 8e5224b
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 13 deletions.
4 changes: 3 additions & 1 deletion apps/rpicam_still.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions core/rpicam_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 8 additions & 6 deletions core/rpicam_app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions core/still_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct StillOptions : public Options
("thumb", value<std::string>(&thumb)->default_value("320:240:70"),
"Set thumbnail parameters as width:height:quality, or none")
("encoding,e", value<std::string>(&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<bool>(&raw)->default_value(false)->implicit_value(true),
"Also save raw file in DNG format")
("latest", value<std::string>(&latest),
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 7 additions & 3 deletions image/yuv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,20 @@ static void yuyv_save(std::vector<libcamera::Span<uint8_t>> const &mem, StreamIn
static void rgb_save(std::vector<libcamera::Span<uint8_t>> 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)
throw std::runtime_error("failed to open file " + filename);
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)
Expand All @@ -146,7 +149,8 @@ void yuv_save(std::vector<libcamera::Span<uint8_t>> 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");
Expand Down
11 changes: 11 additions & 0 deletions utils/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 8e5224b

Please sign in to comment.