Page MenuHomePhabricator

[GSoC Proposal] Implement lossless JPG transformations in the Commons Android App
Open, Needs TriagePublic

Description

Profile Information

Name: Rishan P
Email: Rishan.pgowda@gmail.com
Github : rovertrack
Other communication modes: Discord, Zulip, Slack.
Location during GSoC: Bangalore India.
Typical Working hours (include your timezone) during GSoC: 6:00 pm to 2:00 am (IST) UTC+5:30

Synopsis

App

Wikimedia Commons is an Android application developed by the Wikimedia Foundation that enables users to browse, upload, and contribute media directly to the Wikimedia Commons repository using their mobile devices. Users can easily select images from their device gallery or capture photos using the camera and upload them to the platform. The app aims to simplify the media contribution workflow and make it easier for contributors to share freely licensed images with the Wikimedia ecosystem.

Project

Project Objectives
  • Improve the existing lossless crop/rotate feature to not lose any information, preserving exact picture colors
  • Lossless blur: JPG images are made of many 8x8 pixel blocks. The idea here is to blur only the JPG blocks showing what the users wants to blur, without recompressing the other blocks.
  • Option to automatically blur people faces and car number plates.
Possible Mentor(s)

@Nicolas_Raoul
@RitikaPahwa4444

Have you contacted your mentors already?

Yes.

Implementation

Github issue/discussion links

  • Improve the existing lossless crop/rotate feature to not lose any information, preserving exact picture colors: #6659
  • Lossless blur: JPG images are made of many 8x8 pixel blocks. The idea here is to blur only the JPG blocks showing what the users wants to blur, without recompressing the other blocks: #190

I have no prior knowledge about JPG format , except messing around with photoshop in my school days i got to know about key things like RGB, pixel rendering , pixel blocks grid. That's what got me interested in this project

Phase 1 - Improve existing crop feature

Problem
Issue #6659
The current crop feature takes in the Jpeg runs LLJTran (reads the compressed JPEG blocks, rearranges them mathematically for rotation) here there is no loss in quality.In this step there is no loss in image quality.
LLJTran only handles the IMAGEDATA, not the METADATA.
Metadata is handled by the android's built-in metadata handler
ExifInterface.saveAttributes()
but this handler in the process strips off ICC profile as it ignores the APP2 marker throughout the transformation.
This results in loss in image quality

Solution
Instead of the above two step process we can achieve the lossless crop by passing the image to Jpegtran which is in native C library which on rotation copies every metadata byte-for-byte , rearranges DCT blocks for rotation.NO decoding, NO recompression in the process
This results in :

  • Single step process
  • No metadata such as EXIF , ICC is lost in the process
  • No recompression of the image

As Jpegtran is a C library it would require a JNI (Java Native Interface) for the kotlin application layer to communicate with the Jpegtran library.

Phase 2 - Lossless Block-Level Blur

Problem
Issue #190
Present normal blur make quality loss in the process.
When normal blur is applied to a JPEG image it decodes all pixels , applies blur then recompresses everything which make the image lose quality , metadata and increase in file size.

Solution
If the recompression happens to only relevant blur required pixel blocks then we would not lose quality of the pixel blocks which are untouched then we wont have loss in quality of unblurred regions.

Process:

  1. Get bounding box to the region the user wants to apply the blur :
    • User selects the region by drawing over which gives us the pixel coordinates.
    • Map pixel coordinates to the nearest Minimum Coded Unit (MCU) boundaries.
    • Jump to nearest block boundary if needed.
  2. Transmit the calculated MCU indices to the native layer via JNI. This allows jpegtran to perform high-speed, direct manipulation of the DCT coefficients within the target blocks.
  3. Now that jpegtran has the target blocks it can easily apply them to JPEG 8×8 DCT blocks.

Screenshot 2026-03-29 054329.png (465×581 px, 35 KB)

  • B = background blocks (untouched)
  • F = target blocks (to be blurred)
  • Each block is independent and blurring one block has no effect on another , making sure blur is only applied to required regions.

The Result

  • Original metadata and header preserved
  • Unblurred regions are preserved to their original quality without loss.
  • blur applied to only selected region.

Phase 3 - Auto-detect and blur faces & car number plates.

Problem
No privacy for random people and car number plates captured in the uploading photo.
solution
Display an option for users which upon selecting detects people faces and car number plates in the image, shows to user to which block/region the blur is going to be applied.
The user can confirm all region , remove some of the regions or add regions manually to which the blur needs to be applied.

Process
Uses OpenCV to detect faces/plates.

  1. The selected image is passed to OpenCV DNN via a JNI bridge which runs locally on the phone which runs pretrained lightweight deep learning models trained for object detection.

Preferring DNN over haar cascade as it detects faces in most of the angles compared to later one.
Faces - SSD , MobileNet.
Plates - Lightweight detection model.

  1. Low confidence detections are filtered out using a confidence threshold before being shown to the user.

The bounding box coordinates returned by OpenCV is shown as regions to the user to which the user can

  • confirm all region
  • remove some of the regions
  • add regions manually
  • After the coordinates are finalized it is passed to the same image editing feature which the phase 2 improves the image blurring which applies blur to only required region and remaining region untouched.

Results:

  • User always has final control over what gets blurred
  • Confirmed bounding boxes passed directly to Phase 2
  • Missed regions can be added manually by user
  • False positives can be removed by user
  • Faces , plates and user selected region is blurred successfully.

Deliverables

Timeline

Period ClassificationTasks
Community bonding (May 4 - May 24) Community & SetupGet familiar with mentors / community . Study existing image editing pipeline, LLJTran usage, ExifInterface calls. Set up NDK/JNI build environment. Study jpegtran . Finalize implementation plan with mentors
Week 1-2 (May 25 - June 7)Phase 1: JNI Bridge & jpegtran SetupIntegrate jpegtran using Android NDK. Implement JNI bridge (Kotlin ↔ C). Verfiy quality of image is preserved as original
Week 3-4(June 8 - June 21)Phase 1: Lossless Crop & Rotate CompleteReplace LLJTran + ExifInterface pipeline with pure jpegtran. Verify ICC color profile preserved after rotation. Verify brightness/gamma consistency before and after. Integrate into existing editing UI. Write unit tests
Week 5-6(June 22 - July 5)Phase 2: Lossless Block BlurIntegrate jpegtran via same JNI bridge. Implement pixel coordinate -> MCU block boundary mapping. Implement user region selection UI (draw rectangle). Apply blur to only selected 8×8 blocks. Verify unblurred regions byte-for-byte identical to original.
Week 7 (July 6 - July 12)Mid term evaluationPhase 1 and Phase 2 complete and tested.Midterm evaluation.
Week 8 (July 13 - July19)ExamsEnrolled exam period. Manual testing of Phase 1 and Phase 2. Bug fixes. Code cleanup. No major feature work.
Week 9-10(July 20 - August 2)Phase 3: OpenCV DNN IntegrationIntegrate OpenCV into Android project. Implement JNI bridge for OpenCV DNN. Load SSD MobileNet for face detection. Load lightweight model for license plate detection. Convert Bitmap -> OpenCV Mat. Run detection pipeline locally on device.Verify Proper working
Week 11 (August 3 - August 9)Phase 3: Detection + Blur IntegrationFilter low confidence detections using confidence threshold. Display detected bounding boxes to user for confirmation. Connect confirmed boxes to Phase 2 blur pipeline. Allow user to add/remove/adjust regions manually. End-to-end testing of full pipeline.Write Unit tests for this.
Week 12 (August 10 - August 16)Final CleanupPerformance optimization. Final bug fixes. UI polish. Documentation and developer guidelines. Final project report., Thank you for a wonderful GSOC 2026

This roadmap is designed to be flexible. If technical debt or implementation blockers arise, work can continue beyond the 12-week GSoC period to ensure code quality is never sacrificed for speed. I plan to continue contributing to the Wikimedia Commons Android App even after the GSoC program ends, maintaining the implemented features, addressing feedback, and contributing to other areas of the codebase.

About Me

  • How did you hear about this program?

X (twitter)

  • Will you have any other time commitments, such as school work, another job, planned vacation, etc, during the duration of the program?

Have enrolled in one exam happening July 10 - July 20

  • We advise all candidates eligible for Google Summer of Code and Outreachy to apply for both programs. Are you planning to apply to both programs and, if so, with what organization(s)?

Yes , Wikimedia Foundation i dont know why but thats the one organization which i get along well.

  • What does making this project happen mean to you?

Means gaining knowledge under guidance of some of the best mentors .Knowledge which will help me improve more Giving to open source, Providing values

Availability

Eligible for Google Summer of Code and Outreachy?
I am eligible for Google Summer of Code and am applying only for GSoC.

Do you plan to submit any other proposal apart from this one?
Yes.

Do you have any other plans this summer?
No I will have an exam which i have enrolled in from July 10 - July 20 , during time i will test the app manually for proper working and implement bug fixes , after this my full time is for Gsoc .

How many hours per week can you dedicate to this project?
I will dedicate a minimum of 44+ hours per week to this project and am willing to invest additional time if required to meet project goals.

Have you been accepted to GSoC before?
No, this is my first time applying for Google Summer of Code.

Contributions to Wikimedia Commons

Pull request

Link PRs

  • Total: 25
  • Merged: 13
  • Pending: 11
  • Draft: 1
PR TaskStatus
#6686Updated Commons app to query subclassesMerged
#6721reduced the number of subclasses to query to improve performanceMerged
#6730Feature : Added Depiction selector , pick on mapMerged
#6770Move dbhelper to SupportSQLiteOpenHelper (Room Migration)Merged
#6774created Room based entities and DAOs (Room migration)Merged
#6797Added tests for migration legacy to roomMerged
#6708Fix: crash feedback when no option selectedMerged
#6658fix: Broken media detail layoutMerged
#6664fix: Snappy jump of media detail on launchMerged
#6671fix : Improve nearby sparql queries to query classMerged
#6673Added gas station iconMerged
#6687Added bank and hospital iconsMerged
#6690Recycler view item's text alignmentMerged

Pull Requests Under Review

PR TaskStatus
#6696Fix: alignment bottomsheet headerOpen
#6705Fix: Leaks at Media Detail FragmentOpen
#6711Fix: Keyboard flashOpen
#6713Fix: alignment nearby list itemOpen
#6716fix: Leaks contribution fragmentOpen
#6717Fix : paging and explore map leaksOpen
#6718Fix: Upload MediaDetail LeaksOpen
#6719Fix: NearbyParentFragment LeaksOpen
#6724Optimize Nearby labelsopen
#6754Fix: Nearby filter recycler view not rendering proper itemOpen
#6762fix: Autoformatting issuesopen

Draft Pull Requests

PR Name Status
#6761Searchbar compose migrationDraft

Issues

Link Issue

  • Created: 13
  • Closed: 10
  • Open: 3
Issue Name Status
#4186Crash on tapping last itemClosed
#6798DB Migration copy data from legacyDB to roomClosed
#6777Write tests for migration to roomClosed
#6773Create Room based entities and DAOsClosed
#6769Move the DBOpenHelper to the more modern androidx.sqlite.db.SupportSQLiteOpenHelperClosed
#6707[Bug]: crash at nearby item feedback when no option selectedClosed
#6688[Bug]: recycler items title not perfectly centeredClosed
#6684[Bug]: some places show unknown "?" as they are missing classesClosed
#6683add missing bank and hospital labelsClosed
#6670[Bug]: nearby places not being set with the classesClosed
#6668[Bug]: missing important labels for major placesClosed
PR Review
PR Name Status
#6742Fix: Snackbar overlapping bottom navigation bar on Explore screenMerged

Event Timeline

@Nicolas_Raoul @RitikaPahwa4444 Can you provide some feedback on my proposal when you have the time and tell me some improvements.
Thanks.

Thank you very much for the review and feedback @Nicolas_Raoul.

Hi, thanks for submitting your GSoC 2026 project proposal with Wikimedia!

Please make sure you’ve also submitted your proposal on the official Summer of Code website: https://summerofcode.withgoogle.com. The deadline for both submission and any edits is the same, so ensure everything is finalized before March 31, 18:00 UTC, as changes won’t be possible after that.

We strongly recommend completing any updates at least 30 minutes before the deadline to avoid last-minute glitches or unexpected technical issues.

Wishing you all the best for your application. Hope to see you as part of the program soon! 🚀

Weekly Internship Report

Week 1: May 25 – May 31

Task Progress

  • Based on the intro call done during the community bonding period. The plan was to integrate the Jpegtran library into the commons app. But the library was not in the android library format and was only available as the C command line interface, So instead of having a whole NDK setup (Also as there are no future Native C functionality expected to be in the app) in the commons app where everyone has to install the NDK and setup the NDK environment. It was best we would create an independent library and push the library artifact to maven repository. so that it can just be integrated into the app just like any other.
  • Kamemak authored jpegtran_pixelization library was the one which supported blurring by default. A fork of that library under the commons repo. Which would let us maintain the library and check for changes and update it accordingly required for the proper operation in the android environment
  • The plan also included that this library would have CI/CD pipeline which would auto publish to the maven repo with the latest update. So the fork had to have our own android library beside the main library,
  • Initially we had forked a library which only supported CLI's, To our luck there was another kamemak authored library ajpegtran_example which had exactly what we intended - support operations in the android environment like reading files else we would have had to implement this from scratch. So we dropped the idea of using the other one and focused only on this!
  • A Demo app which would let us test the features exposed by the library. This is in the library repo itself.

Challenges

  • If we want to pusblish the library in CI/CD so instead of targeting the C source files in another module - which is exact copy of the upstream, Also package name conflict would lead to unlinked in error in the build process. We copied the folder into our own module and changed the package name and made it supported our module package name.

Learnings

  • How NDK and native functions are used inside the android apps.
  • Learnt about descriptors as they are used to manage the file openings in the core C library.
  • Sometimes having a separate library rather than having the whole NDK setup in the main app, saves people from extra work.

Weekly Internship Report

Week 2: June 1– June 7

Task Progress

  • Got feedback from maintainers that the API looks good, but the code structure is a bit coupled and the main class was doing more than what it was responsible. So focused fully on making the architecture SOLID and made sure that any newly added features are easily integrated.
  • Made a architectural diagram. This would save us from a lot of refactoring later on and makes sure my vision what i want to implement is visible and maintainers could point out and guide me. Turned out good and settled on some extra pointers and ready to implement.

Challenges

  • we had to make sure there is very less heavy lifting done by the consumer - the developer trying to integrate our library into their app. So we want to make library do all heavy lifting - manage creation and clearing of temp files, keep edited image in the buffer during the whole process instead of passing the file for each transformation.
  • The android Library was made android compatible by the author but still it required options to be passed in CLI based format. Idea was to make the methods specific to each feature. This also helps in better type-check of all the options being processed in the library.

Learnings

  • Thanks to my mentor @RitikaPahwa4444, I learnt that before implementing we must see all the tradeoffs and clarity on responsibility for individual classes. Understand all their requirements and then use the programming principles to design the architecture/API.
  • Any software can start and end at one single main file. It's about how it performs in the long run and how easily new features can be integrated without modifying many of the existing classes