// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
fn png_iccp_valid(data : Bytes) -> Bool {
let mut separator : Int? = None
for index in 0..
index > 0 &&
index <= 79 &&
index + 2 < data.length() &&
data[index + 1] == b'\x00'
None => false
}
}
///|
fn png_bit_depth_valid(bit_depth : Int, color_type : Int) -> Bool {
match color_type {
0 =>
bit_depth == 1 ||
bit_depth == 2 ||
bit_depth == 4 ||
bit_depth == 8 ||
bit_depth == 16
2 | 4 | 6 => bit_depth == 8 || bit_depth == 16
3 => bit_depth == 1 || bit_depth == 2 || bit_depth == 4 || bit_depth == 8
_ => false
}
}
///|
fn png_chromaticities_are_srgb(data : Bytes) -> Bool {
let srgb : FixedArray[UInt] = [
31270U, 32900U, 64000U, 33000U, 30000U, 60000U, 15000U, 6000U,
]
for index in 0.. RasterColorMetadata raise DecodeError {
let chunks = parse_chunks(raw)
if chunks.is_empty() {
raise MissingChunk("IHDR")
}
guard chunks[0] is { chunk_type: "IHDR", data } else {
raise MissingChunk("IHDR must be first chunk")
}
if data.length() != 13 {
raise CorruptData("IHDR must contain exactly 13 bytes")
}
let width = read_i32be(data, 0)
let height = read_i32be(data, 4)
if width <= 0 || height <= 0 {
raise CorruptData("invalid dimensions")
}
let bit_depth = data[8].to_int()
let color_type = data[9].to_int()
if !png_bit_depth_valid(bit_depth, color_type) {
raise CorruptData("invalid PNG bit depth or color type")
}
if data[10] != b'\x00' || data[11] != b'\x00' {
raise CorruptData("invalid PNG compression or filter method")
}
if data[12] != b'\x00' && data[12] != b'\x01' {
raise CorruptData("invalid PNG interlace method")
}
let mut profile_reason : String? = None
let mut hdr_reason : String? = if bit_depth > 8 {
Some("png_\{bit_depth}_bit_samples")
} else {
None
}
for chunk in chunks {
match chunk.chunk_type {
"sRGB" =>
if chunk.data.length() != 1 || chunk.data[0].to_int() > 3 {
raise CorruptData("invalid PNG sRGB chunk")
}
"iCCP" => {
if !png_iccp_valid(chunk.data) {
raise CorruptData("invalid PNG iCCP chunk")
}
if profile_reason is None {
profile_reason = Some("png_iCCP")
}
}
"gAMA" => {
if chunk.data.length() != 4 || read_u32be(chunk.data, 0) == 0U {
raise CorruptData("invalid PNG gAMA chunk")
}
if read_u32be(chunk.data, 0) != 45455U && profile_reason is None {
profile_reason = Some("png_gAMA")
}
}
"cHRM" => {
if chunk.data.length() != 32 {
raise CorruptData("invalid PNG cHRM chunk")
}
if !png_chromaticities_are_srgb(chunk.data) && profile_reason is None {
profile_reason = Some("png_cHRM")
}
}
"cICP" => {
if chunk.data.length() != 4 {
raise CorruptData("invalid PNG cICP chunk")
}
let transfer = chunk.data[1].to_int()
if transfer == 16 || transfer == 18 {
if hdr_reason is None {
hdr_reason = Some("png_cICP_hdr")
}
} else if profile_reason is None {
profile_reason = Some("png_cICP")
}
}
"mDCv" => {
if chunk.data.length() != 24 {
raise CorruptData("invalid PNG mDCv chunk")
}
if hdr_reason is None {
hdr_reason = Some("png_mDCv")
}
}
"cLLi" => {
if chunk.data.length() != 8 {
raise CorruptData("invalid PNG cLLi chunk")
}
if hdr_reason is None {
hdr_reason = Some("png_cLLi")
}
}
_ => ()
}
}
let condition = match hdr_reason {
Some(reason) => HdrOrHighBitDepth(reason)
None =>
match profile_reason {
Some(reason) => EmbeddedColorProfile(reason)
_ => SrgbCompatible
}
}
{ width, height, condition }
}
///|
fn jpeg_segment_has_icc_profile(
data : Bytes,
payload_start : Int,
payload_end : Int,
) -> Bool raise DecodeError {
let signature : FixedArray[Byte] = [
b'I', b'C', b'C', b'_', b'P', b'R', b'O', b'F', b'I', b'L', b'E', b'\x00',
]
if payload_end - payload_start < signature.length() {
return false
}
for index in 0.. Bool {
marker == 0xC0 ||
marker == 0xC1 ||
marker == 0xC2 ||
marker == 0xC3 ||
marker == 0xC5 ||
marker == 0xC6 ||
marker == 0xC7 ||
marker == 0xC9 ||
marker == 0xCA ||
marker == 0xCB ||
marker == 0xCD ||
marker == 0xCE ||
marker == 0xCF
}
///|
pub fn inspect_jpeg_color_metadata(
data : Bytes,
) -> RasterColorMetadata raise DecodeError {
if data.length() < 2 || data[0].to_int() != 0xFF || data[1].to_int() != 0xD8 {
raise InvalidSignature("not a JPEG file")
}
let mut position = 2
let mut width : Int? = None
let mut height : Int? = None
let mut precision : Int? = None
let mut embedded_icc = false
while position + 1 < data.length() {
if data[position].to_int() != 0xFF {
position += 1
continue
}
let marker = data[position + 1].to_int()
position += 2
if marker == 0xD9 {
break
}
if marker == 0x00 || marker == 0xFF {
continue
}
if (marker >= 0xD0 && marker <= 0xD7) || marker == 0x01 {
continue
}
if position + 1 >= data.length() {
raise CorruptData("truncated JPEG segment length")
}
let segment_length = read_u16be_at(data, position)
if segment_length < 2 || segment_length > data.length() - position {
raise CorruptData("invalid JPEG segment length")
}
let segment_end = position + segment_length
if marker == 0xE2 &&
jpeg_segment_has_icc_profile(data, position + 2, segment_end) {
embedded_icc = true
}
if jpeg_start_of_frame_marker(marker) {
if segment_length < 8 {
raise CorruptData("truncated JPEG start-of-frame segment")
}
precision = Some(data[position + 2].to_int())
height = Some(read_u16be_at(data, position + 3))
width = Some(read_u16be_at(data, position + 5))
if width == Some(0) || height == Some(0) {
raise CorruptData("invalid JPEG dimensions")
}
}
position = segment_end
}
guard width is Some(image_width) else {
raise MissingChunk("JPEG start-of-frame marker")
}
guard height is Some(image_height) else {
raise MissingChunk("JPEG start-of-frame marker")
}
let condition = match precision {
Some(value) if value > 8 => HdrOrHighBitDepth("jpeg_\{value}_bit_samples")
_ if embedded_icc => EmbeddedColorProfile("jpeg_icc_app2")
_ => SrgbCompatible
}
{ width: image_width, height: image_height, condition }
}