#!/usr/bin/perl -w use strict; sub linear_to_srgb { my ($c) = @_; if ($c < 0.0031308) { return $c * 12.92; } else { return 1.055 * $c ** (1.0/2.4) - 0.055; } } sub srgb_to_linear { my ($c) = @_; if ($c < 0.04045) { return $c / 12.92; } else { return (($c + 0.055) / 1.055) ** 2.4 } } my @linear_to_srgb; for my $linear (0 .. 4095) { my $srgb = int(linear_to_srgb($linear / 4095.0) * 255.0 + 0.5); push @linear_to_srgb, $srgb; } my @srgb_to_linear; for my $srgb (0 .. 255) { my $linear = int(srgb_to_linear($srgb / 255.0) * 65535.0 + 0.5); push @srgb_to_linear, $linear; } # Ensure that we have a lossless sRGB and back conversion loop. # some of the darkest shades need a little bias -- maximum is just # 5 increments out of 16. This gives us useful property with # least amount of error in the sRGB-to-linear table, and keeps the actual # table lookup in the other direction as simple as possible. for my $srgb (0 .. $#srgb_to_linear) { my $add = 0; while (1) { my $linear = $srgb_to_linear[$srgb]; my $srgb_lossy = $linear_to_srgb[$linear >> 4]; last if $srgb == $srgb_lossy; # Add slight bias to this component until it rounds correctly $srgb_to_linear[$srgb] ++; $add ++; } die "Too many adds at $srgb" if $add > 5; } print <<"PROLOG"; /* WARNING: This file is generated by $0. * Please edit that file instead of this one. */ #include #ifdef HAVE_CONFIG_H #include #endif #include "pixman-private.h" PROLOG print "const uint8_t linear_to_srgb[" . @linear_to_srgb . "] =\n"; print "{\n"; for my $linear (0 .. $#linear_to_srgb) { if (($linear % 10) == 0) { print "\t"; } print sprintf("%d, ", $linear_to_srgb[$linear]); if (($linear % 10) == 9) { print "\n"; } } print "\n};\n"; print "\n"; print "const uint16_t srgb_to_linear[" . @srgb_to_linear . "] =\n"; print "{\n"; for my $srgb (0 .. $#srgb_to_linear) { if (($srgb % 10) == 0) { print "\t"; } print sprintf("%d, ", $srgb_to_linear[$srgb]); if (($srgb % 10) == 9) { print "\n"; } } print "\n};\n";