Skip to content

Commit

Permalink
Updated conversion to grayscale to use weighted method instead of ave…
Browse files Browse the repository at this point in the history
…rage.
  • Loading branch information
StefanFabian committed Mar 18, 2020
1 parent 20ac6c8 commit c86fce4
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 52 deletions.
12 changes: 8 additions & 4 deletions src/image_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,24 @@ void setPixelPreMultiplied( const uint8_t *stream, uint32_t *&output )
++output;
}

template<typename T, Extractor<T> C1, Extractor<T> C2, Extractor<T> C3>
template<typename T, Extractor<T> R, Extractor<T> G, Extractor<T> B>
void setPixelGrayscale( const uint8_t *stream, uint8_t *&output )
{
*output = static_cast<uint8_t>((C1( stream, 255 ) + C2( stream, 255 ) + C3( stream, 255 )) / 3);
// Using weighted method instead of average for perceptually better results
float value = 0.299f * R( stream, 255 ) + 0.587f * G( stream, 255 ) + 0.114f * B( stream, 255 );
*output = static_cast<uint8_t>(value);
++output;
}

template<typename T, Extractor<T> C1, Extractor<T> C2, Extractor<T> C3>
template<typename T, Extractor<T> R, Extractor<T> G, Extractor<T> B>
void setPixelGrayscale( const uint8_t *stream, uint16_t *&output )
{
typedef typename std::conditional<std::is_same<T, uint8_t>::value, uint8_t, uint16_t>::type MaxType;
constexpr MaxType max = std::numeric_limits<MaxType>::max();
constexpr uint16_t mult = (std::numeric_limits<uint16_t>::max() + 1) / (max + 1);
*output = static_cast<uint16_t>((C1( stream, max ) + C2( stream, max ) + C3( stream, max )) * mult / 3);
// Using weighted method instead of average for perceptually better results
float value = 0.299f * R( stream, max ) + 0.587f * G( stream, max ) + 0.114f * B( stream, max );
*output = static_cast<uint16_t>(value * mult);
++output;
}

Expand Down
96 changes: 48 additions & 48 deletions test/image_conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ TEST( ImageConversions, testRGB8 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -192,9 +192,9 @@ TEST( ImageConversions, testRGB8 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -339,9 +339,9 @@ TEST( ImageConversions, testBGR8 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -351,9 +351,9 @@ TEST( ImageConversions, testBGR8 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -491,9 +491,9 @@ TEST( ImageConversions, testRGBA8 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -503,9 +503,9 @@ TEST( ImageConversions, testRGBA8 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -643,9 +643,9 @@ TEST( ImageConversions, testBGRA8 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -655,9 +655,9 @@ TEST( ImageConversions, testBGRA8 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -808,9 +808,9 @@ TEST( ImageConversions, testRGB16 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -820,9 +820,9 @@ TEST( ImageConversions, testRGB16 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5555, 0x5555,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C8A, 0x9645,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -972,9 +972,9 @@ TEST( ImageConversions, testBGR16 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -984,9 +984,9 @@ TEST( ImageConversions, testBGR16 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -1135,9 +1135,9 @@ TEST( ImageConversions, testRGBA16 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -1147,9 +1147,9 @@ TEST( ImageConversions, testRGBA16 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down Expand Up @@ -1298,9 +1298,9 @@ TEST( ImageConversions, testBGRA16 )
EXPECT_EQ( num_bytes, 2 * 3 );
EXPECT_EQ( bytes_per_line, 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
EXPECT_TRUE( compareImage( data, { 85, 85,
100, 100,
56, 166 } ));
EXPECT_TRUE( compareImage( data, { 76, 149,
118, 81,
75, 155 } ));
}

{
Expand All @@ -1310,9 +1310,9 @@ TEST( ImageConversions, testBGRA16 )
EXPECT_EQ( num_bytes, 2 * 3 * 2 );
EXPECT_EQ( bytes_per_line, 2 * 2 );
EXPECT_NE( data, image->data.data()) << "Copy is necessary!";
uint16_t reference[] = { 0x5500, 0x5500,
0x6400, 0x6400,
0x38AA, 0xA6AA };
uint16_t reference[] = { 0x4C3E, 0x95AF,
0x7680, 0x5180,
0x4BEE, 0x9BB3 };
auto *ref_ptr = reinterpret_cast<uint8_t *>(reference);
EXPECT_TRUE( compareImage( data, std::vector<uint8_t>( ref_ptr, ref_ptr + 12 )));
}
Expand Down

0 comments on commit c86fce4

Please sign in to comment.