Apply an ImageFit value.
The arguments to this method, in addition to the ImageFit value to apply,
are two sizes, ostensibly the sizes of an input image and an output canvas.
Specifically, the inputSize
argument gives the size of the complete image
that is being fitted, and the outputSize
gives the size of the rectangle
into which the image is to be drawn.
This function then returns two sizes, combined into a single FittedSizes object.
The FittedSizes.source size is the subpart of the inputSize
that is to
be shown. If the entire input image is shown, then this will equal the
inputSize
, but if the input image is to be cropped down, this may be
smaller.
The FittedSizes.destination size is the subpart of the outputSize
in
which to paint the (possibly cropped) input image. If the
FittedSizes.destination size is smaller than the outputSize
then the
input image is being letterboxed (or pillarboxed).
This method does not express an opinion regarding the alignment of the source and destination sizes within the input and output rectangles. Typically they are centered (this is what BoxDecoration does, for instance, and is how ImageFit is defined). The FractionalOffset class provides a convenience function, inscribe, for resolving the sizes to rects, as shown in the example below.
== Example ==
This example paints an Image image
onto the Rect outputRect
on a
Canvas canvas
, using a Paint paint, applying the ImageFit algorithm
fit
:
final Size imageSize = new Size(image.width.toDouble(), image.height.toDouble());
final FittedSizes sizes = applyImageFit(fit, imageSize, outputRect.size);
final Rect inputSubrect = FractionalOffset.center.inscribe(sizes.source, Point.origin & imageSize);
final Rect outputSubrect = FractionalOffset.center.inscribe(sizes.destination, outputRect);
canvas.drawImageRect(image, inputSubrect, outputSubrect, paint);
Source
FittedSizes applyImageFit(ImageFit fit, Size inputSize, Size outputSize) { Size sourceSize, destinationSize; switch (fit) { case ImageFit.fill: sourceSize = inputSize; destinationSize = outputSize; break; case ImageFit.contain: sourceSize = inputSize; if (outputSize.width / outputSize.height > sourceSize.width / sourceSize.height) destinationSize = new Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height); else destinationSize = new Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width); break; case ImageFit.cover: if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) { sourceSize = new Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width); } else { sourceSize = new Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height); } destinationSize = outputSize; break; case ImageFit.fitWidth: sourceSize = new Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width); destinationSize = new Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width); break; case ImageFit.fitHeight: sourceSize = new Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height); destinationSize = new Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height); break; case ImageFit.none: sourceSize = new Size(math.min(inputSize.width, outputSize.width), math.min(inputSize.height, outputSize.height)); destinationSize = sourceSize; break; case ImageFit.scaleDown: sourceSize = inputSize; destinationSize = inputSize; final double aspectRatio = inputSize.width / inputSize.height; if (destinationSize.height > outputSize.height) destinationSize = new Size(outputSize.height * aspectRatio, outputSize.height); if (destinationSize.width > outputSize.width) destinationSize = new Size(outputSize.width, outputSize.width / aspectRatio); break; } return new FittedSizes(sourceSize, destinationSize); }