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

Need SubsamplingScaleImageView.visibleFileRect(Rect fRect) analog #89

Open
NatalySd opened this issue May 20, 2024 · 4 comments
Open

Need SubsamplingScaleImageView.visibleFileRect(Rect fRect) analog #89

NatalySd opened this issue May 20, 2024 · 4 comments

Comments

@NatalySd
Copy link

I need to get the visible area Rect of the source bitmap to save it into another one (android wallpapers app).
It seems I need something like davemorissey SubsamplingScaleImageView.visibleFileRect(Rect fRect) in ZoomableState.
I tried to look at contentTransformation & transformedContentBounds, but did not succeded in getting the exact rect which is shown.
It would be nice if you add such method.

@brinsche
Copy link

This sounds similar to #64 (comment) maybe the solution works for you as well?

@NatalySd
Copy link
Author

Thanks, but this is different. Composable-to-bitmap api writes to a bitmap a piece of the screen and I need a piece of the original bitmap.

@saket
Copy link
Owner

saket commented May 20, 2024

Hmm, I would have expected transformedContentBounds to give you the bounds you're looking for.

override val transformedContentBounds: Rect by derivedStateOf {
with(contentTransformation) {
if (isSpecified) {
unscaledContentBounds.withOrigin(transformOrigin) {
times(scale).translate(offset)
}

Are its numbers significantly off?

@NatalySd
Copy link
Author

NatalySd commented May 21, 2024

I made some experiments.
I have bitmap 1920 x 1080 (aspect ratio = 1,777777777777778) and screensize = 2000 x 1200 (aspect ratio = 1,666666666666667). I show it full size with ContentScale.Crop and want to get the visible area from the bitmap.

If I pan to top left corner, then visible bitmap crop area will be
left=0, top=0, right=1800, bottom=1080
According to logs I have
contentSize=Size(1920.0, 1080.0) offset=Offset(0.0, 0.0) scaleX=1.1111112 scaleY=1.1111112 transformedContentBounds=Rect.fromLTRB(0.0, 0.0, 2133.3, 1200.0)

If I pan to bottom right corner , then visible bitmap crop area will be
left=120, top=0, right=1920, bottom=1080
According to logs I have
contentSize=Size(1920.0, 1080.0) offset=Offset(-133.3, 0.0) scaleX=1.1111112 scaleY=1.1111112 transformedContentBounds=Rect.fromLTRB(-133.3, 0.0, 2000.0, 1200.0)

So I finnaly succedded to get this area correctly with the following code

getCroppedRectFromBitmap(
    sourceBitmap,
    contentWidth = zoomableState.contentTransformation.contentSize.width,
    contentHeight = zoomableState.contentTransformation.contentSize.height,
    scaledRectWidth = imageContentSizeInDp.width.value * density.density,
    scaledRectHeight = imageContentSizeInDp.height.value * density.density,
    scaledOffsetX = zoomableState.contentTransformation.offset.x,
    scaledOffsetY = zoomableState.contentTransformation.offset.y,
    scaleX = zoomableState.contentTransformation.scale.scaleX,
    scaleY = zoomableState.contentTransformation.scale.scaleY,
)

fun getCroppedRectFromBitmap(
    sourceBitmap:Bitmap,
    scaledRectWidth: Float,
    scaledRectHeight: Float,
    scaledOffsetX: Float,
    scaledOffsetY: Float,
    scaleX: Float,
    scaleY: Float,
): Bitmap? {
    val scale = max(scaleX, scaleY)
    val left = abs(scaledOffsetX / scale).toInt()
    val top = abs(scaledOffsetY / scale).toInt()
    var width = (scaledRectWidth / scale).toInt()
    width = min(width, sourceBitmap.width - left)
    var height = (scaledRectHeight / scale).toInt()
    height = min(height, sourceBitmap.height - top)
    return Bitmap.createBitmap(sourceBitmap, left, top, width, height)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants