11#ifndef GAMP_RENDER_PIXEL_PIXELFORMAT_HPP_
12#define GAMP_RENDER_PIXEL_PIXELFORMAT_HPP_
62 uint32_t m_bitsPerPixel;
67 constexpr size_t hashCodeImpl() const noexcept {
69 size_t hash = 31 + m_bitStride;
70 hash = ((hash << 5) - hash) + m_bitsPerPixel;
71 hash = ((hash << 5) - hash) + m_compMask.size();
72 for(
size_t i=m_compOrder.size(); i-->0; ) {
73 hash = ((hash << 5) - hash) +
number(m_compOrder[i]);
75 for(
size_t i=m_compMask.size(); i-->0; ) {
76 hash = ((hash << 5) - hash) + m_compMask[i];
78 for(
size_t i=m_compOrder.size(); i-->0; ) {
79 hash = ((hash << 5) - hash) + m_compBitShift[i];
86 size_t l = mask.size();
87 for(
size_t i=0; i < l; ++i) {
91 sb.append(std::to_string(
bitCount[i])).append(
": 0x")
92 .append(jau::to_hexstring(mask[i])).append(
" << ").append(std::to_string(shift[i]));
94 return sb.append(
"]");
103 uint32_t bpc, uint32_t
bitStride) noexcept
104 : m_compCount(compCount), m_compOrder(compOrder), m_compMask(), m_compBitCount(), m_compBitShift(),
105 m_bitsPerPixel(bpc * compCount), m_bitStride(
bitStride),
106 m_uniform(
true), m_hashCode(0)
108 const uint32_t compMask = ( 1 << bpc ) - 1;
110 m_compMask[i] = compMask;
111 m_compBitShift[i] = bpc * i;
112 m_compBitCount[i] = bpc;
115 m_hashCode = hashCodeImpl();
127 : m_compCount(compCount), m_compOrder(compOrder), m_compMask(componentMask), m_compBitCount(), m_compBitShift(componentBitShift),
128 m_bitsPerPixel(0), m_bitStride(
bitStride),
129 m_uniform(
true), m_hashCode(0)
134 const uint32_t cmask = m_compMask[i];
135 const uint32_t
bitCount = std::popcount(cmask);
138 if( i > 0 && uniform ) {
139 uniform = m_compMask[i-1] == cmask;
143 m_bitsPerPixel = bpp;
145 m_hashCode = hashCodeImpl();
151 jau::to_string(m_compOrder).c_str(), m_bitStride, m_bitsPerPixel, (
int)m_uniform,
152 m_compMask.size(), toHexString(m_compBitCount, m_compMask, m_compBitShift).c_str());
159 constexpr bool isUniform() const noexcept {
return m_uniform; }
173 constexpr uint32_t
bitsPerPixel() const noexcept {
return m_bitsPerPixel; }
180 constexpr uint32_t
bitStride() const noexcept {
return m_bitStride; }
183 constexpr uint32_t
bytesPerPixel() const noexcept {
return (7+m_bitStride)/8; }
197 constexpr uint32_t
toU32(uint8_t c1NormI8)
const noexcept {
198 return ( c1NormI8 & m_compMask[0] ) << m_compBitShift[0];
200 constexpr uint32_t
toU32(uint8_t c1NormI8, uint8_t c2NormI8, uint8_t c3NormI8)
const noexcept {
201 return ( c1NormI8 & m_compMask[0] ) << m_compBitShift[0] |
202 ( c2NormI8 & m_compMask[1] ) << m_compBitShift[1] |
203 ( c3NormI8 & m_compMask[2] ) << m_compBitShift[2] ;
205 constexpr uint32_t
toU32(uint8_t c1NormI8, uint8_t c2NormI8, uint8_t c3NormI8, uint8_t c4NormI8)
const noexcept {
206 return ( c1NormI8 & m_compMask[0] ) << m_compBitShift[0] |
207 ( c2NormI8 & m_compMask[1] ) << m_compBitShift[1] |
208 ( c3NormI8 & m_compMask[2] ) << m_compBitShift[2] |
209 ( c4NormI8 & m_compMask[3] ) << m_compBitShift[3] ;
211 uint32_t
toU32(
const uint8_t* src)
const {
212 if( m_compCount == 1 ) {
213 return toU32(src[0]);
214 }
else if( m_compCount == 3 ) {
215 return toU32(src[0], src[1], src[2]);
216 }
else if( m_compCount == 4 ) {
217 return toU32(src[0], src[1], src[2], src[3]);
225 return float( ( v >> m_compBitShift[cIdx] ) & m_compMask[cIdx] ) / float( m_compMask[cIdx] ) ;
227 return float( v & m_compMask[cIdx] ) / float( m_compMask[cIdx] ) ;
230 constexpr uint32_t
fromFloat(
float f, uint32_t cIdx,
bool shiftResult)
const noexcept {
232 return shiftResult ? v << m_compBitShift[cIdx] : v;
235 constexpr uint32_t
defaultValue(uint32_t cIdx,
bool shiftResult)
const noexcept {
236 uint32_t v = (
CType::A == m_compOrder[cIdx] ||
CType::Y == m_compOrder[cIdx] )
237 ? m_compMask[cIdx] : 0;
238 return shiftResult ? v << m_compBitShift[cIdx] : v;
241 constexpr size_t hashCode() const noexcept {
return m_hashCode; }
243 constexpr bool operator==(
const PixelFormat& rhs )
const noexcept {
247 if( m_hashCode != rhs.m_hashCode ) {
250 return m_bitStride == rhs.m_bitStride &&
251 m_bitsPerPixel == rhs.m_bitsPerPixel &&
252 m_compOrder == rhs.m_compOrder &&
253 m_compMask == rhs.m_compMask &&
254 m_compBitShift == rhs.m_compBitShift;
301 virtual uint32_t
stride() const noexcept = 0;
311 virtual const uint8_t*
pixels() const noexcept = 0;
336 for(
size_t y=0; y<
m_size.y; ++y) {
338 for(
size_t x=0; x<byte_width; ++x) {
339 hash = ((hash << 5) - hash) + line[x];
364 ", must be greater than bytesPerPixel "+std::to_string(pixelformat.
bytesPerPixel())+
388 m_data = std::move(o.m_data);
396 std::unique_lock<std::mutex> lock(
m_mtx);
400 hash = ((hash << 5) - hash) +
m_size.hashCode();
419 const uint8_t*
pixels() const noexcept
override {
return m_data.data(); }
423 return "PixelRect[obj "+jau::to_hexstring(
this)+
", "+
m_pixelformat->toString()+
", "+
m_size.toString()+
491 { 0x1F, 0x3F, 0x1F },
515 { 0x1F, 0x3F, 0x1F },
540 { 0x1F, 0x1F, 0x1F, 0x01 },
541 { 0, 5, 5+5, 5+5+5 },
565 { 0x01, 0x1F, 0x1F, 0x1F },
566 { 0, 1, 1+5, 1+5+5 },
756 }
else if( fmt ==
BGR565 ) {
762 }
else if( fmt ==
RGB888 ) {
764 }
else if( fmt ==
BGR888 ) {
779 static uint32_t
toU32(
const PixelFormat& dst_fmt, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
781 const uint8_t l = (uint8_t) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) * a );
782 return ( 0xff ) << 24 | ( 0xff & l ) << 16 | ( 0xff & l ) << 8 | ( 0xff & l );
783 }
else if(dst_fmt ==
RGB888) {
784 return ( 0xff ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
785 }
else if(dst_fmt ==
BGR888) {
786 return ( 0xff ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
788 return ( 0xff & a ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
790 return ( 0xff & r ) << 24 | ( 0xff & g ) << 16 | ( 0xff & b ) << 8 | ( 0xff & a );
792 return ( 0xff & b ) << 24 | ( 0xff & g ) << 16 | ( 0xff & r ) << 8 | ( 0xff & a );
794 return ( 0xff & a ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
808 }
else if(src_fmt ==
RGB888) {
813 }
else if(src_fmt ==
BGR888) {
841 return toU32(dst_fmt, r, g, b, a);
847 r =
static_cast<uint8_t
>(src_pixel);
850 a =
static_cast<uint8_t
>(0xff);
851 }
else if( src_fmt ==
RGB888 ) {
852 r =
static_cast<uint8_t
>(src_pixel);
853 g =
static_cast<uint8_t
>(src_pixel >> 8);
854 b =
static_cast<uint8_t
>(src_pixel >> 16);
855 a =
static_cast<uint8_t
>(0xff);
856 }
else if( src_fmt ==
BGR888 ) {
857 b =
static_cast<uint8_t
>(src_pixel);
858 g =
static_cast<uint8_t
>(src_pixel >> 8);
859 r =
static_cast<uint8_t
>(src_pixel >> 16);
860 a =
static_cast<uint8_t
>(0xff);
862 r =
static_cast<uint8_t
>(src_pixel);
863 g =
static_cast<uint8_t
>(src_pixel >> 8);
864 b =
static_cast<uint8_t
>(src_pixel >> 16);
865 a =
static_cast<uint8_t
>(src_pixel >> 24);
867 a =
static_cast<uint8_t
>(src_pixel);
868 b =
static_cast<uint8_t
>(src_pixel >> 8);
869 g =
static_cast<uint8_t
>(src_pixel >> 16);
870 r =
static_cast<uint8_t
>(src_pixel >> 24);
872 a =
static_cast<uint8_t
>(src_pixel);
873 r =
static_cast<uint8_t
>(src_pixel >> 8);
874 g =
static_cast<uint8_t
>(src_pixel >> 16);
875 b =
static_cast<uint8_t
>(src_pixel >> 24);
877 b =
static_cast<uint8_t
>(src_pixel);
878 g =
static_cast<uint8_t
>(src_pixel >> 8);
879 r =
static_cast<uint8_t
>(src_pixel >> 16);
880 a =
static_cast<uint8_t
>(src_pixel >> 24);
884 return toU32(dst_fmt, r, g, b, a);
888 const PixelFormat& destFmt, uint32_t ddestStride,
bool isGLOriented) {
890 if( 0 != ddestStride ) {
891 destStride = ddestStride;
936 const uint8_t* src_pixels,
const PixelFormat& src_fmt,
bool src_glOriented, uint32_t src_lineStride,
937 uint8_t* dst_pixels,
const PixelFormat& dst_fmt,
bool dst_glOriented, uint32_t dst_lineStride) {
938 const uint32_t height = size.
y;
939 const uint32_t width = size.
x;
949 if( 0 != src_lineStride ) {
950 if( src_lineStride < src_bpp * width ) {
955 src_lineStride = src_bpp * width;
957 if( 0 != dst_lineStride ) {
958 if( dst_lineStride < dst_bpp * width ) {
963 dst_lineStride = dst_bpp * width;
967 const uint32_t dst_comp_bitStride = dst_fmt.
bitStride();
968 const bool vert_flip = src_glOriented != dst_glOriented;
969 const bool fast_copy = src_fmt == dst_fmt && 0 == dst_comp_bitStride%8;
972 System.err.println(
"XXX: size "+width+
"x"+height+
", fast_copy "+fast_copy);
973 System.err.println(
"XXX: SRC fmt "+src_fmt+
", "+src_comp+
", stride "+src_lineStride+
", isGLOrient "+src_glOriented);
974 System.err.println(
"XXX: DST fmt "+dst_fmt+
", "+dst_comp+
", stride "+dst_lineStride+
", isGLOrient "+dst_glOriented);
980 if( !vert_flip && dst_lineStride == src_lineStride ) {
981 std::memcpy(dst_pixels, src_pixels, width*dst_lineStride*height);
982 }
else if( vert_flip ) {
983 for(uint32_t y=0; y<height; ++y) {
984 const uint32_t src_off = ( height - 1 - y ) * src_lineStride;
985 const uint32_t dst_off = dst_lineStride*y;
986 std::memcpy(dst_pixels+dst_off, src_pixels+src_off, width*dst_bpp);
989 for(uint32_t y=0; y<height; ++y) {
990 const uint32_t src_off = y * src_lineStride;
991 const uint32_t dst_off = dst_lineStride*y;
992 std::memcpy(dst_pixels+dst_off, src_pixels+src_off, width*dst_bpp);
999 for(uint32_t y=0; y<height; y++) {
1000 const uint32_t src_off = vert_flip ? ( height - 1 - y ) * src_lineStride : y * src_lineStride;
1001 const uint32_t dst_off = dst_lineStride*y;
1002 const uint8_t* src_pos = src_pixels+src_off;
1003 uint8_t* dst_pos = dst_pixels+dst_off;
1004 for(uint32_t x=0; x<width; ++x) {
1005 convert(cmap, dst_fmt, dst_pos, src_fmt, src_pos);
1008 dstBitStream.skip(( dst_lineStride * 8 ) - ( dst_comp_bitStride * width ));
1015 uint8_t* dstBitStream,
1017 const uint8_t* srcBitStream)
1029 sc[sIdx] = srcBitStream.readBits31(srcCompBitCount[sIdx]) & srcCompBitMask[sIdx];
1034 for(
int i=0; i<dCompCount; i++) {
1038 if( 1 == dCompCount &&
1039 PixelFormat.CType::Y == dstComp.componentOrder()[0] &&
1044 final int r = sc[cmap.srcRGBA[0]];
1045 final int g = sc[cmap.srcRGBA[1]];
1046 final int b = sc[cmap.srcRGBA[2]];
1047 final float rF = srcComp.
toFloat(r, cmap.srcRGBA[0],
false);
1048 final float gF = srcComp.
toFloat(g, cmap.srcRGBA[1],
false);
1049 final float bF = srcComp.
toFloat(b, cmap.srcRGBA[2],
false);
1059 final float lF = ( rF + gF + bF ) * aF / 3
f;
1060 final int v = dstComp.
fromFloat(lF, 0,
false);
1062 dstBitStream.writeBits31(dstCompBitCount[0], v);
1065 if( srcBitStream.position() <= 8*4 ) {
1066 System.err.printf(
"convert: rgb[a] -> Y: rgb 0x%02X 0x%02X 0x%02X 0x%02X -> %f %f %f %f"+
1067 " -> %f -> dstC 0 0x%08X (%d bits: %s)%n",
1070 lF, v, dstCompBitCount[0], Bitstream.toBinString(
true, v, dstCompBitCount[0])
1077 for(
int dIdx=0; dIdx<dCompCount; dIdx++) {
1079 if( 0 <= ( sIdx = cmap.dst2src[dIdx] ) ) {
1080 final float f = srcComp.
toFloat(sc[sIdx], sIdx,
false);
1081 final int v = dstComp.
fromFloat(
f, dIdx,
false);
1082 dstBitStream.writeBits31(dstCompBitCount[dIdx], v);
1084 if( srcBitStream.position() <= 8*4 ) {
1085 System.err.printf(
"convert: srcC %d: 0x%08X -> %f -> dstC %d 0x%08X (%d bits: %s)%n",
1086 sIdx, sc[sIdx],
f, dIdx, v, dstCompBitCount[dIdx], Bitstream.toBinString(
true, v, dstCompBitCount[dIdx]));
1090 dstBitStream.writeBits31(dstCompBitCount[dIdx], dcDef[dIdx]);
1092 if( srcBitStream.position() <= 8*4 ) {
1093 System.err.printf(
"convert: srcC %d: undef -> dstC %d 0x%08X (%d bits: %s)%n",
1094 sIdx, dIdx, dcDef[dIdx], dstCompBitCount[dIdx], Bitstream.toBinString(
true, dcDef[dIdx], dstCompBitCount[dIdx]));
Generic PixelRectangle implementation.
jau::sc_atomic_bool m_hashCodeComputed
uint8_t * mutablePixels() noexcept override
Returns the pixels, mutable.
std::vector< uint8_t > m_data
const Point2u32 & size() const noexcept override
Returns the size, i.e.
uint32_t stride() const noexcept override
Returns stride in byte-size, i.e.
const uint8_t * pixels() const noexcept override
Returns the pixels.
size_t hashCode() const noexcept override
GenericPixelRect & operator=(const GenericPixelRect &) noexcept=delete
std::string toString() const override
bool isGLOriented() const noexcept override
Returns true if the memory is laid out in OpenGL's coordinate system, origin at bottom left.
GenericPixelRect(const PixelFormat &pixelformat, const Point2u32 &size, uint32_t strideInBytes, bool isGLOriented)
GenericPixelRect(GenericPixelRect &&o) noexcept
GenericPixelRect(const GenericPixelRect &o) noexcept=delete
const PixelFormat * m_pixelformat
size_t pixelHashCode() const noexcept
const PixelFormat & format() const noexcept override
Returns the PixelFormat.
GenericPixelRect & operator=(GenericPixelRect &&o) noexcept
Pixel Rectangle identified by it's hashCode().
virtual size_t hashCode() const noexcept=0
virtual const Point2u32 & size() const noexcept=0
Returns the size, i.e.
~PixelRectangle() noexcept=default
virtual std::string toString() const =0
virtual uint32_t stride() const noexcept=0
Returns stride in byte-size, i.e.
virtual const PixelFormat & format() const noexcept=0
Returns the PixelFormat.
virtual bool isGLOriented() const noexcept=0
Returns true if the memory is laid out in OpenGL's coordinate system, origin at bottom left.
virtual const uint8_t * pixels() const noexcept=0
Returns the pixels.
virtual uint8_t * mutablePixels() noexcept=0
Returns the pixels, mutable.
ordered_atomic< bool, std::memory_order_seq_cst > sc_atomic_bool
SC atomic integral scalar boolean.
constexpr std::underlying_type_t< E > number(const E v) noexcept
consteval_cxx20 void consteval_assert(bool v)
#define consteval_cxx20
consteval qualifier replacement for C++20 consteval.
constexpr jau::uint_bytes_t< sizeof(T)> round_to_uint(const T v) noexcept
Returns the rounded value cast to unsigned int.
std::array< uint32_t, 4 > u32array4_t
uint32_t find(CType s, jau::nsize_t poolCount, const comparray4_t &pool, bool mapRGB2Y) noexcept
Returns first index of given CType within pool , npos if not exists.
std::array< CType, 4 > comparray4_t
@ Y
Luminance component, e.g.
uint_bytes_t< sizeof(unsigned long int)> nsize_t
Natural 'size_t' alternative using uint<XX>_t with xx = sizeof(unsigned long int)*8 as its natural si...
Point2I< uint32_t > Point2u32
constexpr std::string format_string_n(const std::size_t maxStrLen, const std::string_view &format, const Args &...args)
Safely returns a (potentially truncated) string according to snprintf() formatting rules and variable...
std::string to_string(const bit_order_t v) noexcept
Return std::string representation of the given bit_order_t.
static std::string f(uint32_t v)
static constexpr const bool DEBUG_MODE