Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unimplemented items: +antialias and -black-point-compensation #83

Open
vampirical opened this issue Mar 10, 2015 · 10 comments
Open

Unimplemented items: +antialias and -black-point-compensation #83

vampirical opened this issue Mar 10, 2015 · 10 comments

Comments

@vampirical
Copy link

As far as I can determine it seems neither of these are currently supported. Might just be a gap in the documentation.

Anti-Alias

C API: MagickSetAntialias
CLI: +antialias to disable the default "on" behavior.

Black Point Compensation

Part of the new color handling improvements. Everything else can be taken advantage of through Imagick but there's still this one hole. It can be worked around by tweaking the ICC profiles used but it's a bit of smudge on the otherwise very consistent lcms based workflow.

C API: ImageInfo->black_point_compensation
CLI: -black-point-compensation

@Danack
Copy link
Collaborator

Danack commented Mar 10, 2015

Hi @vampirical,

Can you give an example of the 'black_point_compensation' in action? As the complete documentation for it is: "-black-point-compensation Use black point compensation."

cheers
Dan

@Danack
Copy link
Collaborator

Danack commented Mar 10, 2015

I've added the get/setAntiAlias function. Can you give an example where it would be useful to use it?

Also, I have no idea what black-point-compensation would be used for - but it should be usable already through an option e.g.

$imagick->setOption("black-point-compensation", 3);

But if you can give an example of where it would be used that would be great.

@vampirical
Copy link
Author

That's awesome thanks! Is there a list of the properties available for setOption somewhere, in the C API or something? I'd be happy to produce a list for the docs.

My use case for disabling anti-aliasing is for determining the colors in a vector document, anti-aliasing a 6 color vector document will produce an extra 160+ colors obscuring the originals. You could quantize back down in some cases but it isn't a universal solution. I could see it also being useful if you wanted to avoid extra noise and knew you were going to do a resize at some point anyways, as most of the resize algorithms will introduce their own aliasing.

Black point compensation occurs during a color space transformation. ICC profile based transforms are done based on the white point which can sometimes result in squashed blacks if the destination gamut is smaller than the source gamut. For example if you were going from RGB to CMYK without black point compensation you'd likely lose a lot of detail in dark or shadowy areas of an image. The rendering intent used comes in to play as well though, the default Perceptual intent forces BPC on so it shouldn't be an issue for most people, however most sensitive color workflows won't use Perceptual preferring a Relative Colorimetric intent instead. Here are Adobe's docs on it for more information: http://www.color.org/AdobeBPC.pdf

@Danack
Copy link
Collaborator

Danack commented Mar 10, 2015

Hi @vampirical,

Sorry - I meant can you give an example of the command line usage for both? This will allow me to check that Imagick produces the same images that calling ImageMagick with the equivalent commands do.

cheers
Dan

@vampirical
Copy link
Author

Ah, gotcha. Here you go. :)

Anti-Alias

Test File: https://dl.dropboxusercontent.com/u/19846726/test-images/whatsapp-logo-symbol.ai

# identify -format %k whatsapp-logo-symbol.ai
251
# identify +antialias -format %k whatsapp-logo-symbol.ai
93
# convert whatsapp-logo-symbol.ai -unique-colors whatsapp-logo-symbol-unique.png
# convert +antialias whatsapp-logo-symbol.ai -unique-colors whatsapp-logo-symbol-unique-no-aa.png

Black Point Compensation

Test File: https://dl.dropboxusercontent.com/u/19846726/test-images/lena512color.tiff
sRGB Profile: https://dl.dropboxusercontent.com/u/19846726/test-images/sRGB_IEC61966-2-1_black_scaled.icc
CMYK Profile: https://dl.dropboxusercontent.com/u/19846726/test-images/USWebCoatedSWOP.icc

# convert lena512color.tiff -profile sRGB_IEC61966-2-1_black_scaled.icc -intent Relative -profile USWebCoatedSWOP.icc lena512color-cmyk.tiff
# convert lena512color.tiff -profile sRGB_IEC61966-2-1_black_scaled.icc -intent Relative -black-point-compensation -profile USWebCoatedSWOP.icc lena512color-cmyk-bpc.tiff
# identify -format %k lena512color-cmyk.tiff
143105
# identify -format %k lena512color-cmyk-bpc.tiff
147271

Comparison Image: https://dl.dropboxusercontent.com/u/19846726/test-images/lena-bpc-comparison.jpg
Largest differences are visible around the feather in her hat, especially the bottom left.

@Danack
Copy link
Collaborator

Danack commented Mar 11, 2015

Well that was not fun. I think whatever library is doing the conversion of illustrator files is either broken, or not being called by ImageMagick correctly. Turning anti-aliasing on/off made no difference. So I can't check whether setting the aliasing gets the result you want.

However the code below does seem to be using the alias setting correctly as it produces the images:

aliastest_antialias
aliastest_withoutsmooth

<?php

$tests = [
    true => 'antialias',
    false => 'withoutsmooth'
];


foreach ($tests as $key => $description) {

    $draw = new \ImagickDraw();
    $draw->setFillColor("red");
    $draw->circle(20, 20, 50, 50);
    $draw->setFillColor("blue");
    $draw->circle(90, 50, 50, 50);
    $draw->setFillColor("green");
    $draw->rotate(10);
    $draw->rectangle(50, 60, 80, 80);

    $imagick = new \Imagick();
    $imagick->newImage(100, 100, 'white');
    $imagick->setAntiAlias($key);
    $imagick->setImageFormat("png");
    $imagick->drawImage($draw);

    $imagick->writeImage("aliasTest_$description.png");
}

If you wanted to test before the release you could compile the extension yourself on your system. However I'm reasonably certain the flag is working.

@Danack
Copy link
Collaborator

Danack commented Mar 11, 2015

Well that was not fun, part 2. It turns out that i) I don't know how to use color profiles and ii) I'm not sure that the delegate that ImageMagick is relying on for converting the file is doing the conversion correctly on my machine

I am 99% sure that calling $imagick->setOption("black-point-compensation", $something); should set the correct option. This is based on the fact that the code that in ImageMagick that interprets the command line option is:

if (LocaleCompare("black-point-compensation",option+1) == 0)
          {
            if (*option == '+')
              {
                (void) SetImageOption(image_info,option+1,"false");
                break;
              }
            (void) SetImageOption(image_info,option+1,"true");
            break;
          }

@vampirical Can you investigate this yourself and report back to say if it's working or not? I thought the code below should at least show some difference between the black point compensation being enabled or not (and it does report it as disabled when set to 0 judging by $imagick->getOption("black-point-compensation") but it doesn't seem to affect the output image.

<?php

//lets try all the things
$options = [
    'blackcompensation_true' => 'true',
    'blackcompensation_false' => 'false',
    'blackcompensation_notset' => null,
    'blackcompensation_one' => 1,
    'blackcompensation_zero' => 0,
];

foreach ($options as $key => $value) {
    $imagick = new Imagick(realpath("./lena512color.tiff"));

    if ($value !== null) {
        //Not sure if meant to be before or after
        $imagick->setOption("black-point-compensation", $value);
    }

    $black_scaled_icc = file_get_contents('./sRGB_IEC61966-2-1_black_scaled.icc');
    $imagick->profileImage('srgb', $black_scaled_icc);

    $imagick->setImageRenderingIntent(\Imagick::RENDERINGINTENT_RELATIVE);

    if ($value !== null) { 
        //Not sure if meant to be before or after
        $imagick->setOption("black-point-compensation", $value);
    }

    $web_coated = file_get_contents('./USWebCoatedSWOP.icc');
    $imagick->profileImage('webCoated', $web_coated);
    $imagick->writeImage("./blackPointImagick_$key.tiff");
}

@vampirical
Copy link
Author

The anti-aliasing support looks like it should work fine.

You're setup for testing BPC looks good to me, the BPC option shouldn't affect anything for the first profile image call as it just sets meta data but it should also be harmless. It's lcms2 that does all the heavy lifting and the BPC flag should only come in to play during the second profile image call when it actually starts transforming pixels.

I cannot manage to get any variation of setOption 'black-point-compensation' to affect the image processing going from TIFF -> TIFF. It looks like it may actually be defaulting to on but I'm not positive without being able to get it to switch.

Taking a look at the profiling code, it looks like any value other than MagickFalse should trigger the flag being added to the flags sent to lcms2. The cmsFLAGS_BLACKPOINTCOMPENSATION constant is from lcms2.h and should always be defined if lcms2 is available.

#if defined(cmsFLAGS_BLACKPOINTCOMPENSATION)
            if (image->black_point_compensation != MagickFalse)
              flags|=cmsFLAGS_BLACKPOINTCOMPENSATION;
#endif
            transform=AcquireTransformThreadSet(image,source_profile,
              source_type,target_profile,target_type,intent,flags);

I'll probably have some time next week to dig in a bit and debug it.

@dlemstra
Copy link

I found this issue when I was looking for an implementation of a test for black point compensation to Magick.NET (.NET Implementation of ImageMagick). I managed to create a test for this myself and you can find it here: dlemstra/Magick.NET@afc10df. I got it working by combining the rendering intent (-intent) and the black point composition. Please let me know if you need an explanation of my code ;)

@Danack
Copy link
Collaborator

Danack commented Jun 27, 2016

Thanks for the point @dlemstra - when I'm not so overwhelmed with real life commitments, that should really help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants