Skip to content
New issue

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

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

Already on GitHub? # 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)
}

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

No branches or pull requests

3 participants