fwt_software/include/fgc/RawImage.h

73 lines
3.5 KiB
C++

#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
namespace fgc {
// How a camera frame's bytes are laid out. The camera profile decides which one
// arrives (PixelFormat in the XML); the program accepts these and refuses others.
//
// Mono8 one byte per pixel, grey
// RGB8 three bytes per pixel, R G B - de-Bayered on the camera
// BayerRG8 one byte per pixel, the raw sensor mosaic:
// R G R G ...
// G B G B ...
// BayerRG12p the same mosaic at 12 bits, packed: two pixels in three bytes
// (GenICam "12p": p0 = b0 | (b1 & 0x0F) << 8,
// p1 = b1 >> 4 | b2 << 4)
// BayerRG12Packed
// the same, packed the GigE Vision 1.x way that older GigE
// cameras use (the Manta G-1236C on rietschen): the first byte
// holds p0's HIGH bits, not its low ones
// p0 = b0 << 4 | (b1 & 0x0F),
// p1 = b2 << 4 | b1 >> 4
// Same size as BayerRG12p; read as 12p it would scramble every
// other pixel.
// Mono16 two bytes per pixel, grey, host byte order - the thermal
// camera's counts (TarisCameraSource.h), all 16 bits used
//
// OpenCV names Bayer patterns by the second row, so the camera's BayerRG is
// OpenCV's COLOR_BayerBG2* (measured 2026-09-30 against the camera's own RGB8).
enum class PixelLayout { Unknown, Mono8, RGB8, BayerRG8, BayerRG12p, Mono16, BayerRG12Packed };
// The GenICam name ("BayerRG12p", "BayerRG12Packed"), or "Unknown".
const char* layoutName(PixelLayout layout);
// From a GenICam name; Unknown for anything the program does not handle.
PixelLayout layoutFromName(const std::string& name);
// True for the raw mosaic layouts, which need de-Bayering before saving as colour.
bool layoutIsBayer(PixelLayout layout);
// Bits per value as delivered: 8, 12 for the 12-bit mosaics, 16 for Mono16. 0
// for Unknown.
int layoutBits(PixelLayout layout);
// Bytes one frame of width x height takes in this layout (0 for Unknown).
size_t layoutFrameBytes(PixelLayout layout, uint32_t width, uint32_t height);
// Unpack `pixels` BayerRG12p values from `in` into one 16-bit word each
// (0..4095). `in` holds ceil(pixels * 3 / 2) bytes; an odd last pixel uses the
// low half of its pair, as GenICam specifies.
void unpack12p(const uint8_t* in, uint16_t* out, size_t pixels);
// The same for BayerRG12Packed (GigE Vision 1.x packing, see PixelLayout).
void unpack12Packed(const uint8_t* in, uint16_t* out, size_t pixels);
// Either of the two, by layout: the 12-bit mosaic unpacked to 16-bit words.
void unpack12(PixelLayout layout, const uint8_t* in, uint16_t* out, size_t pixels);
// Brightness of a frame from a sparse sample of its pixels: every `stride`-th
// pixel, so all colour sites of a mosaic are visited. Cheap enough to run on
// every frame the camera delivers (a few thousand samples).
// mean on a 0..255 scale whatever the bit depth (12-bit values / 16,
// 16-bit values / 256)
// clipped share of samples at or near white (>= 250 on that scale)
struct BrightnessSample {
double mean = -1.0;
double clipped = -1.0;
size_t samples = 0;
bool valid() const { return samples > 0; }
};
BrightnessSample sampleBrightness(const uint8_t* frame, size_t bytes, PixelLayout layout,
uint32_t width, uint32_t height, size_t stride = 997);
} // namespace fgc