Skip to content

ICC APP2 section strip#654

Draft
0xDE57 wants to merge 8 commits into
GrapheneOS:mainfrom
0xDE57:remove_icc
Draft

ICC APP2 section strip#654
0xDE57 wants to merge 8 commits into
GrapheneOS:mainfrom
0xDE57:remove_icc

Conversation

@0xDE57

@0xDE57 0xDE57 commented Jun 22, 2026

Copy link
Copy Markdown

Ok. Got this working! New toggle, off by default. Closes #520

Consider this a draft as there are a still some minor todo's:

  1. Does this new setting need an icon? It gave me an error trying to reuse the [!] icon from the exif setting: Duplicate id '@+id/remove_exif_icon', already defined earlier in this layout
  2. Any verbiage adjustments; "Note: Removing ICC can lower image quality / accuracy when viewed on some screens."
  3. PNG support? I didn't see any option for saving as PNG, so only implemented the default JPG. But I can add PNG ICC strip support if needed. Nvm, I see PNG is not supported in 529.
  4. Further testing / validation:

I have only tested on a Pixel 9a which appears to only have 1 ICC chunk by default:

2026-06-21 23:06:01.883  3387-3523  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 1/1 (596 bytes).
2026-06-21 23:06:01.883  3387-3523  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC Profile found! Size: 610 bytes. Total chunks: 1.
2026-06-21 23:06:01.885  3387-3523  ICC_PROFILE             app.grapheneos.camera.dev            D  stripped in 2.606933ms. orig: 821353, cur: 820739 (614)

But have tested a few different images by injecting in the bytes for testing. Including validating against images no ICC chunk:

2026-06-21 23:31:18.037  4166-4295  ICC_PROFILE             app.grapheneos.camera.dev            E  No ICC_PROFILE APP2 markers found in JPEG.

And against images with multi-chunk ICC profile; sample multi-chunk image: https://cloud.githubusercontent.com/assets/1643413/5495182/985fc656-86e2-11e4-9349-78a0dd9d6b4d.jpg

2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 1/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 2/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 3/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 4/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 5/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 6/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 7/9 (65490 bytes).
2026-06-21 23:49:40.924  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 8/9 (65490 bytes).
2026-06-21 23:49:40.925  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC_PROFILE APP2 chunk 9/9 (33248 bytes).
2026-06-21 23:49:40.926  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  ICC Profile found! Size: 557182 bytes. Total chunks: 9.
2026-06-21 23:49:40.927  5332-5447  ICC_PROFILE             app.grapheneos.camera.dev            D  stripped in 3.383871ms. orig: 580171, cur: 22841 (557330)

Output matches iccJpegDump 985fc656-86e2-11e4-9349-78a0dd9d6b4d.jpg -p /tmp/multi.icc

[INFO] ICC_PROFILE APP2 chunk 1/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 2/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 3/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 4/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 5/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 6/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 7/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 8/9 (65490 bytes).
[INFO] ICC_PROFILE APP2 chunk 9/9 (33248 bytes).
[INFO] ICC profile extracted to: /tmp/multi.icc (557168 bytes, 9 chunk(s))

The images that come out so far with ICC strip enabled have been valid and rendering both on device (gallery, in other apps), and in standard image viewers on desktop once pulled from the device. But I am struggling to find more sample data with ICC profiles from different devices, so my testing is severely limited to just the 9a and a couple images found online.

I have also been validating / mapping out ICC data structure in ImHex, extending the jpeg pattern to parse ICC profile (WIP). Now that I know how to parse ICC properties, there is potential to edit unwanted ICC tags (ei: google strings, timestamps, etc...) whilst leaving the rest of the color profile in-tact for color accuracy. But that is out-of-scope for this PR.

References & Resources:


I understand this is a low priory feature, but at least this PR should get it ~90% of the way. Post processing time was mentioned as a potential concern in the linked issue, but it seems to be not too large impact by my measurements (at least on on the 9a, unsure about older devices) averaging out at an extra 3-4 ms per image.

I could not find documentation on preferred standards / best practices / style guide for contributing. I did my best to follow the existing structure, but let me know any adjustments that need to be made and I will correct it.

0xDE57 and others added 8 commits June 18, 2026 04:04
- just the ui toggle, no functionality
- defaulted to off
- no icon
- probably doesn't need the geo-tag note?
- we can find and parse the ICC profile!
- todo: remove this section of bytes
- remove unused import
- adjust summary
- rename variables for clarity
- move extractIccFromJpeg() into it's own JpegUtils class
- adjust extraction to return a data object containing the start and end position of the APP2 section so the caller can know where to strip bytes.
- function to strip bytes
- remove function summaries for consistency, as they do not seem to be used anywhere else in  the project
- remove dead debug log statements
- removing timing test code
- include chunk count in IccProfile and fix variable name
- minor logic simplification
@0xDE57

0xDE57 commented Jun 23, 2026

Copy link
Copy Markdown
Author

I have also validated that the unwanted exif meta data in my previous comment in the linked issue, was indeed coming from the ICC profile.

ExifTool output now with the "Remove ICC profile data after capture" toggle enabled:

ExifTool Version Number : 13.55

File Name  
Directory  
File Size  
File Modification Date/Time 
File Access Date/Time 
File Inode Change Date/Time
File Permissions
File Type 
File Type Extension
MIME Type
Exif Byte Order 
Orientation  
JFIF Version
Resolution Unit 
X Resolution
Y Resolution
Image Width 
Image Height
Encoding Process
Bits Per Sample 
Color Components  
Y Cb Cr Sub Sampling  
Image Size 
Megapixels     

@thestinger

Copy link
Copy Markdown
Member

ICC profiles are not EXIF metadata. The profile is a standard ICC profile for Pixels in general so it doesn't vary across photos. The output of ExifTool is misleading since it shows all the metadata it can find including filesystem metadata for the currently stored file. It's not all EXIF metadata.

@0xDE57

0xDE57 commented Jun 23, 2026

Copy link
Copy Markdown
Author

Yes, I understand that now. What I mean is the data shown in ExifTool was coming from the ICC profile. Not the exif data. That is what mislead me originally. But I am still validating the output with exiftool.

@0xDE57

0xDE57 commented Jun 23, 2026

Copy link
Copy Markdown
Author

The profile is a standard ICC profile for Pixels in general so it doesn't vary across photos.

Then probably all pixels have have only 1 ICC chunk within a single APP2 section?

I don't have any other pixels to validate on.

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

Successfully merging this pull request may close these issues.

Remove ICC profile data too if EXIF removal is enabled

2 participants