Integrating Jpegtran, remove LLJTran + Exifinterface setup#6910
Integrating Jpegtran, remove LLJTran + Exifinterface setup#6910rovertrack wants to merge 8 commits into
Conversation
…ragmentUnitTests.kt to unit tests as they are not intrumented tests
replacing LLJtran + Exifinterface setup.
…brary, moved the resources for tests.
|
|
There was a problem hiding this comment.
Pull request overview
This PR migrates the app’s JPEG edit pipeline from the previous LLJTran + ExifInterface approach to a new jpegtran-based implementation, and reorganizes tests so native-library-dependent coverage runs as instrumented tests.
Changes:
- Replace LLJTran-based rotation/crop implementation with
ajpegtran(jpegtran) and add session-style initialization/cleanup APIs. - Move/adjust tests: delete the old Robolectric
TransformImageTestand add a new instrumentedTransformImageTest; relocate some fragment tests to unit tests. - Update upload UI copy to reflect jpegtran usage and remove AndroidMediaUtil dependency.
Reviewed changes
Copilot reviewed 9 out of 30 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
gradle/libs.versions.toml |
Adds ajpegtran to the version catalog and removes AndroidMediaUtil; also introduces an unrelated XR runtime alias/version. |
app/build.gradle.kts |
Removes AndroidMediaUtil dependency and adds ajpegtran. |
app/src/main/java/fr/free/nrw/commons/edit/TransformImage.kt |
Extends the image transform abstraction with jpegtran init/properties/cleanup APIs. |
app/src/main/java/fr/free/nrw/commons/edit/TransformImageImpl.kt |
Reimplements rotate/crop using jpegtran session state. |
app/src/main/java/fr/free/nrw/commons/edit/EditViewModel.kt |
Adds ViewModel-level init/properties/cleanup delegation for jpegtran session handling. |
app/src/main/java/fr/free/nrw/commons/edit/EditActivity.kt |
Initializes jpegtran in the editing flow and switches crop dimension source to jpegtran properties. |
app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.kt |
Updates the comment describing JPEG-only editing limitations. |
app/src/test/.../ContributionsListFragmentUnitTests.kt |
Adds/relocates fragment unit tests. |
app/src/test/.../MoreBottomSheetLoggedOutFragmentUnitTests.kt |
Adds/relocates fragment unit tests. |
app/src/test/.../TransformImageTest.kt |
Removes the old Robolectric jpeg-transform test suite. |
app/src/androidTest/.../TransformImageTest.kt |
Adds an instrumented jpegtran-backed transform test suite. |
Comments suppressed due to low confidence (2)
app/src/main/java/fr/free/nrw/commons/edit/TransformImageImpl.kt:16
- This file has several unused imports (e.g.,
ExifInterface, coroutines,BufferedOutputStream,FileOutputStream) that are no longer referenced after switching from LLJTran. Removing them avoids lint failures and makes the class easier to read.
import android.content.Context
import androidx.exifinterface.media.ExifInterface
import android.net.Uri
import androidx.core.net.toUri
import fr.free.nrw.commons.ajpegtran.Jpegtran
import fr.free.nrw.commons.ajpegtran.Properties
import fr.free.nrw.commons.ajpegtran.rotate.RotationDegree
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileOutputStream
app/src/main/java/fr/free/nrw/commons/edit/EditActivity.kt:44
- This class KDoc still mentions “copying EXIF data” and “preserving its EXIF attributes”, but the explicit EXIF-copying logic was removed in this PR. The comment should be updated so it matches the current implementation (either rely on jpegtran preserving metadata, or state explicitly what is/ isn’t preserved).
* An activity class for editing and rotating images using Jpegtran.
*
* This activity allows loads an image, allows users to rotate it by 90-degree increments, and
* save the edited image while preserving its EXIF attributes. The class includes methods
* for initializing the UI, animating image rotations, copying EXIF data, and handling
* the image-saving process.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
✅ Generated APK variants! |
RitikaPahwa4444
left a comment
There was a problem hiding this comment.
Looks good in general, left some minor suggestions
| } catch (e: Exception) { | ||
| try { | ||
| contentResolver.openInputStream(Uri.parse(imageUri))?.use { | ||
| contentResolver.openInputStream(imageUri.toUri())?.use { |
There was a problem hiding this comment.
I'm assuming this doesn't change the existing behaviour, please correct me if this understanding is wrong.
| ): File { | ||
| Timber.tag("Trying to rotate image").d("Starting") | ||
| val imagePath = System.currentTimeMillis() | ||
| val output = File(savePath, "rotated_$imagePath.jpg") |
There was a problem hiding this comment.
How about declaring the complete image path as one variable? System.currentTimeMillis() gives a slightly different impression.
| */ | ||
| interface TransformImage { | ||
|
|
||
| /** |
There was a problem hiding this comment.
Now that we have a separate library, we should be able to get rid of this extra layer. I'll raise a clean-up issue that we can pick later.
| * @return The cropped image File, or null if the crop operation fails. | ||
| */ | ||
| override fun cropImage( | ||
| imageFile: File, |
There was a problem hiding this comment.
Are we using imageFile anywhere?
| inJustDecodeBounds = true | ||
| val finalPath = file?.absolutePath | ||
| val resultIntent = Intent().apply { | ||
| putExtra("editedImageFilePath", finalPath) |
There was a problem hiding this comment.
Can filePath be null? Not a very good way to handle it but the deleted code was sending an error back:
resultIntent.putExtra("editedImageFilePath", file?.toUri()?.path ?: "Error")
setResult(RESULT_OK, resultIntent)
|
I just tested the app - do we need to hit the Save button on every operation? I cropped, then wanted to rotate, but that reverted the previous change... Saving exits the EditActivity, so I need to open it again to rotate. |
|
Nice cleanup — removing all that manual MCU-alignment/lossless-crop workaround code in favour of a proper library is a real improvement. One behavioural difference I noticed: in the old |
Description (required)
Integrating Jpegtran which replaces the current LLJTran + Exifinterface setup.
What changes did you make and why?
Tests performed (required)
Transformimagetest.ktScreenshots (for UI changes only)