|
|
// The official Netpbm standard mandates the use of the ITU-R-BT.709
// transfer function, although it acknowledges the use of linear
// encoding or the sRGB transfer function as alternative de-facto
// standards.
gamma = options.GetTranscodingGammaCurve(BT709GammaCurve::Get());
// Greyscale or color output
// TODO - the check for image container type is here to mimic
// old code; do we still need it?
if (image->IsGrayscale() || options.grayscale)
{
grayscale = true;
if (plainFormat)
file->printf("P2\n");
else
file->printf("P5\n");
}
else
{
if (plainFormat)
file->printf("P3\n");
else
file->printf("P6\n");
}
where the gamma setting is moved out of the else condition and above the
if/else conditional selecting greyscale or color output. With this
change the pgm/ppm output matches the documented v3.8 behavior and that
for png greyscale and color outputs.
I've mentioned elsewhere POV-Ray makes a pretty good viewer for >8 bit
channel output files. While using POV-Ray as viewer it generates an
output file if not suppressed. On a whim - aka asking for trouble - I
decided to compare the original rendered output file with the viewer
output file. These two POV-Ray generated images should match. They don't.
First, looking at the POV-Ray png default color output and immediate
input as an image_map in a viewer.
The short story is png output is hard coded to srgb unless overridden by
a File_Gamma setting somewhere. However, this hard coded output doesn't
trigger the generation of the correct srgb, encoding-information block
in the png file, but rather a power law 2.2 gamma block.
What this means in practice is shown in the attached image top row where
the differences are multiplied by 50. The differences are mostly small,
but certainly there.
In addition, looking at the output files generated by the following
commands and using iinfo to see the _gamma block encoding I see:
---
p380 render.pov +w400 +h400 +d -p +fn8 +ofn8
oiio:ColorSpace: "GammaCorrected2.2"
oiio:Gamma: 2.2
---
p380 render.pov +w400 +h400 +d -p +fn8 +ofn8_srgb File_Gamma=srgb
oiio:ColorSpace: "sRGB"
---
p380 render.pov +w400 +h400 +d -p +fn8 +ofn8_1 File_Gamma=1.0
oiio:ColorSpace: "linear"
oiio:Gamma: 1
---
p380 render.pov +w400 +h400 +d -p +fn8 +ofn8_bt709 File_Gamma=bt709
oiio:ColorSpace: "GammaCorrected1.9"
oiio:Gamma: 1.9
Not worked out how to update the color png gamma code as yet. Or looked
into similar pgm/ppm differences. Suppose a good near term rule would be
to always specify the output and input gamma you want. When I do this,
the render result and the viewer result images match - as they should.
Aside: The bottom row of the attached image shows the greyscale
differences which include the default png gamma out immediate issue
above - plus apparently more with greyscale...
Bill P.
---
For those wanting to play at home:
//-------- render.pov
#version 3.8; // Simple scene to test file gamma behavior.
global_settings { assumed_gamma 1 }
#declare Grey50 = srgb <0.5,0.5,0.5>;
background { color Grey50 }
#declare Camera00 = camera {
perspective
location <3,3,-3.001>
sky y
angle 35
right x*(image_width/image_height)
look_at <0,0,0>
}
#declare White = srgb <1,1,1>;
#declare Light00 = light_source { <50,150,-250>, White }
#declare Red = srgb <1,0,0>;
#declare CylinderX = cylinder { -1*x, 1*x, 0.01 pigment { Red } }
#declare Green = srgb <0,1,0>;
#declare CylinderY = cylinder { -1*y, 1*y, 0.01 pigment { Green } }
#declare Blue = srgb <0,0,1>;
#declare CylinderZ = cylinder { -1*z, 1*z, 0.01 pigment { Blue } }
#include "functions.inc"
#declare Fn00 = function (x,y,z) { f_sphere(x,y/3,z,0.1) }
#declare Xfrm00 = transform {
rotate z*30.0
translate <0.5,0.0,0.0>
}
#declare FnXfrm00 = function { transform {Xfrm00 inverse} }
#declare Fn00x = function (x,y,z) {
Fn00(FnXfrm00(x,y,z).x,FnXfrm00(x,y,z).y,FnXfrm00(x,y,z).z)
}
#declare Xfrm01 = transform {
rotate z*60.0
scale <1,3,1>
}
#declare FnXfrm01 = function { transform {Xfrm01 inverse} }
#declare Fn00xx = function (x,y,z) {
Fn00x(FnXfrm01(x,y,z).x,FnXfrm01(x,y,z).y,FnXfrm01(x,y,z).z)
}
#declare Iso99 = isosurface {
function { Fn00xx(x,y,z) }
contained_by { box { -2.0,2.0 } }
threshold 0
accuracy 0.0005
max_gradient 1.1
pigment { color Green }
}
//--- scene ---
camera { Camera00 }
light_source { Light00 }
object { CylinderX }
object { CylinderY }
object { CylinderZ }
object { Iso99 }
//-------- viewer.pov
// p380 viewer.pov +w400 +h400 +d +p +fn8
// Replace three fn8.png below with render.png or whatever.
#version 3.8;
global_settings { assumed_gamma 1 }
#declare Grey50 = srgb <0.5,0.5,0.5>;
background { color Grey50 }
#declare VarOrthoMult =
1.0/max(image_width/image_height,image_height/image_width);
#declare Camera01z = camera {
orthographic
location <0,0,-2>
direction z
right VarOrthoMult*x*max(1,image_width/image_height)
up VarOrthoMult*y*max(1,image_height/image_width)
}
#macro ImageMap00(_HF)
#if (_HF=0)
image_map { "fn8.png"
#else
"fn8.png"
#end
#if (_HF=0)
map_type 0
once
//interpolate 2 // No interpolation
}
#end
#end
#declare ImageMap00_P = pigment { image_map { "fn8.png" gamma 1 } }
#declare ImageMap00_Range = max_extent(ImageMap00_P);
#declare ImageMap00_NrmScale =
<min(1,ImageMap00_Range.x/ImageMap00_Range.y),
min(1,ImageMap00_Range.y/ImageMap00_Range.x),1>;
#declare Pigment00 = pigment {
ImageMap00(0)
translate <-0.5,-0.5,0>
scale ImageMap00_NrmScale
}
#declare Fin00 = finish {
ambient 0.0
diffuse 0
emission srgbft <1,1,1,0,0>
}
#declare Txtr00 = texture { pigment { Pigment00 } finish { Fin00 } }
#declare Plane00 = plane { z, 0 }
#declare Obj00 = object { Plane00 texture { Txtr00 } }
//--- scene ---
camera { Camera01z }
object { Obj00 }
Post a reply to this message
Attachments:
Download 'png_gamma_story.png' (33 KB)
Preview of image 'png_gamma_story.png'
|
|