Skip to content

Commit

Permalink
Use proper sRGB gamma curve
Browse files Browse the repository at this point in the history
  • Loading branch information
kornelski committed Dec 5, 2015
1 parent f8c24a4 commit 904c2f7
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 19 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ Scores for version 1.1 measured against [TID2008][1] database:

TID2008 Category | Spearman correlation
--- | ---
Noise | -0.866
Noise2 | -0.882
Safe | -0.884
Noise | -0.872
Noise2 | -0.888
Safe | -0.889
Hard | -0.903
Simple | -0.921
Exotic | -0.449
Exotic2 | -0.620
Full | -0.804
Simple | -0.922
Exotic | -0.484
Exotic2 | -0.651
Full | -0.818

[1]: http://www.computervisiononline.com/dataset/tid2008-tampere-image-database-2008
33 changes: 24 additions & 9 deletions src/dssim.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,25 @@ void dssim_dealloc_image(dssim_image *img)
free(img);
}

static void set_gamma(double gamma_lut[static 256], const double invgamma)
static int set_gamma(double gamma_lut[static 256], const double invgamma)
{
for (int i = 0; i < 256; i++) {
gamma_lut[i] = pow(i / 255.0, 1.0 / invgamma);
if (invgamma == dssim_srgb_gamma) {
for (int i = 0; i < 256; i++) {
const double s = i / 255.0;
if (s <= 0.04045) {
gamma_lut[i] = s / 12.92;
} else {
gamma_lut[i] = pow((s + 0.055) / 1.055, 2.4);
}
}
return 1;
} else if (invgamma > 0 && invgamma < 1.0) {
for (int i = 0; i < 256; i++) {
gamma_lut[i] = pow(i / 255.0, 1.0 / invgamma);
}
return 1;
} else {
return 0;
}
}

Expand Down Expand Up @@ -202,6 +217,7 @@ inline static dssim_lab rgb_to_lab(const double gamma_lut[static 256], const uns
};
}

#ifndef USE_COCOA
/*
* Flips x/y (like 90deg rotation)
*/
Expand Down Expand Up @@ -267,7 +283,7 @@ static void regular_1d_blur(const dssim_px_t *src, dssim_px_t *restrict tmp1, ds
}
}
}

#endif

/*
* blurs (approximate of gaussian)
Expand Down Expand Up @@ -478,14 +494,13 @@ dssim_image *dssim_create_image(dssim_attr *attr, unsigned char *const *const ro
dssim_row_callback *converter;
int num_channels;

if (gamma <= 0 || gamma > 1.0) {
return NULL;
}

image_data im = {
.row_pointers = (const unsigned char *const *const )row_pointers,
};
set_gamma(im.gamma_lut, gamma);

if (!set_gamma(im.gamma_lut, gamma)) {
return NULL;
}

switch(color_type) {
case DSSIM_GRAY:
Expand Down
3 changes: 3 additions & 0 deletions src/dssim.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ typedef struct {
dssim_attr *dssim_create_attr(void);
void dssim_dealloc_attr(dssim_attr *);

// Magic number to use in place of gamma for a true sRGB curve
static const double dssim_srgb_gamma = -47571492;

/*
Number of scales for multiscale (1 = regular SSIM). Optional weights array contains weight of each scale.
Set before creating any images.
Expand Down
15 changes: 12 additions & 3 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,17 @@ inline static unsigned char to_byte(float in) {
return in * 256.f;
}

double get_gamma(double gamma) {
double get_gamma(const png24_image *image) {
// Assume unlabelled are sRGB too
if (RWPNG_NONE == image->output_color || RWPNG_SRGB == image->output_color) {
return dssim_srgb_gamma;
}
const double gamma = image->gamma;
if (gamma > 0 && gamma <= 1.0) {
// If the gamma chunk states gamma closest to sRGB that PNG can express, then assume sRGB too
if (RWPNG_GAMA_ONLY == image->output_color && gamma > 0.4545499 && gamma < 0.4545501) {
return dssim_srgb_gamma;
}
return gamma;
}

Expand Down Expand Up @@ -137,7 +146,7 @@ int main(int argc, char *const argv[])

dssim_attr *attr = dssim_create_attr();

dssim_image *original = dssim_create_image(attr, image1.row_pointers, DSSIM_RGBA, image1.width, image1.height, get_gamma(image1.gamma));
dssim_image *original = dssim_create_image(attr, image1.row_pointers, DSSIM_RGBA, image1.width, image1.height, get_gamma(&image1));
free(image1.row_pointers);
free(image1.rgba_data);

Expand All @@ -156,7 +165,7 @@ int main(int argc, char *const argv[])
break;
}

dssim_image *modified = dssim_create_image(attr, image2.row_pointers, DSSIM_RGBA, image2.width, image2.height, get_gamma(image2.gamma));
dssim_image *modified = dssim_create_image(attr, image2.row_pointers, DSSIM_RGBA, image2.width, image2.height, get_gamma(&image2));
free(image2.row_pointers);
free(image2.rgba_data);

Expand Down

0 comments on commit 904c2f7

Please sign in to comment.