fn main() { let from_hcie = std::fs::read("_images/_psd_stil_test/inner_shadow/black_triangle_green_inner_shadow_normal_blend_from_hcie.psd").unwrap(); let orig = std::fs::read("_images/_psd_stil_test/inner_shadow/black_triangle_green_inner_shadow_normal_blend.psd").unwrap(); println!("ORIG: {} bytes", orig.len()); println!("FROM_HCIE: {} bytes", from_hcie.len()); // Parse both match hcie_psd::Psd::from_bytes(&orig) { Ok(psd) => println!("ORIG: OK, {}x{}, {} layers", psd.width(), psd.height(), psd.layers().len()), Err(e) => println!("ORIG: FAIL: {:?}", e), } match hcie_psd::Psd::from_bytes(&from_hcie) { Ok(psd) => println!("FROM_HCIE: OK, {}x{}, {} layers", psd.width(), psd.height(), psd.layers().len()), Err(e) => println!("FROM_HCIE: FAIL: {:?}", e), } // Compare headers println!("\n=== Header comparison ==="); println!("ORIG: ch={} {}x{} depth={} cmode={}", u16::from_be_bytes([orig[12], orig[13]]), u32::from_be_bytes([orig[14], orig[15], orig[16], orig[17]]), u32::from_be_bytes([orig[18], orig[19], orig[20], orig[21]]), u16::from_be_bytes([orig[22], orig[23]]), u16::from_be_bytes([orig[24], orig[25]])); println!("FROM_HCIE: ch={} {}x{} depth={} cmode={}", u16::from_be_bytes([from_hcie[12], from_hcie[13]]), u32::from_be_bytes([from_hcie[14], from_hcie[15], from_hcie[16], from_hcie[17]]), u32::from_be_bytes([from_hcie[18], from_hcie[19], from_hcie[20], from_hcie[21]]), u16::from_be_bytes([from_hcie[22], from_hcie[23]]), u16::from_be_bytes([from_hcie[24], from_hcie[25]])); // Compare section sizes println!("\n=== Section sizes ==="); for (label, bytes) in [("ORIG", &orig), ("FROM_HCIE", &from_hcie)] { let cmd_len = u32::from_be_bytes([bytes[26], bytes[27], bytes[28], bytes[29]]) as usize; let ir_start = 30 + cmd_len; let ir_len = u32::from_be_bytes([bytes[ir_start], bytes[ir_start+1], bytes[ir_start+2], bytes[ir_start+3]]) as usize; let lmi_start = ir_start + 4 + ir_len; let lmi_len = u32::from_be_bytes([bytes[lmi_start], bytes[lmi_start+1], bytes[lmi_start+2], bytes[lmi_start+3]]) as usize; let mid_start = lmi_start + 4 + lmi_len; let mid_len = bytes.len() - mid_start; println!("{}: cmd={} ir={} lmi={} mid={}", label, cmd_len, ir_len, lmi_len, mid_len); } // Check merged image compression println!("\n=== Merged Image Data ==="); for (label, bytes) in [("ORIG", &orig), ("FROM_HCIE", &from_hcie)] { let cmd_len = u32::from_be_bytes([bytes[26], bytes[27], bytes[28], bytes[29]]) as usize; let ir_start = 30 + cmd_len; let ir_len = u32::from_be_bytes([bytes[ir_start], bytes[ir_start+1], bytes[ir_start+2], bytes[ir_start+3]]) as usize; let lmi_start = ir_start + 4 + ir_len; let lmi_len = u32::from_be_bytes([bytes[lmi_start], bytes[lmi_start+1], bytes[lmi_start+2], bytes[lmi_start+3]]) as usize; let mid_start = lmi_start + 4 + lmi_len; let comp = u16::from_be_bytes([bytes[mid_start], bytes[mid_start+1]]); println!("{}: compression={} first_row_len={}", label, comp, u16::from_be_bytes([bytes[mid_start+2], bytes[mid_start+3]])); } // Check Layer 1 channel data in detail println!("\n=== Layer 1 channel data (from_hcie) ==="); let lmi = get_lmi(&from_hcie); if let Some(lmi) = lmi { let li_len = u32::from_be_bytes([lmi[0], lmi[1], lmi[2], lmi[3]]) as usize; let li = &lmi[4..4+li_len]; let layer_count = i16::from_be_bytes([li[0], li[1]]).unsigned_abs(); let mut pos = 2; for layer_idx in 0..layer_count { let top = i32::from_be_bytes([li[pos], li[pos+1], li[pos+2], li[pos+3]]); let left = i32::from_be_bytes([li[pos+4], li[pos+5], li[pos+6], li[pos+7]]); let bottom = i32::from_be_bytes([li[pos+8], li[pos+9], li[pos+10], li[pos+11]]); let right = i32::from_be_bytes([li[pos+12], li[pos+13], li[pos+14], li[pos+15]]); let ch_count = u16::from_be_bytes([li[pos+16], li[pos+17]]); pos += 18; println!("Layer {}: rect=({},{},{},{}) channels={}", layer_idx, top, left, bottom, right, ch_count); for ch_idx in 0..ch_count { let ch_id = i16::from_be_bytes([li[pos], li[pos+1]]); let ch_len = u32::from_be_bytes([li[pos+2], li[pos+3], li[pos+4], li[pos+5]]); let crop_w = (right - left) as u32; let crop_h = (bottom - top) as u32; let expected_rows = crop_h; println!(" ch {}: id={} len={} (expected ~{} for {}x{})", ch_idx, ch_id, ch_len, expected_rows * 2 + crop_h as u32 * 2, crop_w, crop_h); pos += 6; } pos += 12; // blend mode etc let extra_len = u32::from_be_bytes([li[pos], li[pos+1], li[pos+2], li[pos+3]]) as usize; pos += 4 + extra_len; } } } fn get_lmi(bytes: &[u8]) -> Option<&[u8]> { let cmd_len = u32::from_be_bytes([bytes[26], bytes[27], bytes[28], bytes[29]]) as usize; let ir_start = 30 + cmd_len; let ir_len = u32::from_be_bytes([bytes[ir_start], bytes[ir_start+1], bytes[ir_start+2], bytes[ir_start+3]]) as usize; let lmi_start = ir_start + 4 + ir_len; let lmi_len = u32::from_be_bytes([bytes[lmi_start], bytes[lmi_start+1], bytes[lmi_start+2], bytes[lmi_start+3]]) as usize; Some(&bytes[lmi_start+4..lmi_start+4+lmi_len]) }