这是我显示图片的方式:
return Scaffold(
body: Center(
child: Image.asset('man_face.jpg'),
),
);
结果是:https://imgur.com/a/CPrQgvS
我只想显示图片的特殊部分。例如,具有x: 250
和y: 360
以及width: 200
和height: 150
的矩形。
应该是这样的:https://imgur.com/a/p41y3nx
我该怎么做?
答案 0 :(得分:2)
您可能想研究这个库。 brendan-duncan/image。一个很好的工具,可以处理抖动图像。
答案 1 :(得分:1)
这里的id是我想出来的代码
它接受一个图像 url 和一个 rect 并只显示图像的 rect 部分
import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
class PartImagePainter extends StatefulWidget {
String imageUrl;
Rect rect;
PartImagePainter(this.imageUrl, this.rect);
@override
_PartImagePainterState createState() => _PartImagePainterState();
}
class _PartImagePainterState extends State<PartImagePainter> {
Future<ui.Image> getImage(String path) async {
Completer<ImageInfo> completer = Completer();
var img = new NetworkImage(path);
img
.resolve(ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool _) {
completer.complete(info);
}));
ImageInfo imageInfo = await completer.future;
return imageInfo.image;
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: getImage(widget.imageUrl),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return paintImage(snapshot.data);
} else {
// Otherwise, display a loading indicator.
return Center(child: CircularProgressIndicator());
}
});
}
paintImage(image) {
return CustomPaint(
painter: ImagePainter(image, widget.rect),
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: widget.rect.height,
),
);
}
}
class ImagePainter extends CustomPainter {
ui.Image resImage;
Rect rectCrop;
ImagePainter(this.resImage, this.rectCrop);
@override
void paint(Canvas canvas, Size size) {
if (resImage == null) {
return;
}
final Rect rect = Offset.zero & size;
final Size imageSize =
Size(resImage.width.toDouble(), resImage.height.toDouble());
FittedSizes sizes = applyBoxFit(BoxFit.fitWidth, imageSize, size);
Rect inputSubRect = rectCrop;
final Rect outputSubRect =
Alignment.center.inscribe(sizes.destination, rect);
final paint = Paint()
..color = Colors.white
..style = PaintingStyle.fill
..strokeWidth = 4;
canvas.drawRect(rect, paint);
canvas.drawImageRect(resImage, inputSubRect, outputSubRect, Paint());
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
答案 2 :(得分:-1)
Flutter 官方文档建议的一种方法是:
<块引用>要显示图像的子部分,请考虑使用 CustomPainter 和 Canvas.drawImageRect。
参考:https://api.flutter.dev/flutter/painting/DecorationImage/alignment.html
这是我的完整代码。使用 PartImage
显示您想要的内容。
class PartImage extends StatefulWidget {
const PartImage({
Key key,
@required this.imageProvider,
@required this.transform,
}) : assert(imageProvider != null),
super(key: key);
final ImageProvider imageProvider;
final Matrix4 transform;
@override
_PartImageState createState() => _PartImageState();
}
class _PartImageState extends State<PartImage> {
ImageStream _imageStream;
ImageInfo _imageInfo;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_getImage();
}
@override
void didUpdateWidget(PartImage oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.imageProvider != oldWidget.imageProvider) _getImage();
}
void _getImage() {
final oldImageStream = _imageStream;
_imageStream = widget.imageProvider.resolve(createLocalImageConfiguration(context));
if (_imageStream.key != oldImageStream?.key) {
final listener = ImageStreamListener(_updateImage);
oldImageStream?.removeListener(listener);
_imageStream.addListener(listener);
}
}
void _updateImage(ImageInfo imageInfo, bool synchronousCall) {
setState(() {
_imageInfo = imageInfo;
});
}
@override
void dispose() {
_imageStream.removeListener(ImageStreamListener(_updateImage));
super.dispose();
}
@override
Widget build(BuildContext context) {
return RawPartImage(
image: _imageInfo?.image, // this is a dart:ui Image object
scale: _imageInfo?.scale ?? 1.0,
transform: widget.transform,
);
}
}
/// ref: [RawImage]
class RawPartImage extends StatelessWidget {
final ui.Image image;
final double scale;
final Matrix4 transform;
const RawPartImage({Key key, this.image, this.scale, this.transform}) : super(key: key);
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _RawPartImagePainter(
image: image,
scale: scale,
transform: transform,
),
);
}
}
class _RawPartImagePainter extends CustomPainter {
final ui.Image image;
final double scale;
final Matrix4 transform;
final painter = Paint();
_RawPartImagePainter({this.image, this.scale, this.transform});
@override
void paint(Canvas canvas, Size size) {
if (image == null) {
return;
}
final transformInv = Matrix4.inverted(transform);
final dst = Offset.zero & size;
final src = Rect.fromPoints(
transformOffset(transformInv, dst.topLeft),
transformOffset(transformInv, dst.bottomRight),
);
// print('src=$src dst=$dst');
canvas.drawImageRect(image, src, dst, painter);
}
@override
bool shouldRepaint(covariant _RawPartImagePainter oldDelegate) {
return oldDelegate.image != image || //
oldDelegate.scale != scale ||
oldDelegate.transform != transform;
}
}
Offset transformOffset(Matrix4 transform, Offset offset) {
Vector4 vecOut = transform * Vector4(offset.dx, offset.dy, 0, 1);
return Offset(vecOut.x, vecOut.y);
}
顺便说一下,如果您有兴趣了解 drawImageRect
后面发生的事情:
drawImageRect
(即 _drawImageRect
实际调用的 C++ 代码:https://github.com/flutter/engine/blob/6bc70e4a114ff4c01b60c77bae754bace5683f6d/lib/ui/painting/canvas.cc#L330canvas_->drawImageRect
。什么是canvas_
?从头文件中我们看到它的类型为 SkCanvas* canvas_;
。Skia
的世界(不再是 Flutter 或 Dart)。 https://skia.org/user/api/skcanvas_overview 了解 SkCanvas。和 https://api.skia.org/classSkCanvas.html#a680ab85c3c7b5eab23b853b97f914334 用于实际的 SkCanvas.drawImageRect
文档。