Status Update
Comments
ap...@google.com <ap...@google.com> #2
Project: platform/frameworks/support
Branch: androidx-main
Author: Louis Pullen-Freilich <
Link:
Adds OverscrollEffect#withoutDrawing and OverscrollEffect#withoutEventHandling
Expand for full commit details
Adds OverscrollEffect#withoutDrawing and OverscrollEffect#withoutEventHandling
These APIs allow overscroll to have events dispatched to it by one component, and rendered in a separate component.
Fixes: b/266550551
Fixes: b/204650733
Fixes: b/255554340
Fixes: b/229537244
Test: OverscrollTest
Relnote: "Adds OverscrollEffect#withoutDrawing and OverscrollEffect#withoutEventHandling APIs - these APIs create a wrapped instance of the provided overscroll effect that doesn't draw / handle events respectively, which allows for rendering overscroll in a separate component from the component that is dispatching events. For example, disabling drawing the overscroll inside a lazy list, and then drawing the overscroll separately on top / elsewhere."
Change-Id: Idbb3d91546b49c1987a041f959bce4b2b09a9f61
Files:
- M
compose/foundation/foundation/api/current.txt
- M
compose/foundation/foundation/api/restricted_current.txt
- M
compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/OverscrollDemo.kt
- M
compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/OverscrollSample.kt
- M
compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/OverscrollTest.kt
- M
compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Overscroll.kt
Hash: f64e25b7a473c757d080521e7dd97b3f6670f60d
Date: Fri Nov 01 18:43:56 2024
ib...@google.com <ib...@google.com> #3
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.compose.foundation:foundation:1.8.0-alpha06
androidx.compose.foundation:foundation-android:1.8.0-alpha06
androidx.compose.foundation:foundation-jvmstubs:1.8.0-alpha06
androidx.compose.foundation:foundation-linuxx64stubs:1.8.0-alpha06
ib...@google.com <ib...@google.com> #4
The size of the JPEG APP1
segment looks wrong in the edited file (from exiftool
):
JPEG APP1 (46 bytes):
Compared to the original file:
JPEG APP1 (65279 bytes):
In binary this difference is visible in the 5th/6th byte of each file (from hexdump -C
). The first 4 bytes are a JPEG marker (0xFF
), a JPEG SOI (start of image, 0xd8
), another marker and an APP1 (0xe1
), followed by 2 bytes indicating the size of the APP1 segment.
Edited image:
ff d8 ff e1 00 30
Original image:
ff d8 ff e1 ff 01
Looking into why ExifInterface
is writing out the wrong APP1 size, I turned on
$ adb shell setprop log.tag.ExifInterface VERBOSE
And now it becomes a bit more obvious (this logging is from
saveJpegAttributes starting with (inputStream: java.io.BufferedInputStream@4fba9e8, outputStream: java.io.BufferedOutputStream@e5c3801)
index: 0, offsets: 8, tag count: 15, data sizes: 81, total size: 65584
65584
(0x10030
) is greater than the max 16-bit unsigned value (2^16 = 65536
), so when we ByteOrderedDataOutputStream.writeUnsignedShort
writeShort((short) val)
) truncates to the lower two bytes (0x0030
) - and this gets written out to the file and then breaks everything.
I think this likely only affects files that are very close to the 2^16
threshold, and the act of 'copying' all the EXIF attributes over probably reformats some of them just enough to take up slightly more bytes.
I'm not sure what is supposed to happen when a JPEG APP1 segment gets larger than 2^16
bytes, I need to dig a bit further into that part.
ib...@google.com <ib...@google.com> #5
Actually thinking about it more, it's not obvious to me why the APP1
segment of the original image is so large either - looking in exiftool
it doesn't seem to contain any particularly enormous fields, so I can't really see where 65kB comes from.
ib...@google.com <ib...@google.com> #6
re APP1
segment is so large, I missed the thumbnail the first time, which takes up a significant chunk (64kB):
+ [IFD1 directory with 15 entries]
| 0) ImageHeight = 384
| - Tag 0x0101 (4 bytes, int32u[1]):
| 0323: 80 01 00 00 [....]
| 1) Orientation = 6
| - Tag 0x0112 (2 bytes, int16u[1]):
| 032f: 06 00 [..]
| Warning = Tag ID 0x0103 Compression out of sequence in IFD1
| 2) Compression = 6
| - Tag 0x0103 (2 bytes, int16u[1]):
| 033b: 06 00 [..]
| 3) ThumbnailOffset = 1273
| - Tag 0x0201 (4 bytes, int32u[1]):
| 0347: f9 04 00 00 [....]
| 4) ThumbnailLength = 64000
| - Tag 0x0202 (4 bytes, int32u[1]):
| 0353: 00 fa 00 00 [....]
| Warning = Tag ID 0x010f Make out of sequence in IFD1
ib...@google.com <ib...@google.com> #7
APP1
:
Exif metadata are restricted in size to 64 kB in JPEG images because according to the specification this information must be contained within a single JPEG APP1 segment.
Charcoal: Do you know if CameraX is deciding how large to make the thumbnail in this case, or is this happening lower down in the device? Taking up 64,000 bytes doesn't leave much space for the rest of the Exif data.
Related thread I found (also complaining about a Samsung device, but from 2013...):
I experimented to see what exiftool
does now when the APP1
segment gets too large, and it looks like they just add a second APP1
segment and call it 'multi-segment EXIF` (I have no idea how well supported this is):
$ exiftool -UserComment="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" b-263747161_original.jpg
Warning: [minor] File contains multi-segment EXIF - b-263747161_original.jpg
1 image files updated
$ exiftool -v3 b-263747161_original.jpg
ExifToolVersion = 12.52
FileName = b-263747161_original.jpg
Directory = .
FileSize = 434075
FileModifyDate = 1678121141
FileAccessDate = 1678121141
FileInodeChangeDate = 1678121141
FilePermissions = 33184
FileType = JPEG
FileTypeExtension = JPG
MIMEType = image/jpeg
JPEG APP1 (65533 bytes):
0006: 45 78 69 66 00 00 49 49 2a 00 08 00 00 00 0d 00 [Exif..II*.......]
0016: 00 01 04 00 01 00 00 00 a0 05 00 00 01 01 04 00 [................]
0026: 01 00 00 00 38 04 00 00 0e 01 02 00 01 00 00 00 [....8...........]
0036: 00 00 00 00 0f 01 02 00 08 00 00 00 aa 00 00 00 [................]
0046: 10 01 02 00 09 00 00 00 b2 00 00 00 12 01 03 00 [................]
0056: 01 00 00 00 06 00 00 00 1a 01 05 00 01 00 00 00 [................]
0066: bc 00 00 00 1b 01 05 00 01 00 00 00 c4 00 00 00 [................]
[snip 65421 bytes]
Warning = [minor] File contains multi-segment EXIF
JPEG APP1 (71 bytes):
10007: 45 78 69 66 00 00 00 00 00 00 00 00 00 00 00 00 [Exif............]
10017: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
10027: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
10037: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
10047: 00 00 00 00 00 00 00 [.......]
ExifByteOrder = II
Obviously the current ExifInterface
behaviour is very problematic (corrupting the image completely), but I'm not actually sure the best way to improve it. Some options I came up with:
- If the size of the
APP1
segment is larger than2^16
then just write the first2^16
bytes and hope. - Implement the same 'split segment' support that
exiftool
has. - Add logic to
ExifInterface
to resize a thumbnail to free up space in theAPP1
segment if it runs out (this seems too magical and could be very confusing for users). - Refuse to save a file in
ExifInterface.saveAttributes
if it results inAPP1
being larger than2^16
, either by silently not writing out (confusing) or throwing an exception (disruptive). - Add prioritisation of Exif tags, so when we run out of space we drop tags lowest-priority-first (very unlikely we can predict the 'correct' prioritisation such that users aren't annoyed/confused by the tags we decide to drop).
ch...@google.com <ch...@google.com> #8
Hi Ian,
Thanks for looking into the issue and provide the detailed analysis result.
About the question: Charcoal: Do you know if CameraX is deciding how large to make the thumbnail in this case, or is this happening lower down in the device? Taking up 64,000 bytes doesn't leave much space for the rest of the Exif data.
CameraX doesn't specify any thumbnail related capture request settings (
I'm curious about why this issue only happens when setting a FUSED location data but does not happen when setting a GPS location data? Does the FUSED location data in Exif actually occupy a little bit more size than GPS location data? So it causes the different result?
ib...@google.com <ib...@google.com> #9
I'm curious about why this issue only happens when setting a FUSED location data but does not happen when setting a GPS location data? Does the FUSED location data in Exif actually occupy a little bit more size than GPS location data? So it causes the different result?
Good question - I actually only got as far as playing with the image provided inside MyApplication-ExifLocationIssue.zip
, I didn't look at CameraXBasic-WriteFusedLocation.zip
, and as you noted in
ib...@google.com <ib...@google.com> #10
I've decided to go with option 4 from saveAttributes
in order to avoid creating a corrupted image. I've filed a new issue to track the possibility of adding multi-segment support in the future:
ap...@google.com <ap...@google.com> #11
Branch: androidx-main
commit c6bbc03f39f811ac546882880be46380cb31f5d5
Author: Ian Baker <ibaker@google.com>
Date: Tue Mar 07 11:09:08 2023
Throw an exception if trying to write a JPEG APP1 segment that's too large
jpeg_with_full_app_segment.jpg is an image taken with a Samsung A32
with a nearly-full APP1 segment due to a 64,000 byte thumbnail:
$ exiftool -v3 jpeg_with_exif_full_app1_segment.jpg
<snip>
JPEG APP1 (65072 bytes):
<snip>
| 5) ThumbnailLength = 64000
Bug: 263747161
Test: ./gradlew :exifinterface:exifinterface:connectedAndroidTest
Change-Id: Id421cd36d974ad4f29a2c6d6c730d99d8986d917
M exifinterface/exifinterface/build.gradle
M exifinterface/exifinterface/src/androidTest/java/androidx/exifinterface/media/ExifInterfaceTest.java
A exifinterface/exifinterface/src/androidTest/res/raw/jpeg_with_exif_full_app1_segment.jpg
M exifinterface/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java
ib...@google.com <ib...@google.com>
mw...@gmail.com <mw...@gmail.com> #12
Are you sure it's an issue with the APP1 segment being too large with the FUSED location? I was thinking perhaps there's some issue with the length calculation that's happening as we were able to fix these images by just detecting the start of the jpeg image data and re-writing the length field based on that detection.
ib...@google.com <ib...@google.com> #13
Are you sure it's an issue with the APP1 segment being too large with the FUSED location? I was thinking perhaps there's some issue with the length calculation that's happening as we were able to fix these images by just detecting the start of the jpeg image data and re-writing the length field based on that detection.
This fix is consistent with the current failure mode of ExifInterface
when the APP1
segment gets 'too large' (before my change linked above in 0x10030
bytes to write to the APP1 segment, and ExifInterface
does two things:
- When writing the length of the APP1 segment it truncates this to
0x0030
- It writes all those
0x10030
bytes out, and then it writes the rest of the image.
A JPEG parser (I assume) comes along and reads the length of the APP1
segment (0x30
) and skips that many bytes, then expects to find JPEG data - but it's actually in the middle of the Exif and so it fails.
If you manually find the start of the JPEG data then you obviate both of the problems - and the image is 'fixed'.
na...@google.com <na...@google.com> #14
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.exifinterface:exifinterface:1.3.7
na...@google.com <na...@google.com> #15
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.exifinterface:exifinterface:1.4.0-alpha01
Description
Component used: Version used: Devices/Android versions reproduced on: Samsung A32 (sm-a325f) Android 12 (also A12/A13 mentioned in b/263289024 )
When reporting bugs, please always include:
Where possible, please also provide: