Skip to content

Cropped images are sometimes 1 pixel too small #123

Open

Description

@wave-dash

smartcrop --width 100 --height 400 %1 %~n1_out%~x1

When I run this command on kitty.jpg from the test suite, the output image is 99x400.

2023-03-19_22-47-36_dopus_crop

I assume this happens because of the skewed aspect ratio of the requested crop, I've encountered a similar "missing pixel" problem when cropping in Photoshop. Is there a way to force exact dimensions for the output?

Activity

  1. jwagner commented on Mar 20, 2023

    @jwagner
    Owner

    Hey @wave-dash thanks for the detailed report. I don't think this is the correct repo though. Can you please report it against https://github.com/jwagner/smartcrop-cli ? Looks like a rounding error somewhere. I don't have time to go digging for it right now but I should get to it eventually. :)

  2. wave-dash commented on Mar 21, 2023

    @wave-dash
    Author

    Sure thing, sorry about that. This repo seemed more active, and I figured the code for the two would be mostly the same.

  3. kamiyo commented on Aug 6, 2023

    @kamiyo

    I actually have a similar problem using smartcrop-sharp. When passing it options like this:

    const { topCrop } = await smartcrop.crop(imageFile, {
                minScale: 1.0,
                width: 3,
                height: 2,
            });
    

    OR

    const { topCrop } = await smartcrop.crop(imageFile, {
                minScale: 1.0,
                width: 4000,
                height: 2666,
            });
    

    It always returns a height of 2656 instead. I think the issues are here:

    smartcrop.js/smartcrop.js

    Lines 120 to 121 in de2d143

    options.cropWidth = ~~(options.cropWidth * prescale);
    options.cropHeight = ~~(options.cropHeight * prescale);

    smartcrop.js/smartcrop.js

    Lines 147 to 148 in de2d143

    crop.x = ~~(crop.x / prescale);
    crop.y = ~~(crop.y / prescale);

    In the first pair of lines, I believe you are scaling down the dimensions for the downsampled image (for processing ease, I'm assuming). But since it's floored, once you scale back up in the second pair of lines, it won't be at the correct width, especially if the initial wasn't a multiple of 256.

    To prove the above example in pseudocode,

    prescale = 0.064
    downsampledCropHeight = floor(2666 * 0.064) = 170
    finalCropHeight = floor(170 / 0.064) = 2656
    

    I don't know what the solution should be. You could force based on aspect ratio. But as an end user, I guess I can just use the x and y of the crop, and force the dimensions myself.

    Just letting you know where I think the issue lies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions