AcademySoftwareFoundation / OpenImageIO

Reading, writing, and processing images in a wide variety of file formats, using a format-agnostic API, aimed at VFX applications.
https://openimageio.readthedocs.org
Apache License 2.0
1.99k stars 603 forks source link

chromatic aberration correction with raw:aber doesn't work as expected #4145

Closed kfjahnke closed 9 months ago

kfjahnke commented 10 months ago

My Samyang fisheye produces quite strong chromatic aberration. When I convert the images with dcraw, I invoke the chromatic aberration correction using the parameter -C 0.9996 0.9996. Now I tried the same with oiio, passing raw:aber like this:

  ImageSpec config;
  auto f2 = TypeDesc(OpenImageIO_v2_4::TypeDesc::FLOAT,2) ;
  float aber[2] = { .9996f , .9996f } ;
  config.attribute ( "raw:aber" , f2 , aber ) ;
  auto inp = ImageInput::open ( filename , &config ) ;
  ...

The resulting image has chromatic aberration and does not look like the output of dcraw with -C 0.9996 0.9996. I played around with the parameters for a while, and I found that I could reproduce dcraw's output passing the reciprocal values instead, so float aber[2] = { 1.0f/.9996f, 1.0f/.9996f } ;

OpenImageIO version and dependencies

Please run oiiotool --buildinfo and paste the output here.

That's quite a mouthful. Okay, here it comes:

oiiotool --buildinfo
Invalid option "--buildinfo"
oiiotool -- simple image processing operations
OpenImageIO 2.4.7.1 http://www.openimageio.org

Usage: oiiotool [filename|command]...

Important usage tips:
  * The oiiotool command line is processed in order, LEFT to RIGHT.
  * The command line consists of image NAMES ('image.tif') and COMMANDS
    ('--over'). Commands start with dashes (one or two dashes are
    equivalent). Some commands have required arguments which must follow on
    the command line. For example, the '-o' command is followed by a
    filename.
  * oiiotool is STACK-based: naming an image pushes it on the stack, and
    most commands pop the top image (or sometimes more than one image),
    perform a calculation, and push the result image back on the stack. For
    example, the '--over' command pops the top two images off the stack,
    composites them, then pushes the result back onto the stack.
  * Some commands allow one or more optional MODIFIERS in the form
    'name=value', which are appended directly to the command itself (no
    spaces), separated by colons ':'. For example,
       oiiotool in.tif --text:x=100:y=200:color=1,0,0 "Hello" -o out.tif
  * Using numerical wildcards will run the whole command line on each of
    several sequentially-named files, for example:
       oiiotool fg.#.tif bg.#.tif -over -o comp.#.tif
    See the manual for info about subranges, number of digits, etc.
  * Command line arguments containing substrings enclosed in braces {}
    are replaced by evaluating their contents as expressions. Simple math is
    allowed as well as retrieving metadata such as {TOP.'foo:bar'},
    {IMG[0].filename}, or {FRAME_NUMBER/24.0}.

Options (general flags):
    --help                        Print help message
    --version                     Print version
    -v                            Verbose status messages
    -q                            Quiet mode (turn verbose off and reduce
                                    printed output)
    -n                            No saved output (dry run)
    --no-error-exit               Do not exit upon error, try to process
                                    additional comands (danger!)
    -a                            Do operations on all subimages/miplevels
    --debug                       Debug mode
    --runstats                    Print runtime statistics
    --info                        Print resolution and basic info on all
                                    inputs, detailed metadata if -v is also
                                    used (options: format=xml:verbose=1)
    --list-formats                List all supported file formats and their
                                    filename extensions
    --metamatch REGEX             Which metadata is printed with -info -v
    --no-metamatch REGEX          Which metadata is excluded with -info -v
    --stats                       Print pixel statistics of all inputs files
    --dumpdata                    Print all pixel data values of input
                                    files (options: empty=1, C=arrayname)
    --hash                        Print SHA-1 hash of each input image
    -u                            Update mode: skip outputs when the file
                                    exists and is newer than all inputs
    --no-clobber                  Do not overwrite existing files
    --threads N                   Number of threads (default 0 == #cores)
    --no-autopremult              Turn off automatic premultiplication of
                                    images with unassociated alpha
    --autopremult                 Turn on automatic premultiplication of
                                    images with unassociated alpha
    --autoorient                  Automatically --reorient all images upon
                                    input
    --autocc                      Automatically color convert based on
                                    filename (options: unpremult=)
    --noautocc                    Turn off automatic color conversion
    --native                      Keep native pixel data type (bypass cache
                                    if necessary)
    --cache MB                    ImageCache size (in MB: default=4096)
    --autotile TILESIZE           Autotile enable for cached images (the
                                    argument is the tile size, default 0
                                    means no autotile)
    --metamerge                   Always merge metadata of all inputs into
                                    output
    --oiioattrib NAME VALUE       Sets global OpenImageIO attribute
                                    (options: type=...)
Control flow and scripting:
    --set NAME VALUE              Set a user variable (options: type=...)
    --if VALUE                    If VALUE is not 0 or empty, execute
                                    commands until --endif
    --else                        Else clause of the current 'if' block
    --endif                       End the current 'if' block
    --while VALUE                 If VALUE is not 0 or empty, execute
                                    commands until --endwhile and loop
    --endwhile                    End the current 'while' block
    --for VARIABLE RANGE          Iterate over a range the commands between
                                    here and --endfor.  The range may be END
                                    (implied begin 0 and step 1), START,END
                                    (implied step 1) or START,END,STEP
    --endfor                      End the current 'for' block
    --frames FRAMERANGE           Frame range for '#' or printf-style
                                    wildcards
    --framepadding NDIGITS        Frame number padding digits (ignored when
                                    using printf-style wildcards)
    --views VIEWNAMES             Views for %V/%v wildcards
                                    (comma-separated, defaults to
                                    "left,right")
    --skip-bad-frames             Skip to next frame in range if there's an
                                    error, rather than exiting
    --wildcardoff                 Disable numeric wildcard expansion for
                                    subsequent command line arguments
    --wildcardon                  Enable numeric wildcard expansion for
                                    subsequent command line arguments
    --evaloff                     Disable {expression} evaluation for
                                    subsequent command line arguments
    --evalon                      Enable {expression} evaluation for
                                    subsequent command line arguments
Commands that read images:
    -i FILENAME                   Input file (options: autocc=, ch=, info=,
                                    infoformat=, now=, type=, unpremult=)
    --iconfig NAME VALUE          Sets input config attribute (options:
                                    type=...)
    --missingfile OPTION          Set policy for missing input files:
                                    'error' (default), 'black', 'checker'
Commands that write images:
    -o FILENAME                   Output the current image to the named
                                    file (options: all=, autocc=, autocrop=,
                                    autotrim=, bits=, contig=, datatype=,
                                    dither=, fileformatname=, scanline=,
                                    separate=, tile=, unpremult=)
    -otex FILENAME                Output the current image as a texture
    -oenv FILENAME                Output the current image as a latlong env
                                    map
    -obump FILENAME               Output the current bump texture map as a
                                    6 channels texture including the first
                                    and second moment of the bump slopes
                                    (options: bumpformat=height|normal|auto,
                                    uvslopes_scale=val>=0)
Options that affect subsequent image output:
    -d TYPE                       '-d TYPE' sets the output data format of
                                    all channels, '-d CHAN=TYPE' overrides a
                                    single named channel (multiple -d args
                                    are allowed). Data types include: uint8,
                                    sint8, uint10, uint12, uint16, sint16,
                                    uint32, sint32, half, float, double
    --scanline                    Output scanline images
    --tile WIDTH HEIGHT           Output tiled images with this tile size
    --compression NAME            Set the compression method (in the form
                                    "name" or "name:quality")
    --dither                      Add dither when writing <= 8-bit output
                                    from > 8 bit input
    --planarconfig CONFIG         Force planarconfig (contig, separate,
                                    default)
    --adjust-time                 Adjust file times to match DateTime
                                    metadata
    --noautocrop                  Do not automatically crop images whose
                                    formats don't support separate pixel data
                                    and full/display windows
    --autotrim                    Automatically trim black borders upon
                                    output to file formats that support
                                    separate pixel data and full/display
                                    windows
Options that print data (usually about the current image):
    --echo TEXT                   Echo message to console (options:
                                    newline=0)
    --printinfo                   Print info and metadata of the current
                                    top image
    --printstats                  Print pixel statistics of the current top
                                    image (options: roi=<geom>)
    --colorcount COLORLIST        Count of how many pixels have the given
                                    color (argument: color;color;...)
                                    (options: eps=color)
    --rangecheck MIN MAX          Count of how many pixels are outside the
                                    min/max color range (each is a
                                    comma-separated color value list)
Options that change current image metadata (but not pixel values):
    --attrib NAME VALUE           Sets metadata attribute (options:
                                    type=...)
    --sattrib NAME VALUE          Sets string metadata attribute
    --eraseattrib REGEX           Erase attributes matching regex
    --caption TEXT                Sets caption (ImageDescription metadata)
    --keyword KEYWORD             Add a keyword
    --clear-keywords              Clear all keywords
    --nosoftwareattrib            Do not write command line into
                                    Exif:ImageHistory, Software metadata
                                    attributes
    --sansattrib                  Write command line into Software &
                                    ImageHistory but remove --sattrib and
                                    --attrib options
    --orientation ORIENT          Set the assumed orientation
    --orientcw                    Rotate orientation metadata 90 deg
                                    clockwise
    --orientccw                   Rotate orientation metadata 90 deg
                                    counter-clockwise
    --orient180                   Rotate orientation metadata 180 deg
    --origin +X+Y                 Set the pixel data window origin (e.g.
                                    +20+10, -16-16)
    --originoffset +X+Y           Offset the pixel data window origin from
                                    its current position (e.g. +20+10, -16-16)
    --fullsize GEOM               Set the display window (e.g., 1920x1080,
                                    1024x768+100+0, -20-30)
    --fullpixels                  Set the 'full' image range to be the
                                    pixel data window
    --chnames NAMELIST            Set the channel names (comma-separated)
Options that affect subsequent actions:
    --fail THRESH                 Failure threshold difference (0.000001)
    --failpercent PCNT            Allow this percentage of failures in diff
                                    (0)
    --hardfail THRESH             Fail diff if any one pixel exceeds this
                                    error (infinity)
    --warn THRESH                 Warning threshold difference (0.00001)
    --warnpercent PCNT            Allow this percentage of warnings in diff
                                    (0)
    --hardwarn THRESH             Warn if any one pixel difference exceeds
                                    this error (infinity)
Actions:
    --create GEOM NCHANS          Create a blank image
    --pattern NAME GEOM NCHANS    Create a patterned image. Pattern name
                                    choices: black, constant, fill, checker,
                                    noise
    --kernel NAME GEOM            Create a centered convolution kernel
    --capture                     Capture an image (options: camera=%d)
    --diff                        Print report on the difference of two
                                    images (modified by --fail,
                                    --failpercent, --hardfail, --warn,
                                    --warnpercent --hardwarn)
    --pdiff                       Print report on the perceptual difference
                                    of two images (modified by --fail,
                                    --failpercent, --hardfail, --warn,
                                    --warnpercent --hardwarn)
    --add                         Add two images
    --addc VAL                    Add to all channels a scalar or
                                    per-channel constants (e.g.: 0.5 or
                                    1,1.25,0.5)
    --sub                         Subtract two images
    --subc VAL                    Subtract from all channels a scalar or
                                    per-channel constants (e.g.: 0.5 or
                                    1,1.25,0.5)
    --mul                         Multiply two images
    --mulc VAL                    Multiply the image values by a scalar or
                                    per-channel constants (e.g.: 0.5 or
                                    1,1.25,0.5)
    --div                         Divide first image by second image
    --divc VAL                    Divide the image values by a scalar or
                                    per-channel constants (e.g.: 0.5 or
                                    1,1.25,0.5)
    --mad                         Multiply two images, add a third
    --invert                      Take the color inverse (subtract from 1)
                                    (options: chbegin=0, chend=3
    --abs                         Take the absolute value of the image
                                    pixels
    --absdiff                     Absolute difference between two images
    --absdiffc VAL                Absolute difference versus a scalar or
                                    per-channel constant (e.g.: 0.5 or
                                    1,1.25,0.5)
    --powc VAL                    Raise the image values to a scalar or
                                    per-channel power (e.g.: 2.2 or
                                    2.2,2.2,2.2,1.0)
    --noise                       Add noise to an image (options:
                                    type=gaussian:mean=0:stddev=0.1,
                                    type=uniform:min=0:max=0.1,
                                    type=salt:value=0:portion=0.1, seed=0
    --chsum                       Turn into 1-channel image by summing
                                    channels (options: weight=r,g,...)
    --colormap MAPNAME            Color map based on channel 0 (arg:
                                    "inferno", "viridis", "magma", "turbo",
                                    "plasma", "blue-red", "spectrum", "heat",
                                    or comma-separated list of RGB triples)
    --crop GEOM                   Set pixel data resolution and offset,
                                    cropping or padding if necessary (WxH+X+Y
                                    or xmin,ymin,xmax,ymax)
    --croptofull                  Crop or pad to make pixel data region
                                    match the "full" region
    --trim                        Crop to the minimal ROI containing
                                    nonzero pixel values
    --cut GEOM                    Cut out the ROI and reposition to the
                                    origin (WxH+X+Y or xmin,ymin,xmax,ymax)
    --paste +X+Y                  Paste fg over bg at the given position
                                    (e.g., +100+50; '-' or 'auto' indicates
                                    using the data window position as-is;
                                    options: all=%d, mergeroi=%d)
    --pastemeta                   Copy the metadata from the first image to
                                    the second image and write the combined
                                    result.
    --mosaic WxH                  Assemble images into a mosaic (arg: WxH;
                                    options: pad=0, fit=WxH)
    --over                        'Over' composite of two images
    --zover                       Depth composite two images with Z
                                    channels (options: zeroisinf=%d)
    --deepmerge                   Merge/composite two deep images
    --deepholdout                 Hold out one deep image by another
    --rotate90                    Rotate the image 90 degrees clockwise
    --rotate180                   Rotate the image 180 degrees
    --rotate270                   Rotate the image 270 degrees clockwise
                                    (or 90 degrees CCW)
    --flip                        Flip the image vertically (top<->bottom)
    --flop                        Flop the image horizontally (left<->right)
    --reorient                    Rotate and/or flop the image to transform
                                    the pixels to match the Orientation
                                    metadata
    --transpose                   Transpose the image
    --cshift +X+Y                 Circular shift the image (e.g.: +20-10)
    --resample GEOM               Resample (640x480, 50%) (options:
                                    interp=0)
    --resize GEOM                 Resize (640x480, 50%) (options:
                                    filter=%s, highlightcomp=%d)
    --fit GEOM                    Resize to fit within a window size
                                    (options: filter=%s, pad=%d, fillmode=%s,
                                    exact=%d, highlightcomp=%d)
    --pixelaspect ASPECT          Scale up the image's width or height to
                                    match the given pixel aspect ratio
                                    (options: filter=%s, highlightcomp=%d)
    --rotate DEGREES              Rotate pixels (degrees clockwise) around
                                    the center of the display window
                                    (options: filter=%s, center=%f,%f,
                                    recompute_roi=%d, highlightcomp=%d
    --warp MATRIX                 Warp pixels (argument is a 3x3 matrix,
                                    separated by commas) (options: filter=%s,
                                    recompute_roi=%d, highlightcomp=%d)
    --st_warp                     Warp the first image using normalized
                                    "st" coordinates from the second image
                                    (options: filter=%s, chan_s=0, chan_t=1,
                                    flip_s=0, flip_t=0)
    --convolve                    Convolve with a kernel
    --blur WxH                    Blur the image (options: kernel=name)
    --median WxH                  Median filter the image
    --dilate WxH                  Dilate (area maximum) the image
    --erode WxH                   Erode (area minimum) the image
    --unsharp                     Unsharp mask (options: kernel=gaussian,
                                    width=3, contrast=1, threshold=0)
    --laplacian                   Laplacian filter the image
    --fft                         Take the FFT of the image
    --ifft                        Take the inverse FFT of the image
    --polar                       Convert complex (real,imag) to polar
                                    (amplitude,phase)
    --unpolar                     Convert polar (amplitude,phase) to
                                    complex (real,imag)
    --fixnan STRATEGY             Fix NaN/Inf values in the image (choices:
                                    none, black, box3, error)
    --fillholes                   Fill in holes (where alpha is not 1)
    --max                         Pixel-by-pixel max of two images
    --maxc VAL                    Max all values with a scalar or
                                    per-channel constants (e.g.: 0.5 or
                                    1,1.25,0.5)
    --maxchan                     Maximum of all channels of the image
    --min                         Pixel-by-pixel min of two images
    --minc VAL                    Min all values with a scalar or
                                    per-channel constants (e.g.: 0.5 or
                                    1,1.25,0.5)
    --minchan                     Minimum of all channels of the image
    --clamp                       Clamp values (options: min=..., max=...,
                                    clampalpha=0)
    --contrast                    Remap values (options: black=0...,
                                    white=1..., sthresh=0.5...,
                                    scontrast=1.0..., gamma=1, clamp=0|1)
    --saturate SCALE              Scale saturation of the color channels
    --rangecompress               Compress the range of pixel values with a
                                    log scale (options: luma=0|1)
    --rangeexpand                 Un-rangecompress pixel values back to a
                                    linear scale (options: luma=0|1)
    --line X1,Y1,X2,Y2,...        Render a poly-line (options: color=)
    --point X1,Y1,X2,Y2,...       Render points (options: color=)
    --box X1,Y1,X2,Y2             Render a box (options: color=)
    --fill GEOM                   Fill a region (options: color=)
    --text TEXT                   Render text into the current image
                                    (options: x=, y=, size=, color=)
Manipulating channels or subimages:
    --ch CHANLIST                 Select or shuffle channels (e.g.,
                                    "R,G,B", "B,G,R", "2,3,4")
    --chappend                    Append the channels of the last two images
    --unmip                       Discard all but the top level of a MIPmap
    --selectmip MIPLEVEL          Select just one MIP level (0 = highest
                                    res)
    --subimage SUBIMAGEINDEX      Select just one subimage by index or name
                                    (options: delete=1)
    --sisplit                     Split the top image's subimges into
                                    separate images
    --siappend                    Append the last two images into one
                                    multi-subimage image
    --siappendall                 Append all images on the stack into a
                                    single multi-subimage image
    --deepen                      Deepen normal 2D image to deep
    --flatten                     Flatten deep image to non-deep
Image stack manipulation:
    --dup                         Duplicate the current image (push a copy
                                    onto the stack)
    --swap                        Swap the top two images on the stack.
    --pop                         Throw away the current image
    --label %s                    Label the top image
Color management:
    --colorconfig FILENAME        Explicitly specify an OCIO configuration
                                    file
    --iscolorspace COLORSPACE     Set the assumed color space (without
                                    altering pixels)
    --tocolorspace COLORSPACE     Convert the current image's pixels to a
                                    named color space
    --colorconvert SRC DST        Convert pixels from 'src' to 'dst' color
                                    space (options: key=, value=, unpremult=,
                                    strict=)
    --ccmatrix MATRIXVALS         Color convert pixels with a 3x3 or 4x4
                                    matrix (options: unpremult=,transpose=)
    --ociolook LOOK               Apply the named OCIO look (options:
                                    from=, to=, inverse=, key=, value=,
                                    unpremult=)
    --ociodisplay DISPLAY VIEW    Apply the named OCIO display and view
                                    (options: from=, looks=, key=, value=,
                                    unpremult=)
    --ociofiletransform FILENAME  Apply the named OCIO filetransform
                                    (options: inverse=, unpremult=)
    --unpremult                   Divide all color channels of the current
                                    image by the alpha to "un-premultiply"
    --premult                     Multiply all color channels of the
                                    current image by the alpha
    --repremult                   Multiply all color channels of the
                                    current image by the alpha, but don't
                                    crush alpha=0 pixels to black.
    --iccwrite FILENAME           Output the current image's ICC profile as
                                    a separate file
    --iccread FILENAME            Add the contents of the file to the top
                                    image as its ICC profile

Input formats supported: bmp, cineon, dds, dicom, dpx, ffmpeg, fits, gif,
    hdr, heif, ico, iff, jpeg, jpeg2000, null, openexr, openvdb, png, pnm,
    psd, raw, rla, sgi, softimage, targa, tiff, webp, zfile
Output formats supported: bmp, dpx, fits, gif, hdr, heif, ico, iff, jpeg,
    jpeg2000, null, openexr, png, pnm, rla, sgi, targa, term, tiff, webp,
    zfile
OpenColorIO 2.1.2, color config: built-in
Known color spaces: "linear", "default", "rgb", "RGB", "sRGB", "Rec709"
Filters available: box, triangle, gaussian, sharp-gaussian, catmull-rom,
    blackman-harris, sinc, lanczos3, radial-lanczos3, nuke-lanczos6,
    mitchell, bspline, disk, cubic, keys, simon, rifman
Dependent libraries: OpenEXR 3.1.5, LIBTIFF Version 4.5.0, jpeg-turbo
    2.1.2/jp62, dcmtk 3.6.7, FFMpeg 5.1 (Lavf59.27.100), gif_lib 5.2.1,
    libheif 1.14.2, OpenJpeg 2.5.0, null 1.0, OpenVDB 10.0.1abi10, libpng
    1.6.39, libraw 0.20.2-Release, Webp 1.2.4
OIIO 2.4.7.1 built for C++17/201703 sse2
Running on 4 cores 15.3GB
    sse2,sse3,ssse3,sse41,sse42,avx,avx2,fma,f16c,popcnt,rdrand
Full OIIO documentation can be found at
    https://openimageio.readthedocs.io

Full command line was:
> oiiotool --buildinfo

Also please tell us if there was anything unusual about your environment or nonstandard build options you used.

No. ordinary package from debian12 stable.

I can provide a test image, if you like.

lgritz commented 10 months ago

I think it is correct. We take that "raw:aber" attribute and directly pass those values in the imgdata.params.aber[] parameter block to libraw.

On the other hand, dcraw itself takes its command line arguments and inverts them before passing to libraw, as you can see here: https://github.com/ncruces/dcraw/blob/master/dcraw.c#L10166

I think it makes more sense for us to directly map our attribute to libraw's controls. Nowhere in OIIO documentation or raw support do we imply that we're trying to emulate the naming or other conventions of dcraw's command line options exactly. It would be nice if that corresponds, too, but unfortunately dcraw doesn't present the same interface as libraw in terms of this parameter.

kfjahnke commented 9 months ago

Ah, that explains it! The code you point to does precisely what produces the behaviour I noticed: it converts the chromatic aberration arguments to their reciprocal values. Maybe you could put a little hint into the documentation to point out that the parameters don't necessarily map to dcraw parameters - just to save other users the wild goose chase.

Thanks for the clarification - I take the liberty to close this issue.