Merge pull request #3432 from Beep6581/fix_image_datas_convert_to

Use full range in `ImageDatas::convertTo<>` (#3429)
This commit is contained in:
Floessie
2016-09-27 07:42:54 +02:00
committed by GitHub
6 changed files with 77 additions and 88 deletions

View File

@@ -58,10 +58,10 @@ enum TypeInterpolation { TI_Nearest, TI_Bilinear };
class ImageDatas : virtual public ImageDimensions
{
public:
template <class S, class D >
void convertTo (S srcValue, D &dstValue)
template<class S, class D>
void convertTo(S src, D& dst) const
{
dstValue = static_cast<D>(srcValue);
dst = src;
}
// parameters that will never be used, replaced by the subclasses r, g and b parameters!
@@ -100,30 +100,30 @@ public:
};
template <>
inline void ImageDatas::convertTo<unsigned short, unsigned char> (const unsigned short srcValue, unsigned char &dstValue)
template<>
inline void ImageDatas::convertTo(unsigned short src, unsigned char& dst) const
{
dstValue = (unsigned char)(srcValue >> 8);
dst = uint16ToUint8Rounded(src);
}
template <>
inline void ImageDatas::convertTo<unsigned char, int> (const unsigned char srcValue, int &dstValue)
template<>
inline void ImageDatas::convertTo(unsigned char src, int& dst) const
{
dstValue = (int)(srcValue) << 8;
dst = src * 257;
}
template <>
inline void ImageDatas::convertTo<unsigned char, unsigned short> (const unsigned char srcValue, unsigned short &dstValue)
template<>
inline void ImageDatas::convertTo(unsigned char src, unsigned short& dst) const
{
dstValue = (unsigned short)(srcValue) << 8;
dst = src * 257;
}
template <>
inline void ImageDatas::convertTo<float, unsigned char> (const float srcValue, unsigned char &dstValue)
template<>
inline void ImageDatas::convertTo(float src, unsigned char& dst) const
{
dstValue = (unsigned char)( (unsigned short)(srcValue) >> 8 );
dst = uint16ToUint8Rounded(src);
}
template <>
inline void ImageDatas::convertTo<unsigned char, float> (const unsigned char srcValue, float &dstValue)
template<>
inline void ImageDatas::convertTo(unsigned char src, float& dst) const
{
dstValue = float( (unsigned short)(srcValue) << 8 );
dst = src * 257;
}
// --------------------------------------------------------------------

View File

@@ -28,9 +28,9 @@ namespace
void getScanline8 (const uint16_t *red, const uint16_t *green, const uint16_t *blue, int width, unsigned char* buffer)
{
for (int i = 0, ix = 0; i < width; i++) {
buffer[ix++] = red[i] >> 8;
buffer[ix++] = green[i] >> 8;
buffer[ix++] = blue[i] >> 8;
buffer[ix++] = rtengine::uint16ToUint8Rounded(red[i]);
buffer[ix++] = rtengine::uint16ToUint8Rounded(green[i]);
buffer[ix++] = rtengine::uint16ToUint8Rounded(blue[i]);
}
}
@@ -92,10 +92,10 @@ void Image16::setScanline (int row, unsigned char* buffer, int bps, float *minVa
case (IIOSF_UNSIGNED_CHAR): {
int ix = 0;
for (int i = 0; i < width; i++) {
r(row, i) = (unsigned short)(buffer[ix++]) << 8;
g(row, i) = (unsigned short)(buffer[ix++]) << 8;
b(row, i) = (unsigned short)(buffer[ix++]) << 8;
for (int i = 0; i < width; ++i) {
r(row, i) = static_cast<unsigned short>(buffer[ix++]) * 257;
g(row, i) = static_cast<unsigned short>(buffer[ix++]) * 257;
b(row, i) = static_cast<unsigned short>(buffer[ix++]) * 257;
}
break;
@@ -105,7 +105,7 @@ void Image16::setScanline (int row, unsigned char* buffer, int bps, float *minVa
unsigned short* sbuffer = (unsigned short*) buffer;
int ix = 0;
for (int i = 0; i < width; i++) {
for (int i = 0; i < width; ++i) {
r(row, i) = sbuffer[ix++];
g(row, i) = sbuffer[ix++];
b(row, i) = sbuffer[ix++];
@@ -298,11 +298,11 @@ Image16::to8()
{
Image8* img8 = new Image8(width, height);
for ( int h = 0; h < height; ++h ) {
for ( int w = 0; w < width; ++w ) {
img8->r(h, w) = (unsigned char)( r(h, w) >> 8);
img8->g(h, w) = (unsigned char)( g(h, w) >> 8);
img8->b(h, w) = (unsigned char)( b(h, w) >> 8);
for (int h = 0; h < height; ++h) {
for (int w = 0; w < width; ++w) {
img8->r(h, w) = uint16ToUint8Rounded(r(h, w));
img8->g(h, w) = uint16ToUint8Rounded(g(h, w));
img8->b(h, w) = uint16ToUint8Rounded(b(h, w));
}
}
@@ -314,11 +314,11 @@ Image16::tofloat()
{
Imagefloat* imgfloat = new Imagefloat(width, height);
for ( int h = 0; h < height; ++h ) {
for ( int w = 0; w < width; ++w ) {
imgfloat->r(h, w) = (float)r(h, w);
imgfloat->g(h, w) = (float)g(h, w);
imgfloat->b(h, w) = (float)b(h, w);
for (int h = 0; h < height; ++h) {
for (int w = 0; w < width; ++w) {
imgfloat->r(h, w) = r(h, w);
imgfloat->g(h, w) = g(h, w);
imgfloat->b(h, w) = b(h, w);
}
}

View File

@@ -49,8 +49,8 @@ void Image8::getScanline (int row, unsigned char* buffer, int bps)
} else if (bps == 16) {
unsigned short* sbuffer = (unsigned short*) buffer;
for (int i = 0, ix = row * width * 3; i < width * 3; i++, ix++) {
sbuffer[i] = (unsigned short)(data[ix]) << 8;
for (int i = 0, ix = row * width * 3; i < width * 3; ++i, ++ix) {
sbuffer[i] = static_cast<unsigned short>(data[ix]) * 257;
}
}
}
@@ -73,8 +73,8 @@ void Image8::setScanline (int row, unsigned char* buffer, int bps, float *minVal
case (IIOSF_UNSIGNED_SHORT): {
unsigned short* sbuffer = (unsigned short*) buffer;
for (int i = 0, ix = row * width * 3; i < width * 3; i++, ix++) {
data[ix] = sbuffer[i] >> 8;
for (int i = 0, ix = row * width * 3; i < width * 3; ++i, ++ix) {
data[ix] = uint16ToUint8Rounded(sbuffer[i]);
}
break;

View File

@@ -333,11 +333,11 @@ Imagefloat::to8()
#pragma omp parallel for schedule(static)
#endif
for ( int h = 0; h < height; ++h ) {
for ( int w = 0; w < width; ++w ) {
img8->r(h, w) = (unsigned char)( (unsigned short)(r(h, w)) >> 8);
img8->g(h, w) = (unsigned char)( (unsigned short)(g(h, w)) >> 8);
img8->b(h, w) = (unsigned char)( (unsigned short)(b(h, w)) >> 8);
for (int h = 0; h < height; ++h) {
for (int w = 0; w < width; ++w) {
img8->r(h, w) = uint16ToUint8Rounded(r(h, w));
img8->g(h, w) = uint16ToUint8Rounded(g(h, w));
img8->b(h, w) = uint16ToUint8Rounded(b(h, w));
}
}
@@ -352,11 +352,11 @@ Imagefloat::to16()
#pragma omp parallel for schedule(static)
#endif
for ( int h = 0; h < height; ++h ) {
for ( int w = 0; w < width; ++w ) {
img16->r( h, w) = (unsigned short)(r(h, w));
img16->g( h, w) = (unsigned short)(g(h, w));
img16->b( h, w) = (unsigned short)(b(h, w));
for (int h = 0; h < height; ++h) {
for (int w = 0; w < width; ++w) {
img16->r(h, w) = r(h, w);
img16->g(h, w) = g(h, w);
img16->b(h, w) = b(h, w);
}
}

View File

@@ -88,36 +88,28 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
for (int i = 0; i < H; i++) {
for (int i = 0; i < H; ++i) {
float* rL = lab->L[i];
float* ra = lab->a[i];
float* rb = lab->b[i];
int ix = i * 3 * W;
float R, G, B;
float fy, fx, fz, x_, y_, z_, LL;
float x_, y_, z_;
for (int j = 0; j < W; j++) {
for (int j = 0; j < W; ++j) {
//float L1=rL[j],a1=ra[j],b1=rb[j];//for testing
fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116
fx = (0.002 * ra[j]) / 327.68 + fy;
fz = fy - (0.005 * rb[j]) / 327.68;
LL = rL[j] / 327.68;
x_ = 65535.0 * Color::f2xyz(fx) * Color::D50x;
// y_ = 65535.0 * Color::f2xyz(fy);
z_ = 65535.0 * Color::f2xyz(fz) * Color::D50z;
y_ = (LL > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / Color::kappa;
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_ );
Color::xyz2srgb(x_, y_, z_, R, G, B);
/* copy RGB */
//int R1=((int)gamma2curve[(R)])
data[ix++] = ((int)Color::gamma2curve[R]) >> 8;
data[ix++] = ((int)Color::gamma2curve[G]) >> 8;
data[ix++] = ((int)Color::gamma2curve[B]) >> 8;
data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[R]);
data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[G]);
data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[B]);
}
}
}
@@ -205,30 +197,23 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
#pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif
for (int i = cy; i < cy + ch; i++) {
float R, G, B;
for (int i = cy; i < cy + ch; ++i) {
float* rL = lab->L[i];
float* ra = lab->a[i];
float* rb = lab->b[i];
int ix = 3 * i * cw;
for (int j = cx; j < cx + cw; j++) {
float R, G, B;
float x_, y_, z_;
float fy = (0.00862069 * rL[j]) / 327.68 + 0.137932; // (L+16)/116
float fx = (0.002 * ra[j]) / 327.68 + fy;
float fz = fy - (0.005 * rb[j]) / 327.68;
float LL = rL[j] / 327.68;
float x_ = 65535.0 * Color::f2xyz(fx) * Color::D50x;
//float y_ = 65535.0 * Color::f2xyz(fy);
float z_ = 65535.0 * Color::f2xyz(fz) * Color::D50z;
float y_ = (LL > Color::epskap) ? 65535.0 * fy * fy * fy : 65535.0 * LL / Color::kappa;
for (int j = cx; j < cx + cw; ++j) {
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_);
Color::xyz2rgb(x_, y_, z_, R, G, B, xyz_rgb);
image->data[ix++] = (int)Color::gamma2curve[R] >> 8;
image->data[ix++] = (int)Color::gamma2curve[G] >> 8;
image->data[ix++] = (int)Color::gamma2curve[B] >> 8;
image->data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[R]);
image->data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[G]);
image->data[ix++] = uint16ToUint8Rounded(Color::gamma2curve[B]);
}
}
}

View File

@@ -1,14 +1,15 @@
#ifndef _MYMATH_
#define _MYMATH_
#include <cmath>
#include <algorithm>
#pragma once
#include <algorithm>
#include <cmath>
#include <cstdint>
namespace rtengine
{
static const int MAXVAL = 0xffff;
static const float MAXVALF = float(MAXVAL); // float version of MAXVAL
static const double MAXVALD = double(MAXVAL); // double version of MAXVAL
constexpr int MAXVAL = 0xffff;
constexpr float MAXVALF = static_cast<float>(MAXVAL); // float version of MAXVAL
constexpr double MAXVALD = static_cast<double>(MAXVAL); // double version of MAXVAL
template <typename _Tp>
inline _Tp SQR (_Tp x)
@@ -107,6 +108,9 @@ inline int float2uint16range(float d) // clips input to [0;65535] and rounds
return d + 0.5f;
}
constexpr std::uint8_t uint16ToUint8Rounded(std::uint16_t i)
{
return ((i + 128) - ((i + 128) >> 8)) >> 8;
}
#endif
}