1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
// 纯 MoonBit PSD 解码器
// 支持 8-bit RGB(channelCount=3)/ RGBA(channelCount=4)、无压缩(compression=0)
// 大端序字节流,按通道排列像素数据交错为 RGBRGBRGB
// 规范: Adobe Photoshop PSD File Format + stb_image.h:6126-6280 stbi__psd_load

///|
/// 解码 PSD 字节流为 Image
/// 支持 8-bit RGB(channelCount=3)/ RGBA(channelCount=4)、无压缩(compression=0)
/// Header(26 字节) + Color mode data + Image resources + Layer and mask data + Image data
/// 像素数据按通道排列(RRRGGGBBB),交错为 Image.data 格式(RGBRGBRGB)
pub fn decode_psd_pure(data : Bytes) -> @types.Image raise @types.LoadError {
  let len = data.length()
  // Header 26 字节
  if len < 26 {
    raise @types.LoadError::DecodeFailed(
      "PSD 数据过短:无法读取完整 header",
    )
  }
  // signature "8BPS" (0x38 0x42 0x50 0x53)
  if data[0].to_int() != 0x38 ||
    data[1].to_int() != 0x42 ||
    data[2].to_int() != 0x50 ||
    data[3].to_int() != 0x53 {
    raise @types.LoadError::DecodeFailed("PSD signature 错误,非 \"8BPS\"")
  }
  // version (2 字节 BE),必须为 1
  let version = read_u16_be(data, 4)
  if version != 1 {
    raise @types.LoadError::DecodeFailed("PSD version 错误,仅支持 1")
  }
  // reserved(6 字节) 跳过
  // channelCount (2 字节 BE)
  let channel_count = read_u16_be(data, 12)
  if channel_count != 3 && channel_count != 4 {
    raise @types.LoadError::DecodeFailed(
      "不支持的 PSD channelCount,仅支持 3(RGB)和 4(RGBA)",
    )
  }
  // h (4 字节 BE)
  let h = read_u32_be(data, 14)
  // w (4 字节 BE)
  let w = read_u32_be(data, 18)
  // bitdepth (2 字节 BE),仅支持 8
  let bitdepth = read_u16_be(data, 22)
  if bitdepth != 8 {
    raise @types.LoadError::DecodeFailed(
      "不支持的 PSD bitdepth,仅支持 8",
    )
  }
  // colorMode (2 字节 BE),仅支持 3(RGB)
  let color_mode = read_u16_be(data, 24)
  if color_mode != 3 {
    raise @types.LoadError::DecodeFailed(
      "不支持的 PSD colorMode,仅支持 3(RGB)",
    )
  }
  // 尺寸校验
  if w == 0 || h == 0 {
    raise @types.LoadError::DecodeFailed("PSD 尺寸无效")
  }
  // 跳过 3 个 length 前缀段(color mode data / image resources / layer and mask data)
  let mut pos = 26
  for _ in 0..<3 {
    if pos + 4 > len {
      raise @types.LoadError::DecodeFailed(
        "PSD 数据过短:无法读取 4 字节 BE",
      )
    }
    let seg_len = read_u32_be(data, pos)
    pos += 4
    if pos + seg_len > len {
      raise @types.LoadError::DecodeFailed("PSD 段数据越界")
    }
    pos += seg_len
  }
  // Image data: compression (2 字节 BE)
  if pos + 2 > len {
    raise @types.LoadError::DecodeFailed(
      "PSD 数据过短:无法读取 2 字节 BE",
    )
  }
  let compression = read_u16_be(data, pos)
  pos += 2
  if compression != 0 {
    raise @types.LoadError::DecodeFailed(
      "不支持的 PSD compression,仅支持 0(无压缩)",
    )
  }
  // 像素数据:按通道排列,每通道 w*h 字节
  let pixel_count = w * h
  let pixel_bytes = channel_count * pixel_count
  if pos + pixel_bytes > len {
    raise @types.LoadError::DecodeFailed("PSD 像素数据不足")
  }
  // 交错:data[i * channel_count + c] = raw[c * w * h + i]
  let interleaved : Array[Byte] = Array::make(pixel_bytes, b'\x00')
  for c in 0..<channel_count {
    let channel_base = c * pixel_count
    for i in 0..<pixel_count {
      interleaved[i * channel_count + c] = data[pos + channel_base + i]
    }
  }
  @types.Image::{
    width: w,
    height: h,
    channels: channel_count,
    data: Bytes::from_array(interleaved),
  }
}