fix(StatusImageCrop): fix wrong initial image fit

The initial fit was computed for the square crop-window

updates: 5118
This commit is contained in:
Stefan 2022-05-20 23:05:19 +03:00 committed by Stefan Dunca
parent 07e711e30c
commit ee3effcdd1
2 changed files with 41 additions and 52 deletions

View File

@ -82,12 +82,7 @@ Item {
\qmlproperty rect StatusImageCropPanel::cropRect \qmlproperty rect StatusImageCropPanel::cropRect
\sa StatusImageCrop::cropRect \sa StatusImageCrop::cropRect
*/ */
property alias cropRect: cropEditor.cropRect readonly property alias cropRect: cropEditor.cropRect
/*!
\qmlproperty rect StatusImageCropPanel::cropRect
\sa StatusImageCrop::cropRect
*/
readonly property alias cropWindow: cropEditor.cropWindow
/*! /*!
\qmlproperty real StatusImageCrop::scrollZoomFactor \qmlproperty real StatusImageCrop::scrollZoomFactor
How fast is image scaled (zoomed) when using mouse scroll How fast is image scaled (zoomed) when using mouse scroll
@ -116,16 +111,11 @@ Item {
QtObject { QtObject {
id: d id: d
readonly property int referenceWindowWidth: 1000
function updateAspectRatio(newAR) { function updateAspectRatio(newAR) {
// Keep width and adjust height if(root.sourceSize.width === 0 || root.sourceSize.height === 0)
const eW = cropEditor.cropRect.width return
const w = (eW <= 0) ? cropEditor.sourceSize.width : eW cropEditor.setCropRect(cropEditor.fillContentInWindow(root.sourceSize, Qt.size(referenceWindowWidth, referenceWindowWidth / root.aspectRatio)))
const h = w/newAR
const c = (eW <= 0)
? Qt.point(cropEditor.sourceSize.width/2, cropEditor.sourceSize.height/2)
: Qt.point(cropEditor.cropRect.x + w/2, cropEditor.cropRect.y + cropEditor.cropRect.height/2)
const nR = Qt.rect(c.x - w/2, c.y-h/2, w, h)
cropEditor.setCropRect(nR)
} }
} }

View File

@ -123,12 +123,6 @@ Item {
e.g. to set the crop window to show and match image's AR use Qt.rect(0, 0, sourceSize.width, sourceSize.height) e.g. to set the crop window to show and match image's AR use Qt.rect(0, 0, sourceSize.width, sourceSize.height)
*/ */
readonly property rect cropRect: d.cropRect readonly property rect cropRect: d.cropRect
/*!
\qmlproperty rect StatusImageCrop::cropRect
The position and zis of the crop rectangle in item's space; without extra spacing
*/
readonly property alias cropWindow: d.cropWindow
/*! /*!
\qmlproperty real StatusImageCrop::aspectRatio \qmlproperty real StatusImageCrop::aspectRatio
*/ */
@ -146,7 +140,7 @@ Item {
\sa StatusImageCrop::source \sa StatusImageCrop::source
*/ */
readonly property size sourceSize: mainImage.sourceSize readonly property alias sourceSize: mainImage.sourceSize
/*! /*!
\qmlproperty real StatusImageCrop::scrToImgScale \qmlproperty real StatusImageCrop::scrToImgScale
@ -218,7 +212,7 @@ Item {
function getZoomRect(scale /*real*/) { function getZoomRect(scale /*real*/) {
const oldCenter = root.rectCenter(root.cropRect) const oldCenter = root.rectCenter(root.cropRect)
const inflatedRect = root.inflateRectBy(root.minimumCropRect(), 1/scale) const inflatedRect = root.inflateRectBy(d.minimumCropRect(), 1/scale)
return root.recenterRect(inflatedRect, oldCenter); return root.recenterRect(inflatedRect, oldCenter);
} }
@ -248,44 +242,34 @@ Item {
return Qt.rect(newCenter.x - target.width/2 , newCenter.y - target.height/2, target.width, target.height) return Qt.rect(newCenter.x - target.width/2 , newCenter.y - target.height/2, target.width, target.height)
} }
//> cropRect for minimum zoom: 1.0 function fillContentInWindow(contentSize /*size*/, windowSize /*size*/) {
function minimumCropRect() { const contentAR = contentSize.width/contentSize.height
const sourceAR = root.sourceSize.width/root.sourceSize.height const windowAR = windowSize.width/windowSize.height
const widthBound = sourceAR > root.aspectRatio const heightBound = contentAR > windowAR
const minCropSize = widthBound ? Qt.size(root.sourceSize.width, root.sourceSize.width/root.aspectRatio) if(heightBound) {
: Qt.size(root.sourceSize.height * root.aspectRatio, root.sourceSize.height) const wWidth = contentSize.height * windowAR
let res = Qt.rect(widthBound ? 0 : -(root.sourceSize.width - minCropSize.width)/2, // x const horizontalBorder = (contentSize.width - wWidth)/2
widthBound ? -(root.sourceSize.height - minCropSize.height)/2 : 0, // y return Qt.rect(horizontalBorder, 0, wWidth, contentSize.height)
minCropSize.width, minCropSize.height) }
return res else {
const wHeight = contentSize.width / windowAR
const verticalBorder = (contentSize.height - wHeight)/2
return Qt.rect(0, verticalBorder, contentSize.width, wHeight)
}
} }
QtObject { QtObject {
id: d id: d
property rect cropRect: fillContentInSquaredWindow(root.sourceSize) property rect cropRect
onCropRectChanged: windowRect.requestPaint() onCropRectChanged: windowRect.requestPaint()
readonly property real zoomToFill: { readonly property real zoomToFill: {
const rectangle = fillContentInSquaredWindow(root.sourceSize) const rectangle = root.fillContentInWindow(root.sourceSize, d.cropWindowSize)
return d.currentZoom(root.sourceSize, Qt.size(rectangle.width, rectangle.height)) return d.currentZoom(root.sourceSize, Qt.size(rectangle.width, rectangle.height))
} }
property rect cropWindow property size cropWindowSize: Qt.size(d.cropRect.width, d.cropRect.height)
// Probably called from render thread, run async
signal updateCropWindow(rect newRect)
onUpdateCropWindow: cropWindow = newRect
function fillContentInSquaredWindow(c /*size*/) {
if(c.width > c.height) {
const border = (c.width - c.height)/2
return Qt.rect(border, 0, c.height, c.height)
}
else {
const border = (c.height - c.width)/2
return Qt.rect(0, border, c.width, c.width)
}
}
//> 1.0 is the content represented by w fully inscribed in c //> 1.0 is the content represented by w fully inscribed in c
function currentZoom(c /*size*/, w /*size*/) { function currentZoom(c /*size*/, w /*size*/) {
@ -293,10 +277,26 @@ Item {
const hScale = c.height/w.height const hScale = c.height/w.height
return Math.max(wScale, hScale) return Math.max(wScale, hScale)
} }
//> cropRect for minimum zoom: 1.0
function minimumCropRect() {
const sourceAR = root.sourceSize.width/root.sourceSize.height
const widthBound = sourceAR > root.aspectRatio
const minCropSize = widthBound ? Qt.size(root.sourceSize.width, root.sourceSize.width/root.aspectRatio)
: Qt.size(root.sourceSize.height * root.aspectRatio, root.sourceSize.height)
let res = Qt.rect(widthBound ? 0 : -(root.sourceSize.width - minCropSize.width)/2, // x
widthBound ? -(root.sourceSize.height - minCropSize.height)/2 : 0, // y
minCropSize.width, minCropSize.height)
return res
}
} }
onWindowStyleChanged: windowRect.requestPaint() onWindowStyleChanged: windowRect.requestPaint()
onSourceSizeChanged: d.cropRect = d.fillContentInSquaredWindow(sourceSize) onRadiusChanged: windowRect.requestPaint()
onSourceSizeChanged: {
if(d.cropWindowSize.width > 0 && d.cropWindowSize.height > 0)
d.cropRect = root.fillContentInWindow(sourceSize, d.cropWindowSize)
}
Canvas { Canvas {
id: windowRect id: windowRect
@ -330,7 +330,6 @@ Item {
ctx.roundedRect(cW.x, cW.y, cW.width, cW.height, root.radius, root.radius) ctx.roundedRect(cW.x, cW.y, cW.width, cW.height, root.radius, root.radius)
ctx.fill() ctx.fill()
ctx.restore() ctx.restore()
d.updateCropWindow(cW)
} }
} }