Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filterQuality property to improve image quality after scale #228

Merged
merged 1 commit into from
Dec 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions example/lib/screens/examples/full_screen_examples.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ class FullScreenExamples extends StatelessWidget {
);
},
),
ExampleButtonNode(
title: "Large Image (filter quality: medium)",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const FullScreenWrapper(
imageProvider:
const AssetImage("assets/large-image.jpg"),
filterQuality: FilterQuality.medium,
),
),
);
},
),
ExampleButtonNode(
title: "Small Image (custom background)",
onPressed: () {
Expand Down Expand Up @@ -200,6 +215,7 @@ class FullScreenWrapper extends StatelessWidget {
this.maxScale,
this.initialScale,
this.basePosition = Alignment.center,
this.filterQuality = FilterQuality.none,
});

final ImageProvider imageProvider;
Expand All @@ -209,6 +225,7 @@ class FullScreenWrapper extends StatelessWidget {
final dynamic maxScale;
final dynamic initialScale;
final Alignment basePosition;
final FilterQuality filterQuality;

@override
Widget build(BuildContext context) {
Expand All @@ -224,6 +241,7 @@ class FullScreenWrapper extends StatelessWidget {
maxScale: maxScale,
initialScale: initialScale,
basePosition: basePosition,
filterQuality: filterQuality,
),
);
}
Expand Down
7 changes: 7 additions & 0 deletions lib/photo_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ class PhotoView extends StatefulWidget {
this.customSize,
this.gestureDetectorBehavior,
this.tightMode,
this.filterQuality,
}) : child = null,
childSize = null,
super(key: key);
Expand Down Expand Up @@ -274,6 +275,7 @@ class PhotoView extends StatefulWidget {
this.customSize,
this.gestureDetectorBehavior,
this.tightMode,
this.filterQuality,
}) : loadingChild = null,
imageProvider = null,
gaplessPlayback = false,
Expand Down Expand Up @@ -357,6 +359,9 @@ class PhotoView extends StatefulWidget {
/// Useful when inside a [Dialog]
final bool tightMode;

/// Quality levels for image filters.
final FilterQuality filterQuality;

@override
State<StatefulWidget> createState() {
return _PhotoViewState();
Expand Down Expand Up @@ -516,6 +521,7 @@ class _PhotoViewState extends State<PhotoView> {
onTapDown: widget.onTapDown,
gestureDetectorBehavior: widget.gestureDetectorBehavior,
tightMode: widget.tightMode ?? false,
filterQuality: widget.filterQuality ?? FilterQuality.none,
);
}

Expand Down Expand Up @@ -570,6 +576,7 @@ class _PhotoViewState extends State<PhotoView> {
onTapDown: widget.onTapDown,
gestureDetectorBehavior: widget.gestureDetectorBehavior,
tightMode: widget.tightMode ?? false,
filterQuality: widget.filterQuality ?? FilterQuality.none,
);
}

Expand Down
7 changes: 7 additions & 0 deletions lib/photo_view_gallery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
onTapDown: pageOption.onTapDown,
gestureDetectorBehavior: pageOption.gestureDetectorBehavior,
tightMode: pageOption.tightMode,
filterQuality: pageOption.filterQuality,
)
: PhotoView(
key: ObjectKey(index),
Expand All @@ -258,6 +259,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
onTapDown: pageOption.onTapDown,
gestureDetectorBehavior: pageOption.gestureDetectorBehavior,
tightMode: pageOption.tightMode,
filterQuality: pageOption.filterQuality,
);

return ClipRect(
Expand Down Expand Up @@ -294,6 +296,7 @@ class PhotoViewGalleryPageOptions {
this.onTapDown,
this.gestureDetectorBehavior,
this.tightMode,
this.filterQuality,
}) : child = null,
childSize = null,
assert(imageProvider != null);
Expand All @@ -313,6 +316,7 @@ class PhotoViewGalleryPageOptions {
this.onTapDown,
this.gestureDetectorBehavior,
this.tightMode,
this.filterQuality,
}) : imageProvider = null,
assert(child != null),
assert(childSize != null);
Expand Down Expand Up @@ -361,4 +365,7 @@ class PhotoViewGalleryPageOptions {

/// Mirror to [PhotoView.tightMode]
final bool tightMode;

/// Quality levels for image filters.
final FilterQuality filterQuality;
}
27 changes: 21 additions & 6 deletions lib/src/core/photo_view_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class PhotoViewCore extends StatefulWidget {
@required this.scaleStateController,
@required this.basePosition,
@required this.tightMode,
@required this.filterQuality,
}) : customChild = null,
super(key: key);

Expand All @@ -54,6 +55,7 @@ class PhotoViewCore extends StatefulWidget {
@required this.scaleStateController,
@required this.basePosition,
@required this.tightMode,
@required this.filterQuality,
}) : imageProvider = null,
gaplessPlayback = false,
super(key: key);
Expand All @@ -77,6 +79,8 @@ class PhotoViewCore extends StatefulWidget {
final HitTestBehavior gestureDetectorBehavior;
final bool tightMode;

final FilterQuality filterQuality;

@override
State<StatefulWidget> createState() {
return PhotoViewCoreState();
Expand Down Expand Up @@ -282,9 +286,10 @@ class PhotoViewCoreState extends State<PhotoViewCore>
) {
if (snapshot.hasData) {
final PhotoViewControllerValue value = snapshot.data;
final useImageScale = widget.filterQuality != FilterQuality.none;
final matrix = Matrix4.identity()
..translate(value.position.dx, value.position.dy)
..scale(scale);
..scale(useImageScale ? 1.0 : scale);
if (widget.enableRotation) {
matrix..rotateZ(value.rotation);
}
Expand All @@ -293,6 +298,7 @@ class PhotoViewCoreState extends State<PhotoViewCore>
delegate: _CenterWithOriginalSizeDelegate(
scaleBoundaries.childSize,
basePosition,
useImageScale,
),
child: _buildHero(),
);
Expand Down Expand Up @@ -343,28 +349,37 @@ class PhotoViewCoreState extends State<PhotoViewCore>
: Image(
image: widget.imageProvider,
gaplessPlayback: widget.gaplessPlayback ?? false,
filterQuality: widget.filterQuality,
width: scaleBoundaries.childSize.width * scale,
fit: BoxFit.contain,
);
}
}

class _CenterWithOriginalSizeDelegate extends SingleChildLayoutDelegate {
const _CenterWithOriginalSizeDelegate(this.subjectSize, this.basePosition);
const _CenterWithOriginalSizeDelegate(
this.subjectSize, this.basePosition, this.useImageScale);

final Size subjectSize;
final Alignment basePosition;
final bool useImageScale;

@override
Offset getPositionForChild(Size size, Size childSize) {
final double offsetX =
((size.width - subjectSize.width) / 2) * (basePosition.x + 1);
final double offsetY =
((size.height - subjectSize.height) / 2) * (basePosition.y + 1);
((size.width - (useImageScale ? childSize.width : subjectSize.width)) /
2) *
(basePosition.x + 1);
final double offsetY = ((size.height -
(useImageScale ? childSize.height : subjectSize.height)) /
2) *
(basePosition.y + 1);
return Offset(offsetX, offsetY);
}

@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return BoxConstraints.tight(subjectSize);
return useImageScale ? BoxConstraints() : BoxConstraints.tight(subjectSize);
}

@override
Expand Down