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

Ability to view image edges in the center of the screen #63

Open
gmikhail opened this issue Feb 2, 2024 · 3 comments
Open

Ability to view image edges in the center of the screen #63

gmikhail opened this issue Feb 2, 2024 · 3 comments

Comments

@gmikhail
Copy link

gmikhail commented Feb 2, 2024

I want to achieve this behavior:

Screen_recording_20240202_204729.mp4

How can I do it?

In Subsampling Scale Image View I only have to setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_CENTER) for this.

@saket
Copy link
Owner

saket commented Feb 2, 2024

I've been wanting to do this, but haven't been able to find time yet. Wanna help me out? 🙂

We can add a PanSpec class along the lines of ZoomSpec.

@gmikhail
Copy link
Author

gmikhail commented Feb 3, 2024

Next week I'll try to see how it's done in Subsampling Scale Image View.

I haven't looked at the Telephoto source code yet, so I'm not sure how long it will take to implement this functionality.

@gmikhail
Copy link
Author

gmikhail commented Feb 8, 2024

I made a working implementation of this feature using Coil. The implementation itself is quite simple. We calculate the available boundaries and then constrain the offset within them.

var imageWidth by remember { mutableIntStateOf(0) }
var imageHeight by remember { mutableIntStateOf(0) }
var zoom by remember { mutableFloatStateOf(1f) }
var offsetX by remember { mutableFloatStateOf(0f) }
var offsetY by remember { mutableFloatStateOf(0f) }
val minScale = 1f
val maxScale = 5f
// Gesture container
Box(
    modifier = Modifier
        .fillMaxSize()
        .checkerboardBackground()
        .pointerInput(Unit) {
            detectTransformGestures(
                onGesture = { _, pan, gestureZoom, _ ->
                    zoom = (zoom * gestureZoom).coerceIn(minScale, maxScale)
                    // --- PAN_LIMIT_CENTER implementation start ---
                    val imageWidthHalf = (imageWidth / 2f) * zoom
                    val imageHeightHalf = (imageHeight / 2f) * zoom
                    val newOffsetX = offsetX + pan.x
                    val newOffsetY = offsetY + pan.y
                    offsetX = newOffsetX.coerceIn(-imageWidthHalf, imageWidthHalf)
                    offsetY = newOffsetY.coerceIn(-imageHeightHalf, imageHeightHalf)
                    // --- PAN_LIMIT_CENTER implementation end ---
                    LogUtil.log(TAG, "offsetX = $offsetX, offsetY = $offsetY")
                }
            )
        }
    contentAlignment = Alignment.Center
) {
    // Image
    AsyncImage(
        model = ImageRequest.Builder(LocalContext.current)
            .data(uri)
            .listener(
                onSuccess = { _, result ->
                    val bitmap = result.drawable.toBitmap()
                    imageWidth = bitmap.width
                    imageHeight = bitmap.height
                    // TODO work with bitmap
                }
            )
            .build(),
        contentDescription = null,
        modifier = Modifier
            .graphicsLayer(
                scaleX = zoom,
                scaleY = zoom,
                translationX = offsetX,
                translationY = offsetY,
            )
    )
}

Could you help with integration into Telephoto?

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

2 participants