@@ -4,22 +4,13 @@ import android.util.Log
44import java.io.ByteArrayOutputStream
55
66
7- /* *
8- * Data class to hold the extracted ICC profile information.
9- */
107data class IccProfile (
11- val start : Int , // Start index of the APP2 section containing the ICC profile
12- val end : Int , // End index of the APP2 section containing the ICC profile
13- // The full ICC profile bytes segment [signature + header + data] (this will be smaller than the total APP2 section)
8+ val app2SectionStart : Int , // Start index of the APP2 section containing the ICC profile
9+ val app2SectionLength : Int , // Length of the entire APP2 section containing the ICC profile
10+ val iccChunks : Int ,
1411 val iccBytes : ByteArray
1512)
1613
17- /* *
18- * Extracts the ICC profile from a JPEG byte array.
19- * Based off iccDEV -> iccJpegDump
20- * @param jpegBytes The JPEG file contents.
21- * @return The ICC profile bytes, or null if none was found.
22- */
2314fun extractIccFromJpeg (jpegBytes : ByteArray ): IccProfile ? {
2415 val tag = " ICC_PROFILE"
2516
@@ -55,7 +46,6 @@ fun extractIccFromJpeg(jpegBytes: ByteArray): IccProfile? {
5546 while (pos < jpegBytes.size && jpegBytes[pos] == 0xFF .toByte()) pos++
5647 if (pos >= jpegBytes.size) break
5748
58- // Log.d(tag, "marker - %d: %02x %02x".format(markerPos, jpegBytes[markerPos].toInt() and 0xFF, jpegBytes[markerPos+1].toInt() and 0xFF))
5949 val marker = jpegBytes[pos].toInt() and 0xFF
6050 pos++ // move past the marker code
6151
@@ -79,7 +69,6 @@ fun extractIccFromJpeg(jpegBytes: ByteArray): IccProfile? {
7969 // Handle APP2 segments that may contain ICC data
8070 if (marker == 0xE2 && payloadLength >= 14 ) {
8171 if (jpegBytes.copyOfRange(segStart, segStart + 12 ).contentEquals(iccSig)) {
82- // Log.d(tag, "sig found @ $segStart. starting pos $magicPos. Payload length $payloadLength bytes")
8372 val seq = jpegBytes[segStart + 12 ].toInt() and 0xFF
8473 val total = jpegBytes[segStart + 13 ].toInt() and 0xFF
8574
@@ -107,20 +96,12 @@ fun extractIccFromJpeg(jpegBytes: ByteArray): IccProfile? {
10796 if (magicPos < minStart) minStart = magicPos
10897 if (chunkEnd > maxEnd) maxEnd = chunkEnd
10998
110- // Include header in the returned bytes,
111- // store the FULL segment (signature + header + data) for the first chunk,
112- // and only the data for subsequent chunks.
113- val chunkData = if (seq == 1 ) {
114- jpegBytes.copyOfRange(segStart, segStart + payloadLength)
115- } else {
116- jpegBytes.copyOfRange(segStart + 14 , segStart + payloadLength)
117- }
118-
99+ // store payload (excluding the 12‑byte signature + 2‑byte header)
100+ val chunkData = jpegBytes.copyOfRange(segStart + 14 , segStart + payloadLength)
119101 chunks[seq - 1 ] = chunkData
120102 seenChunks[seq - 1 ] = true
121103
122- val chunkSize = if (seq == 1 ) payloadLength - 14 else payloadLength // exclude header on first section
123- Log .d(tag, " ICC_PROFILE APP2 chunk ${seq} /${total} (${chunkSize} bytes). found at [$segStart -$chunkEnd ]. (${chunkEnd- segStart} bytes)" )
104+ Log .d(tag, " ICC_PROFILE APP2 chunk ${seq} /${total} (${payloadLength- 14 } bytes)." )
124105 }
125106 }
126107
@@ -146,29 +127,11 @@ fun extractIccFromJpeg(jpegBytes: ByteArray): IccProfile? {
146127 }
147128 val iccBytes = iccStream.toByteArray()
148129
149- // debug output
150- /*
151- Log.d(tag, "--- ICC Profile Extraction Complete ---")
152- Log.d(tag, "Start Index: $minStart")
153- Log.d(tag, "End Index: $maxEnd")
154- Log.d(tag, "Total APP2 size: ${maxEnd - minStart}")
155- Log.d(tag, "ICC Size: ${iccBytes.size} bytes") //including header
156- val preview = iccBytes.joinToString(" ") { "%02X".format(it) }
157- Log.d(tag, "Data Preview: $preview...")
158- Log.d(tag, "---------------------------------------")*/
159130 Log .d(tag, " ICC Profile found! Size: ${iccBytes.size} bytes. Total chunks: ${totalChunks} ." )
160131
161- return IccProfile (minStart, maxEnd - minStart, iccBytes)
132+ return IccProfile (minStart, maxEnd - minStart, totalChunks, iccBytes)
162133}
163134
164- /* *
165- * Returns a new ByteArray with the specified section removed.
166- *
167- * @param original The source byte array.
168- * @param start The starting index of the section to remove.
169- * @param length The number of bytes to remove.
170- * @return A new ByteArray containing the remaining bytes.
171- */
172135fun stripBytes (original : ByteArray , start : Int , length : Int ): ByteArray {
173136 if (length <= 0 ) return original.copyOf()
174137
@@ -178,10 +141,6 @@ fun stripBytes(original: ByteArray, start: Int, length: Int): ByteArray {
178141 " Strip range ($start to ${start + length} ) exceeds array size (${original.size} )"
179142 }
180143
181- /*
182- Log.d("ICC strip","start - %d: %02x".format(start, original[start].toInt() and 0xFF))
183- Log.d("ICC strip","end - %d: %02x".format(start+length, original[start+length].toInt() and 0xFF))
184- Log.d("ICC strip","length - $length:")*/
185144 val newSize = original.size - length
186145 val result = ByteArray (newSize)
187146
0 commit comments