Commit 7aeb539d authored by namanix's avatar namanix Committed by Dan Field

Added a filterQuality parameter to images. (#23329)

* Added a filterQuality parameter to images.

* Removed this break by accident.

* Modified the test case to check the filterQuality

* Update packages/flutter/lib/src/rendering/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Update packages/flutter/lib/src/rendering/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Update packages/flutter/lib/src/rendering/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Update packages/flutter/lib/src/widgets/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Update packages/flutter/lib/src/widgets/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Update packages/flutter/lib/src/rendering/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Update packages/flutter/lib/src/rendering/image.dart
Co-Authored-By: 's avatarnamanix <namanix@gmail.com>

* Added documentation for the new parameter and corrected some space issue's
parent 323d1574
......@@ -261,6 +261,7 @@ class DecorationImagePainter {
centerSlice: _details.centerSlice,
repeat: _details.repeat,
flipHorizontally: flipHorizontally,
filterQuality: FilterQuality.low
);
if (clipPath != null)
......@@ -347,7 +348,12 @@ class DecorationImagePainter {
/// invert will be applied after it. This is primarily used for implementing
/// smart invert on iOS.
///
/// The `canvas`, `rect`, `image`, `scale`, `alignment`, `repeat`, and `flipHorizontally`
/// * `filterQuality`: Use this to change the quality when scaling an image.
/// Use the [FilterQuality.low] quality setting to scale the image, which corresponds to
/// bilinear interpolation, rather than the default [FilterQuality.none] which corresponds
/// to nearest-neighbor.
///
/// The `canvas`, `rect`, `image`, `scale`, `alignment`, `repeat`, `flipHorizontally` and `filterQuality`
/// arguments must not be null.
///
/// See also:
......@@ -367,6 +373,7 @@ void paintImage({
ImageRepeat repeat = ImageRepeat.noRepeat,
bool flipHorizontally = false,
bool invertColors = false,
FilterQuality filterQuality = FilterQuality.low
}) {
assert(canvas != null);
assert(image != null);
......@@ -407,10 +414,7 @@ void paintImage({
if (colorFilter != null)
paint.colorFilter = colorFilter;
if (sourceSize != destinationSize) {
// Use the "low" quality setting to scale the image, which corresponds to
// bilinear interpolation, rather than the default "none" which corresponds
// to nearest-neighbor.
paint.filterQuality = FilterQuality.low;
paint.filterQuality = filterQuality;
}
paint.invertColors = invertColors;
final double halfWidthDelta = (outputSize.width - destinationSize.width) / 2.0;
......
......@@ -21,7 +21,7 @@ export 'package:flutter/painting.dart' show
class RenderImage extends RenderBox {
/// Creates a render box that displays an image.
///
/// The [scale], [alignment], [repeat], and [matchTextDirection] arguments
/// The [scale], [alignment], [repeat], [matchTextDirection] and [filterQuality] arguments
/// must not be null. The [textDirection] argument must not be null if
/// [alignment] will need resolving or if [matchTextDirection] is true.
RenderImage({
......@@ -37,10 +37,12 @@ class RenderImage extends RenderBox {
Rect centerSlice,
bool matchTextDirection = false,
TextDirection textDirection,
bool invertColors = false
bool invertColors = false,
FilterQuality filterQuality = FilterQuality.low
}) : assert(scale != null),
assert(repeat != null),
assert(alignment != null),
assert(filterQuality != null),
assert(matchTextDirection != null),
_image = image,
_width = width,
......@@ -54,7 +56,8 @@ class RenderImage extends RenderBox {
_centerSlice = centerSlice,
_matchTextDirection = matchTextDirection,
_invertColors = invertColors,
_textDirection = textDirection {
_textDirection = textDirection,
_filterQuality = filterQuality {
_updateColorFilter();
}
......@@ -145,6 +148,21 @@ class RenderImage extends RenderBox {
markNeedsPaint();
}
/// Used to set the filterQuality of the image
/// Use the [FilterQuality.low] quality setting to scale the image, which corresponds to
/// bilinear interpolation, rather than the default [FilterQuality.none] which corresponds
/// to nearest-neighbor.
FilterQuality get filterQuality => _filterQuality;
FilterQuality _filterQuality;
set filterQuality(FilterQuality value) {
assert(value != null);
if(value == _filterQuality)
return;
_filterQuality = value;
markNeedsPaint();
}
/// Used to combine [color] with this image.
///
/// The default is [BlendMode.srcIn]. In terms of the blend mode, [color] is
......@@ -348,6 +366,7 @@ class RenderImage extends RenderBox {
repeat: _repeat,
flipHorizontally: _flipHorizontally,
invertColors: invertColors,
filterQuality: _filterQuality
);
}
......@@ -367,5 +386,6 @@ class RenderImage extends RenderBox {
properties.add(FlagProperty('matchTextDirection', value: matchTextDirection, ifTrue: 'match text direction'));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('invertColors', invertColors));
properties.add(EnumProperty<FilterQuality>('filterQuality', filterQuality));
}
}
......@@ -4498,7 +4498,7 @@ class RichText extends LeafRenderObjectWidget {
class RawImage extends LeafRenderObjectWidget {
/// Creates a widget that displays an image.
///
/// The [scale], [alignment], [repeat], and [matchTextDirection] arguments must
/// The [scale], [alignment], [repeat], [matchTextDirection] and [filterQuality] arguments must
/// not be null.
const RawImage({
Key key,
......@@ -4514,6 +4514,7 @@ class RawImage extends LeafRenderObjectWidget {
this.centerSlice,
this.matchTextDirection = false,
this.invertColors = false,
this.filterQuality = FilterQuality.low,
}) : assert(scale != null),
assert(alignment != null),
assert(repeat != null),
......@@ -4543,6 +4544,12 @@ class RawImage extends LeafRenderObjectWidget {
/// If non-null, this color is blended with each image pixel using [colorBlendMode].
final Color color;
/// Used to set the filterQuality of the image
/// Use the "low" quality setting to scale the image, which corresponds to
/// bilinear interpolation, rather than the default "none" which corresponds
/// to nearest-neighbor.
final FilterQuality filterQuality;
/// Used to combine [color] with this image.
///
/// The default is [BlendMode.srcIn]. In terms of the blend mode, [color] is
......@@ -4643,6 +4650,7 @@ class RawImage extends LeafRenderObjectWidget {
matchTextDirection: matchTextDirection,
textDirection: matchTextDirection || alignment is! Alignment ? Directionality.of(context) : null,
invertColors: invertColors,
filterQuality: filterQuality,
);
}
......@@ -4661,7 +4669,8 @@ class RawImage extends LeafRenderObjectWidget {
..centerSlice = centerSlice
..matchTextDirection = matchTextDirection
..textDirection = matchTextDirection || alignment is! Alignment ? Directionality.of(context) : null
..invertColors = invertColors;
..invertColors = invertColors
..filterQuality = filterQuality;
}
@override
......@@ -4679,6 +4688,7 @@ class RawImage extends LeafRenderObjectWidget {
properties.add(DiagnosticsProperty<Rect>('centerSlice', centerSlice, defaultValue: null));
properties.add(FlagProperty('matchTextDirection', value: matchTextDirection, ifTrue: 'match text direction'));
properties.add(DiagnosticsProperty<bool>('invertColors', invertColors));
properties.add(EnumProperty<FilterQuality>('filterQuality', filterQuality));
}
}
......
......@@ -21,6 +21,7 @@ export 'package:flutter/painting.dart' show
AssetImage,
ExactAssetImage,
FileImage,
FilterQuality,
ImageConfiguration,
ImageInfo,
ImageStream,
......@@ -143,6 +144,11 @@ class Image extends StatefulWidget {
/// Otherwise, the image dimensions will change as the image is loaded, which
/// will result in ugly layout changes.
///
/// Use [filterQuality] to change the quality when scaling an image.
/// Use the [FilterQuality.low] quality setting to scale the image,
/// which corresponds to bilinear interpolation, rather than the default
/// [FilterQuality.none] which corresponds to nearest-neighbor.
///
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
const Image({
Key key,
......@@ -159,9 +165,11 @@ class Image extends StatefulWidget {
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
}) : assert(image != null),
assert(alignment != null),
assert(repeat != null),
assert(filterQuality != null),
assert(matchTextDirection != null),
super(key: key);
......@@ -179,6 +187,11 @@ class Image extends StatefulWidget {
/// An optional [headers] argument can be used to send custom HTTP headers
/// with the image request.
///
/// Use [filterQuality] to change the quality when scaling an image.
/// Use the [FilterQuality.low] quality setting to scale the image,
/// which corresponds to bilinear interpolation, rather than the default
/// [FilterQuality.none] which corresponds to nearest-neighbor.
///
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
Image.network(String src, {
Key key,
......@@ -195,6 +208,7 @@ class Image extends StatefulWidget {
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
Map<String, String> headers,
}) : image = NetworkImage(src, scale: scale, headers: headers),
assert(alignment != null),
......@@ -214,6 +228,11 @@ class Image extends StatefulWidget {
/// On Android, this may require the
/// `android.permission.READ_EXTERNAL_STORAGE` permission.
///
/// Use [filterQuality] to change the quality when scaling an image.
/// Use the [FilterQuality.low] quality setting to scale the image,
/// which corresponds to bilinear interpolation, rather than the default
/// [FilterQuality.none] which corresponds to nearest-neighbor.
///
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
Image.file(File file, {
Key key,
......@@ -230,9 +249,11 @@ class Image extends StatefulWidget {
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
}) : image = FileImage(file, scale: scale),
assert(alignment != null),
assert(repeat != null),
assert(filterQuality != null),
assert(matchTextDirection != null),
super(key: key);
......@@ -272,6 +293,11 @@ class Image extends StatefulWidget {
/// Otherwise, the image dimensions will change as the image is loaded, which
/// will result in ugly layout changes.
///
/// Use [filterQuality] to change the quality when scaling an image.
/// Use the [FilterQuality.low] quality setting to scale the image,
/// which corresponds to bilinear interpolation, rather than the default
/// [FilterQuality.none] which corresponds to nearest-neighbor.
///
/// ## Sample code
///
/// Suppose that the project's `pubspec.yaml` file contains the following:
......@@ -370,6 +396,7 @@ class Image extends StatefulWidget {
this.matchTextDirection = false,
this.gaplessPlayback = false,
String package,
this.filterQuality = FilterQuality.low,
}) : image = scale != null
? ExactAssetImage(name, bundle: bundle, scale: scale, package: package)
: AssetImage(name, bundle: bundle, package: package),
......@@ -387,6 +414,11 @@ class Image extends StatefulWidget {
/// Otherwise, the image dimensions will change as the image is loaded, which
/// will result in ugly layout changes.
///
/// Use [filterQuality] to change the quality when scaling an image.
/// Use the [FilterQuality.low] quality setting to scale the image,
/// which corresponds to bilinear interpolation, rather than the default
/// [FilterQuality.none] which corresponds to nearest-neighbor.
///
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
Image.memory(Uint8List bytes, {
Key key,
......@@ -403,6 +435,7 @@ class Image extends StatefulWidget {
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
}) : image = MemoryImage(bytes, scale: scale),
assert(alignment != null),
assert(repeat != null),
......@@ -439,6 +472,12 @@ class Image extends StatefulWidget {
/// If non-null, this color is blended with each image pixel using [colorBlendMode].
final Color color;
/// Used to set the filterQuality of the image
/// Use the "low" quality setting to scale the image, which corresponds to
/// bilinear interpolation, rather than the default "none" which corresponds
/// to nearest-neighbor.
final FilterQuality filterQuality;
/// Used to combine [color] with this image.
///
/// The default is [BlendMode.srcIn]. In terms of the blend mode, [color] is
......@@ -545,6 +584,7 @@ class Image extends StatefulWidget {
properties.add(FlagProperty('matchTextDirection', value: matchTextDirection, ifTrue: 'match text direction'));
properties.add(StringProperty('semanticLabel', semanticLabel, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('this.excludeFromSemantics', excludeFromSemantics));
properties.add(EnumProperty<FilterQuality>('filterQuality', filterQuality));
}
}
......@@ -651,6 +691,7 @@ class _ImageState extends State<Image> {
centerSlice: widget.centerSlice,
matchTextDirection: widget.matchTextDirection,
invertColors: _invertColors,
filterQuality: widget.filterQuality,
);
if (widget.excludeFromSemantics)
return image;
......
......@@ -93,6 +93,7 @@ void main() {
' image: [10×10]\n'
' alignment: center\n'
' invertColors: false\n'
' filterQuality: low\n'
),
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment