Best resize and or crop logic

2019-02-13 16:54发布

问题:

I've come across this a few times and thought it would be good to put it out there. What's your best image resize and/or crop logic. The idea being that some method is called with a target image, dimensions and a crop flag - this would return or save off or whatever the desired image.

Mine is below. Converted from VB to C# so yes there'll be small bugs but logic is what we're looking at.

// INIT
// On/off
bool WeAreCropping = true;

// Get some dimensions
int TargetWidth = RequestedWidth;
int TargetHeight = RequestedHeight;
int SourceWidth = SourceImage.Width;
int SourceHeight = SourceImage.Height;
int ResizeWidth = TargetWidth;
int ResizeHeight = TargetHeight;

// GET RESIZE VALUES
// Are we cropping?
if (WeAreCropping) {

    // Get source and target aspect ratio
    double SourceAspectRatio = SourceWidth / SourceHeight;
    double TargetAspectRatio = TargetWidth / TargetHeight;

    // Compare aspect ratios to find out if we should we resize by 
    // width or height or nothing
    if (TargetAspectRatio < SourceAspectRatio) {
        ResizeWidth = TargetHeight / SourceHeight * SourceWidth;
    }
    else if (TargetAspectRatio > SourceAspectRatio) {
        ResizeHeight = TargetWidth / SourceWidth * SourceHeight;
    }
    else {
      // Same aspect ratio
    }


}
else {

    // If the target image is bigger than the source
    if (TargetWidth > SourceWidth && TargetHeight > SourceHeight) {
        TargetWidth = SourceWidth;
        TargetHeight = SourceHeight;
    }

    double Ratio = 0;

    // What ratio should we resize it by
    if (SourceWidth / TargetWidth > SourceHeight / TargetHeight) {
        Ratio = SourceWidth / TargetWidth;
    }
    else {
        Ratio = SourceHeight / TargetHeight;
    }

    ResizeWidth = Math.Ceiling(SourceWidth / Ratio);

    ResizeHeight = Math.Ceiling(SourceHeight / Ratio);
}

// TIME TO DO SUMFINK
// Resize the image using ResizeWidth and ResizeHeight
// Do it

if (WeAreCropping) {
    // Crop the resized image at the center TargetWidth and TargetHeight
    // Do it
}

I suspect this could be much more elegant so maybe you could do better.

回答1:

I'd say you should utilize standard geometry types like Rectangle and Size. Then you should probably also support a use case, when the caller wants to fit the image in some larger rectangle, but still wants to keep the original image sizes ratio.

One way to implement the resizing you can find here.



回答2:

This is probably a bit more involved than what you need, but for an example of some advanced cropping techniques, check this out.