1use crate::psd::ReadOptions;
48
49#[derive(Debug, Clone, PartialEq, Eq)]
51pub enum ReadError {
52 UnexpectedEndOfBuffer,
55 ReadingPastEndOfFile,
57 InvalidSignature { signature: String, offset: usize },
59 SizeTooLarge,
61 SectionExceedsFileSize,
63 StrictViolation(String),
65}
66
67impl std::fmt::Display for ReadError {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 match self {
70 ReadError::UnexpectedEndOfBuffer => write!(f, "Reading bytes exceeding buffer length"),
71 ReadError::ReadingPastEndOfFile => write!(f, "Reading past end of file"),
72 ReadError::InvalidSignature { signature, offset } => {
73 write!(f, "Invalid signature: '{}' at 0x{:x}", signature, offset)
74 }
75 ReadError::SizeTooLarge => write!(f, "Sizes larger than 4GB are not supported"),
76 ReadError::SectionExceedsFileSize => write!(f, "Section exceeds file size"),
77 ReadError::StrictViolation(msg) => write!(f, "{}", msg),
78 }
79 }
80}
81
82impl std::error::Error for ReadError {}
83
84pub type ReadResult<T> = Result<T, ReadError>;
86
87#[derive(Debug)]
103pub struct PsdReader<'a> {
104 pub buffer: &'a [u8],
105 pub offset: usize,
106 pub strict: bool,
108 pub debug: bool,
109 pub large: bool,
110 pub global_alpha: bool,
111 pub options: ReadOptions,
112}
113
114impl<'a> PsdReader<'a> {
115 pub fn new(buffer: &'a [u8], offset: Option<usize>, length: Option<usize>) -> PsdReader<'a> {
122 let start = offset.unwrap_or(0);
123 let end = match length {
124 Some(len) => start + len,
125 None => buffer.len(),
126 };
127 PsdReader {
128 buffer: &buffer[start..end],
129 offset: 0,
130 strict: false,
131 debug: false,
132 large: false,
133 global_alpha: false,
134 options: ReadOptions::default(),
135 }
136 }
137}
138
139pub fn warn_or_throw(reader: &PsdReader, message: &str) -> ReadResult<()> {
145 if reader.strict {
146 return Err(ReadError::StrictViolation(message.to_string()));
147 }
148 Ok(())
150}
151
152#[inline]
157fn ensure(reader: &PsdReader, len: usize) -> ReadResult<usize> {
158 let start = reader.offset;
159 if start + len > reader.buffer.len() {
160 return Err(ReadError::UnexpectedEndOfBuffer);
161 }
162 Ok(start)
163}
164
165pub fn read_uint8(reader: &mut PsdReader) -> ReadResult<u8> {
166 let start = ensure(reader, 1)?;
167 reader.offset += 1;
168 Ok(reader.buffer[start])
169}
170
171pub fn peek_uint8(reader: &PsdReader) -> ReadResult<u8> {
173 let start = ensure(reader, 1)?;
174 Ok(reader.buffer[start])
175}
176
177pub fn read_int8(reader: &mut PsdReader) -> ReadResult<i8> {
180 Ok(read_uint8(reader)? as i8)
181}
182
183pub fn read_int16(reader: &mut PsdReader) -> ReadResult<i16> {
184 let start = ensure(reader, 2)?;
185 reader.offset += 2;
186 Ok(i16::from_be_bytes([reader.buffer[start], reader.buffer[start + 1]]))
187}
188
189pub fn read_uint16(reader: &mut PsdReader) -> ReadResult<u16> {
190 let start = ensure(reader, 2)?;
191 reader.offset += 2;
192 Ok(u16::from_be_bytes([reader.buffer[start], reader.buffer[start + 1]]))
193}
194
195pub fn read_uint16_le(reader: &mut PsdReader) -> ReadResult<u16> {
197 let start = ensure(reader, 2)?;
198 reader.offset += 2;
199 Ok(u16::from_le_bytes([reader.buffer[start], reader.buffer[start + 1]]))
200}
201
202pub fn read_int32(reader: &mut PsdReader) -> ReadResult<i32> {
203 let start = ensure(reader, 4)?;
204 reader.offset += 4;
205 Ok(i32::from_be_bytes([
206 reader.buffer[start],
207 reader.buffer[start + 1],
208 reader.buffer[start + 2],
209 reader.buffer[start + 3],
210 ]))
211}
212
213pub fn read_int32_le(reader: &mut PsdReader) -> ReadResult<i32> {
215 let start = ensure(reader, 4)?;
216 reader.offset += 4;
217 Ok(i32::from_le_bytes([
218 reader.buffer[start],
219 reader.buffer[start + 1],
220 reader.buffer[start + 2],
221 reader.buffer[start + 3],
222 ]))
223}
224
225pub fn read_uint32(reader: &mut PsdReader) -> ReadResult<u32> {
226 let start = ensure(reader, 4)?;
227 reader.offset += 4;
228 Ok(u32::from_be_bytes([
229 reader.buffer[start],
230 reader.buffer[start + 1],
231 reader.buffer[start + 2],
232 reader.buffer[start + 3],
233 ]))
234}
235
236pub fn read_float32(reader: &mut PsdReader) -> ReadResult<f32> {
237 let start = ensure(reader, 4)?;
238 reader.offset += 4;
239 Ok(f32::from_be_bytes([
240 reader.buffer[start],
241 reader.buffer[start + 1],
242 reader.buffer[start + 2],
243 reader.buffer[start + 3],
244 ]))
245}
246
247pub fn read_float64(reader: &mut PsdReader) -> ReadResult<f64> {
248 let start = ensure(reader, 8)?;
249 reader.offset += 8;
250 Ok(f64::from_be_bytes([
251 reader.buffer[start],
252 reader.buffer[start + 1],
253 reader.buffer[start + 2],
254 reader.buffer[start + 3],
255 reader.buffer[start + 4],
256 reader.buffer[start + 5],
257 reader.buffer[start + 6],
258 reader.buffer[start + 7],
259 ]))
260}
261
262pub fn read_fixed_point32(reader: &mut PsdReader) -> ReadResult<f64> {
264 Ok(read_int32(reader)? as f64 / (1i64 << 16) as f64)
265}
266
267pub fn read_fixed_point_path32(reader: &mut PsdReader) -> ReadResult<f64> {
269 Ok(read_int32(reader)? as f64 / (1i64 << 24) as f64)
270}
271
272pub fn read_bytes(reader: &mut PsdReader, length: usize) -> ReadResult<Vec<u8>> {
283 let start = reader.offset;
284 reader.offset += length;
285
286 if start + length > reader.buffer.len() {
287 warn_or_throw(reader, "Reading bytes exceeding buffer length")?;
289 if length > 100 * 1024 * 1024 {
290 return Err(ReadError::ReadingPastEndOfFile);
291 }
292 let mut result = vec![0u8; length];
293 let avail = reader.buffer.len().saturating_sub(start);
294 let len = length.min(avail);
295 if len > 0 {
296 result[..len].copy_from_slice(&reader.buffer[start..start + len]);
297 }
298 Ok(result)
299 } else {
300 Ok(reader.buffer[start..start + length].to_vec())
301 }
302}
303
304pub fn read_bytes_slice<'a>(reader: &mut PsdReader<'a>, length: usize) -> ReadResult<&'a [u8]> {
310 let start = ensure(reader, length)?;
311 reader.offset += length;
312 Ok(&reader.buffer[start..start + length])
313}
314
315pub fn skip_bytes(reader: &mut PsdReader, count: usize) {
317 reader.offset += count;
318}
319
320pub fn read_short_string(reader: &mut PsdReader, length: usize) -> ReadResult<String> {
330 let buffer = read_bytes(reader, length)?;
331 let mut result = String::with_capacity(buffer.len());
332 for &b in &buffer {
333 result.push(b as char); }
335 Ok(result)
336}
337
338pub fn read_ascii_string(reader: &mut PsdReader, length: usize) -> ReadResult<String> {
340 let mut result = String::with_capacity(length);
341 for _ in 0..length {
342 result.push(read_uint8(reader)? as char);
343 }
344 Ok(result)
345}
346
347pub fn read_signature(reader: &mut PsdReader) -> ReadResult<String> {
349 read_short_string(reader, 4)
350}
351
352pub fn valid_signature_at(reader: &PsdReader, offset: usize) -> bool {
354 if offset + 4 > reader.buffer.len() {
355 return false;
356 }
357 let sig = &reader.buffer[offset..offset + 4];
358 sig == b"8BIM" || sig == b"8B64"
359}
360
361pub fn read_pascal_string(reader: &mut PsdReader, pad_to: usize) -> ReadResult<String> {
366 let mut length = read_uint8(reader)? as usize;
367 let text = if length != 0 {
368 read_short_string(reader, length)?
369 } else {
370 String::new()
371 };
372
373 loop {
375 length += 1;
376 if length % pad_to == 0 {
377 break;
378 }
379 reader.offset += 1;
380 }
381
382 Ok(text)
383}
384
385pub fn read_unicode_string(reader: &mut PsdReader) -> ReadResult<String> {
387 let length = read_uint32(reader)? as usize;
388 read_unicode_string_with_length(reader, length)
389}
390
391pub fn read_unicode_string_with_length(
397 reader: &mut PsdReader,
398 length: usize,
399) -> ReadResult<String> {
400 let mut units: Vec<u16> = Vec::with_capacity(length);
401 let mut remaining = length;
402 while remaining > 0 {
403 remaining -= 1;
404 let value = read_uint16(reader)?;
405 if value != 0 || remaining > 0 {
407 units.push(value);
408 }
409 }
410 Ok(utf16_units_to_string(&units))
411}
412
413pub fn read_unicode_string_with_length_le(
415 reader: &mut PsdReader,
416 length: usize,
417) -> ReadResult<String> {
418 let mut units: Vec<u16> = Vec::with_capacity(length);
419 let mut remaining = length;
420 while remaining > 0 {
421 remaining -= 1;
422 let value = read_uint16_le(reader)?;
423 if value != 0 || remaining > 0 {
424 units.push(value);
425 }
426 }
427 Ok(utf16_units_to_string(&units))
428}
429
430fn utf16_units_to_string(units: &[u16]) -> String {
438 char::decode_utf16(units.iter().copied())
439 .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
440 .collect()
441}
442
443pub fn check_signature(reader: &mut PsdReader, a: &str, b: Option<&str>) -> ReadResult<()> {
448 let offset = reader.offset;
449 let signature = read_signature(reader)?;
450
451 if signature != a && Some(signature.as_str()) != b {
452 return Err(ReadError::InvalidSignature { signature, offset });
453 }
454 Ok(())
455}
456
457pub fn read_section<T, F>(
474 reader: &mut PsdReader,
475 round: usize,
476 func: F,
477 skip_empty: bool,
478 eight_bytes: bool,
479) -> ReadResult<Option<T>>
480where
481 F: FnOnce(&mut PsdReader, &dyn Fn(&PsdReader) -> usize) -> ReadResult<T>,
482{
483 let mut length = read_uint32(reader)? as usize;
484
485 if eight_bytes {
486 if length != 0 {
487 return Err(ReadError::SizeTooLarge);
488 }
489 length = read_uint32(reader)? as usize;
490 }
491
492 if length == 0 && skip_empty {
494 return Ok(None);
495 }
496
497 let mut end = reader.offset + length;
498 if end > reader.buffer.len() {
499 return Err(ReadError::SectionExceedsFileSize);
500 }
501
502 let left = move |r: &PsdReader| end_minus_offset(end, r);
503 let result = func(reader, &left)?;
504
505 if reader.offset != end {
506 if reader.offset > end {
507 warn_or_throw(reader, "Exceeded section limits")?;
508 } else {
509 warn_or_throw(reader, "Unread section data")?;
510 }
511 }
512
513 while length % round != 0 {
515 length += 1;
516 end += 1;
517 }
518
519 reader.offset = end;
520
521 Ok(Some(result))
522}
523
524#[inline]
525fn end_minus_offset(end: usize, reader: &PsdReader) -> usize {
526 end.saturating_sub(reader.offset)
527}
528
529pub fn peek_uint32(reader: &PsdReader) -> ReadResult<u32> {
533 let start = ensure(reader, 4)?;
534 Ok(u32::from_be_bytes([
535 reader.buffer[start],
536 reader.buffer[start + 1],
537 reader.buffer[start + 2],
538 reader.buffer[start + 3],
539 ]))
540}
541
542use crate::additional_info::{read_additional_info_key, ReadCtx};
547use crate::helpers::{
548 create_image_data, decode_bitmap, image_data_to_canvas, offset_for_channel,
549 to_blend_mode, ColorSpace, LayerMaskFlags, MaskParams,
550};
551use crate::image_resources::read_image_resource;
552use crate::psd::{
553 Color, ColorMode, Compression, GlobalLayerMaskInfo, ImageResources, Layer, LayerAdditionalInfo,
554 LayerMaskData, LayerRawData, LayerRawDataChannel, PatternInfo, PixelData, Cmyk, Grayscale, Hsb,
555 Lab, PatternBounds, Rgb, ChannelId, SectionDividerType,
556};
557
558#[derive(Debug, Clone, Copy)]
560struct ChannelInfo {
561 id: i16,
562 length: usize,
563}
564
565fn is_supported_color_mode(mode: u16) -> bool {
567 matches!(mode, 0 | 1 | 3 | 2) }
569
570fn color_mode_from_u16(mode: u16) -> Option<ColorMode> {
571 Some(match mode {
572 0 => ColorMode::Bitmap,
573 1 => ColorMode::Grayscale,
574 2 => ColorMode::Indexed,
575 3 => ColorMode::Rgb,
576 4 => ColorMode::Cmyk,
577 7 => ColorMode::Multichannel,
578 8 => ColorMode::Duotone,
579 9 => ColorMode::Lab,
580 _ => return None,
581 })
582}
583
584fn channel_id_from_i16(id: i16) -> ChannelId {
585 match id {
586 0 => ChannelId::Color0,
587 1 => ChannelId::Color1,
588 2 => ChannelId::Color2,
589 3 => ChannelId::Color3,
590 -2 => ChannelId::UserMask,
591 -3 => ChannelId::RealUserMask,
592 _ => ChannelId::Transparency,
595 }
596}
597
598pub struct DecodeTarget {
606 pub width: usize,
607 pub height: usize,
608 pub data: Vec<u8>,
610 pub channels: usize,
611}
612
613impl DecodeTarget {
614 pub fn rgba(width: usize, height: usize) -> DecodeTarget {
615 DecodeTarget { width, height, data: vec![0u8; width * height * 4], channels: 4 }
616 }
617 pub fn wide(width: usize, height: usize, channels: usize) -> DecodeTarget {
618 DecodeTarget { width, height, data: vec![0u8; width * height * channels], channels }
619 }
620 pub fn into_pixel_data(self) -> PixelData {
621 PixelData { width: self.width as u32, height: self.height as u32, data: self.data }
622 }
623}
624
625pub fn read_psd(buffer: &[u8], options: &ReadOptions) -> ReadResult<crate::psd::Psd> {
632 let mut reader = PsdReader::new(buffer, None, None);
633 reader.options = options.clone();
634 reader.strict = options.strict.unwrap_or(false);
635 reader.debug = options.debug.unwrap_or(false);
636 read_psd_from_reader(&mut reader)
637}
638
639pub fn read_psd_from_reader(reader: &mut PsdReader) -> ReadResult<crate::psd::Psd> {
642 check_signature(reader, "8BPS", None)?;
644 let version = read_uint16(reader)?;
645 if version != 1 && version != 2 {
646 return Err(ReadError::StrictViolation(format!(
647 "Invalid PSD file version: {}",
648 version
649 )));
650 }
651
652 skip_bytes(reader, 6);
653 let channels = read_uint16(reader)?;
654 let height = read_uint32(reader)?;
655 let width = read_uint32(reader)?;
656 let bits_per_channel = read_uint16(reader)?;
657 let color_mode_raw = read_uint16(reader)?;
658 let max_size: u32 = if version == 1 { 30000 } else { 300000 };
659
660 if width > max_size || height > max_size {
661 return Err(ReadError::StrictViolation(format!(
662 "Invalid size: {}x{}",
663 width, height
664 )));
665 }
666 if channels > 16 {
667 return Err(ReadError::StrictViolation(format!(
668 "Invalid channel count: {}",
669 channels
670 )));
671 }
672 if ![1, 8, 16, 32].contains(&bits_per_channel) {
673 return Err(ReadError::StrictViolation(format!(
674 "Invalid bitsPerChannel: {}",
675 bits_per_channel
676 )));
677 }
678 if !is_supported_color_mode(color_mode_raw) {
679 return Err(ReadError::StrictViolation(format!(
680 "Color mode not supported: {}",
681 color_mode_raw
682 )));
683 }
684
685 let color_mode = color_mode_from_u16(color_mode_raw);
686
687 let mut psd = crate::psd::Psd {
688 width: width as f64,
689 height: height as f64,
690 channels: Some(channels as f64),
691 bits_per_channel: Some(bits_per_channel as f64),
692 color_mode,
693 ..Default::default()
694 };
695
696 reader.large = version == 2;
697 reader.global_alpha = false;
698
699 let palette = read_section(
701 reader,
702 1,
703 |reader, left| {
704 if left(reader) == 0 {
705 return Ok(None);
706 }
707 let mut palette: Option<Vec<Rgb>> = None;
708 if color_mode == Some(ColorMode::Indexed) {
709 if left(reader) != 768 {
710 return Err(ReadError::StrictViolation(
711 "Invalid color palette size".to_string(),
712 ));
713 }
714 let mut pal: Vec<Rgb> = Vec::with_capacity(256);
715 for _ in 0..256 {
716 pal.push(Rgb { r: read_uint8(reader)? as f64, g: 0.0, b: 0.0 });
717 }
718 for i in 0..256 {
719 pal[i].g = read_uint8(reader)? as f64;
720 }
721 for i in 0..256 {
722 pal[i].b = read_uint8(reader)? as f64;
723 }
724 palette = Some(pal);
725 }
726 skip_bytes(reader, left(reader));
727 Ok(palette)
728 },
729 true,
730 false,
731 )?;
732 if let Some(Some(p)) = palette {
733 psd.palette = Some(p);
734 }
735
736 let mut image_resources = ImageResources::default();
738 read_section(
739 reader,
740 1,
741 |reader, left| {
742 while left(reader) > 0 {
743 realign_with_signature(reader, is_valid_image_resource_signature)?;
744 let id = read_uint16(reader)?;
745 read_pascal_string(reader, 2)?; read_section(
748 reader,
749 2,
750 |reader, left| {
751 let skip = id == 1036 && reader.options.skip_thumbnail == Some(true);
752 let throw_for_missing =
753 reader.options.throw_for_missing_features == Some(true);
754 let block_len = left(reader);
755 if !skip {
756 match read_image_resource(id, reader, &mut image_resources, block_len) {
757 Ok(()) => {}
758 Err(e) => {
759 if throw_for_missing {
760 return Err(e);
761 }
762 skip_bytes(reader, left(reader));
763 }
764 }
765 } else {
766 skip_bytes(reader, left(reader));
767 }
768 Ok(())
769 },
770 false,
771 false,
772 )?;
773 }
774 Ok(())
775 },
776 true,
777 false,
778 )?;
779 psd.image_resources = Some(image_resources);
780
781 read_section(
783 reader,
784 1,
785 |reader, left| {
786 read_section(
787 reader,
788 2,
789 |reader, left| {
790 read_layer_info(reader, &mut psd)?;
791 skip_bytes(reader, left(reader));
792 Ok(())
793 },
794 true,
795 reader.large,
796 )?;
797
798 if left(reader) > 0 {
800 if let Some(info) = read_global_layer_mask_info(reader)? {
801 psd.global_layer_mask_info = Some(info);
802 }
803 } else {
804 skip_bytes(reader, left(reader));
805 }
806
807 while left(reader) > 0 {
808 while left(reader) > 0 && peek_uint8(reader)? == 0 {
810 skip_bytes(reader, 1);
811 }
812
813 if left(reader) >= 12 {
814 let mut info = std::mem::take(&mut psd.additional_info);
816 read_additional_layer_info(reader, &mut info)?;
817 psd.additional_info = info;
818 } else {
819 skip_bytes(reader, left(reader));
820 break;
821 }
822 }
823 Ok(())
824 },
825 true,
826 reader.large,
827 )?;
828
829 let has_children = psd.children.as_ref().map_or(false, |c| !c.is_empty());
830 let skip_layer = reader.options.skip_layer_image_data == Some(true);
831 let skip_composite =
832 reader.options.skip_composite_image_data == Some(true) && (skip_layer || has_children);
833
834 if !skip_composite {
835 read_image_data(reader, &mut psd)?;
836 }
837
838 Ok(psd)
839}
840
841fn is_valid_image_resource_signature(sig: &str) -> bool {
842 sig == "8BIM" || sig == "MeSa" || sig == "AgHg" || sig == "PHUT" || sig == "DCSR"
843}
844
845fn read_layer_info(reader: &mut PsdReader, psd: &mut crate::psd::Psd) -> ReadResult<()> {
850 let mut layer_count = read_int16(reader)? as i32;
851
852 if layer_count < 0 {
853 reader.global_alpha = true;
854 layer_count = -layer_count;
855 }
856 let layer_count = layer_count as usize;
857
858 let mut layers: Vec<Layer> = Vec::with_capacity(layer_count);
859 let mut layer_channels: Vec<Vec<ChannelInfo>> = Vec::with_capacity(layer_count);
860
861 for _ in 0..layer_count {
862 let (layer, channels) = read_layer_record(reader, psd)?;
863 layers.push(layer);
864 layer_channels.push(channels);
865 }
866
867 for i in 0..layer_count {
868 read_layer_channel_image_data(reader, psd, &mut layers[i], &layer_channels[i])?;
869 }
870
871 if psd.children.is_none() {
872 psd.children = Some(Vec::new());
873 }
874
875 build_layer_tree(psd, layers);
879
880 Ok(())
881}
882
883fn build_layer_tree(psd: &mut crate::psd::Psd, mut layers: Vec<Layer>) {
885 struct Frame {
896 children: Vec<Layer>,
897 folder: Option<Layer>,
898 }
899
900 let mut stack: Vec<Frame> = vec![Frame { children: Vec::new(), folder: None }];
901
902 for i in (0..layers.len()).rev() {
903 let l = std::mem::take(&mut layers[i]);
904 let ty = l
905 .additional_info
906 .section_divider
907 .as_ref()
908 .map(|d| d.divider_type)
909 .unwrap_or(SectionDividerType::Other);
910
911 match ty {
912 SectionDividerType::OpenFolder | SectionDividerType::ClosedFolder => {
913 let mut folder = l;
914 folder.opened = Some(ty == SectionDividerType::OpenFolder);
915 folder.children = Some(Vec::new());
916 if let Some(div) = &folder.additional_info.section_divider {
917 if let Some(key) = &div.key {
918 if let Some(bm) = to_blend_mode(key) {
919 folder.blend_mode = Some(bm);
920 }
921 }
922 }
923 stack.push(Frame { children: Vec::new(), folder: Some(folder) });
927 }
928 SectionDividerType::BoundingSectionDivider => {
929 let frame = stack.pop().unwrap_or(Frame { children: Vec::new(), folder: None });
932 if let Some(mut folder) = frame.folder {
933 folder.children = Some(frame.children);
934 if let Some(parent) = stack.last_mut() {
935 parent.children.insert(0, folder);
936 }
937 } else {
938 if let Some(parent) = stack.last_mut() {
940 for layer in frame.children.into_iter().rev() {
941 parent.children.insert(0, layer);
942 }
943 }
944 }
945 }
946 _ => {
947 if let Some(top) = stack.last_mut() {
948 top.children.insert(0, l);
949 }
950 }
951 }
952 }
953
954 while stack.len() > 1 {
956 let frame = stack.pop().unwrap();
957 if let Some(mut folder) = frame.folder {
958 folder.children = Some(frame.children);
959 if let Some(parent) = stack.last_mut() {
960 parent.children.insert(0, folder);
961 }
962 } else if let Some(parent) = stack.last_mut() {
963 for layer in frame.children.into_iter().rev() {
964 parent.children.insert(0, layer);
965 }
966 }
967 }
968
969 let root = stack.pop().unwrap();
970 let children = psd.children.get_or_insert_with(Vec::new);
971 *children = root.children;
972}
973
974fn read_layer_record(
979 reader: &mut PsdReader,
980 _psd: &mut crate::psd::Psd,
981) -> ReadResult<(Layer, Vec<ChannelInfo>)> {
982 let mut layer = Layer::default();
983 layer.top = Some(read_int32(reader)? as f64);
984 layer.left = Some(read_int32(reader)? as f64);
985 layer.bottom = Some(read_int32(reader)? as f64);
986 layer.right = Some(read_int32(reader)? as f64);
987
988 let channel_count = read_uint16(reader)?;
989 let mut channels: Vec<ChannelInfo> = Vec::with_capacity(channel_count as usize);
990
991 for _ in 0..channel_count {
992 let id = read_int16(reader)?;
993 let mut length = read_uint32(reader)? as usize;
994 if reader.large {
995 if length != 0 {
996 return Err(ReadError::StrictViolation(
997 "Sizes larger than 4GB are not supported".to_string(),
998 ));
999 }
1000 length = read_uint32(reader)? as usize;
1001 }
1002 channels.push(ChannelInfo { id, length });
1003 }
1004
1005 check_signature(reader, "8BIM", None)?;
1006 let blend_mode = read_signature(reader)?;
1007 match to_blend_mode(&blend_mode) {
1008 Some(bm) => layer.blend_mode = Some(bm),
1009 None => {
1010 return Err(ReadError::StrictViolation(format!(
1011 "Invalid blend mode: '{}'",
1012 blend_mode
1013 )))
1014 }
1015 }
1016
1017 layer.opacity = Some(read_uint8(reader)? as f64 / 0xff as f64);
1018 layer.clipping = Some(read_uint8(reader)? == 1);
1019
1020 let flags = read_uint8(reader)?;
1021 layer.transparency_protected = Some((flags & 0x01) != 0);
1022 layer.hidden = Some((flags & 0x02) != 0);
1023 if flags & 0x20 != 0 {
1024 layer.effects_open = Some(true);
1025 }
1026
1027 skip_bytes(reader, 1);
1028
1029 let large = reader.large;
1031 let mut info = std::mem::take(&mut layer.additional_info);
1032 read_section(
1033 reader,
1034 1,
1035 |reader, left| {
1036 read_layer_mask_data(reader, &mut info)?;
1037
1038 if let Some(ranges) = read_layer_blending_ranges(reader)? {
1039 info.blending_ranges = Some(ranges);
1040 }
1041 info.name = Some(read_pascal_string(reader, 1)?);
1042
1043 while left(reader) > 4 && !valid_signature_at(reader, reader.offset) {
1045 reader.offset += 1;
1046 }
1047
1048 while left(reader) >= 12 {
1049 read_additional_layer_info(reader, &mut info)?;
1050 }
1051
1052 skip_bytes(reader, left(reader));
1053 Ok(())
1054 },
1055 true,
1056 false,
1057 )?;
1058 let _ = large;
1059 layer.additional_info = info;
1060
1061 Ok((layer, channels))
1062}
1063
1064fn read_layer_mask_data(
1065 reader: &mut PsdReader,
1066 info: &mut LayerAdditionalInfo,
1067) -> ReadResult<()> {
1068 read_section(
1069 reader,
1070 1,
1071 |reader, left| {
1072 if left(reader) == 0 {
1073 return Ok(());
1074 }
1075 let mut mask = LayerMaskData::default();
1076 mask.top = Some(read_int32(reader)? as f64);
1077 mask.left = Some(read_int32(reader)? as f64);
1078 mask.bottom = Some(read_int32(reader)? as f64);
1079 mask.right = Some(read_int32(reader)? as f64);
1080 mask.default_color = Some(read_uint8(reader)? as f64);
1081
1082 let flags = read_uint8(reader)?;
1083 mask.position_relative_to_layer =
1084 Some((flags & LayerMaskFlags::PositionRelativeToLayer as u8) != 0);
1085 mask.disabled = Some((flags & LayerMaskFlags::LayerMaskDisabled as u8) != 0);
1086 mask.from_vector_data =
1087 Some((flags & LayerMaskFlags::LayerMaskFromRenderingOtherData as u8) != 0);
1088
1089 if left(reader) >= 18 {
1090 let mut real_mask = LayerMaskData::default();
1091 let real_flags = read_uint8(reader)?;
1092 real_mask.position_relative_to_layer =
1093 Some((real_flags & LayerMaskFlags::PositionRelativeToLayer as u8) != 0);
1094 real_mask.disabled =
1095 Some((real_flags & LayerMaskFlags::LayerMaskDisabled as u8) != 0);
1096 real_mask.from_vector_data = Some(
1097 (real_flags & LayerMaskFlags::LayerMaskFromRenderingOtherData as u8) != 0,
1098 );
1099 real_mask.default_color = Some(read_uint8(reader)? as f64);
1100 real_mask.top = Some(read_int32(reader)? as f64);
1101 real_mask.left = Some(read_int32(reader)? as f64);
1102 real_mask.bottom = Some(read_int32(reader)? as f64);
1103 real_mask.right = Some(read_int32(reader)? as f64);
1104 info.real_mask = Some(real_mask);
1105 }
1106
1107 if flags & LayerMaskFlags::MaskHasParametersAppliedToIt as u8 != 0 {
1108 let params = read_uint8(reader)?;
1109 if params & MaskParams::UserMaskDensity as u8 != 0 {
1110 mask.user_mask_density = Some(read_uint8(reader)? as f64 / 0xff as f64);
1111 }
1112 if params & MaskParams::UserMaskFeather as u8 != 0 {
1113 mask.user_mask_feather = Some(read_float64(reader)?);
1114 }
1115 if params & MaskParams::VectorMaskDensity as u8 != 0 {
1116 mask.vector_mask_density = Some(read_uint8(reader)? as f64 / 0xff as f64);
1117 }
1118 if params & MaskParams::VectorMaskFeather as u8 != 0 {
1119 mask.vector_mask_feather = Some(read_float64(reader)?);
1120 }
1121 }
1122
1123 info.mask = Some(mask);
1124 skip_bytes(reader, left(reader));
1125 Ok(())
1126 },
1127 true,
1128 false,
1129 )?;
1130 Ok(())
1131}
1132
1133fn read_blending_range(reader: &mut PsdReader) -> ReadResult<Vec<f64>> {
1134 Ok(vec![
1135 read_uint8(reader)? as f64,
1136 read_uint8(reader)? as f64,
1137 read_uint8(reader)? as f64,
1138 read_uint8(reader)? as f64,
1139 ])
1140}
1141
1142fn read_layer_blending_ranges(
1143 reader: &mut PsdReader,
1144) -> ReadResult<Option<crate::psd::BlendingRanges>> {
1145 let res = read_section(
1146 reader,
1147 1,
1148 |reader, left| {
1149 let composite_gray_blend_source = read_blending_range(reader)?;
1150 let composite_graph_blend_destination_range = read_blending_range(reader)?;
1151 let mut ranges: Vec<crate::psd::BlendingRange> = Vec::new();
1152 while left(reader) > 0 {
1153 let source_range = read_blending_range(reader)?;
1154 let dest_range = read_blending_range(reader)?;
1155 ranges.push(crate::psd::BlendingRange { source_range, dest_range });
1156 }
1157 Ok(crate::psd::BlendingRanges {
1158 composite_gray_blend_source,
1159 composite_graph_blend_destination_range,
1160 ranges,
1161 })
1162 },
1163 true,
1164 false,
1165 )?;
1166 Ok(res)
1167}
1168
1169fn read_layer_channel_image_data(
1174 reader: &mut PsdReader,
1175 psd: &crate::psd::Psd,
1176 layer: &mut Layer,
1177 channels: &[ChannelInfo],
1178) -> ReadResult<()> {
1179 if reader.options.skip_layer_image_data == Some(true) {
1180 return Ok(());
1181 }
1182
1183 let color_mode = psd.color_mode.unwrap_or(ColorMode::Rgb);
1184 let bits_per_channel = psd.bits_per_channel.unwrap_or(8.0);
1185 let large = reader.large;
1186
1187 let mut raw_channels: Vec<LayerRawDataChannel> = Vec::with_capacity(channels.len());
1188
1189 for channel in channels {
1190 let start = reader.offset;
1191 let mut compression = Compression::RawData;
1192 let mut data: Option<Vec<u8>> = None;
1193
1194 if channel.length == 1 {
1195 return Err(ReadError::StrictViolation("Invalid channel length".to_string()));
1196 }
1197 if channel.length != 0 {
1198 let mut comp = read_uint16(reader)?;
1199 if comp > 3 {
1200 reader.offset -= 1;
1201 comp = read_uint16(reader)?;
1202 }
1203 if comp > 3 {
1204 reader.offset -= 3;
1205 comp = read_uint16(reader)?;
1206 }
1207 if comp > 3 {
1208 return Err(ReadError::StrictViolation(format!(
1209 "Invalid compression: {}",
1210 comp
1211 )));
1212 }
1213 compression = compression_from_u16(comp);
1214 if channel.length > 2 {
1215 data = Some(read_bytes(reader, channel.length - 2)?);
1216 }
1217 }
1218
1219 reader.offset = start + channel.length;
1220 raw_channels.push(LayerRawDataChannel {
1221 id: channel_id_from_i16(channel.id),
1222 compression,
1223 data,
1224 });
1225 }
1226
1227 layer.raw_data = Some(LayerRawData {
1228 color_mode,
1229 bits_per_channel,
1230 channels: raw_channels,
1231 large,
1232 });
1233
1234 if reader.options.use_raw_data != Some(true) {
1235 let use_image_data = reader.options.use_image_data == Some(true);
1236 let throw_missing = reader.options.throw_for_missing_features == Some(true);
1237 decode_layer_image_data(layer, use_image_data, throw_missing)?;
1238 }
1239
1240 Ok(())
1241}
1242
1243fn compression_from_u16(v: u16) -> Compression {
1244 match v {
1245 0 => Compression::RawData,
1246 1 => Compression::RleCompressed,
1247 2 => Compression::ZipWithoutPrediction,
1248 _ => Compression::ZipWithPrediction,
1249 }
1250}
1251
1252fn setup_grayscale(data: &mut [u8], width: usize, height: usize) {
1253 let size = width * height * 4;
1254 let mut i = 0;
1255 while i < size {
1256 let c = data[i];
1257 data[i + 1] = c;
1258 data[i + 2] = c;
1259 i += 4;
1260 }
1261}
1262
1263fn reset_alpha(target: &mut DecodeTarget, cmyk: bool) {
1264 let alpha = 0xffu8;
1265 let offset = if cmyk { 4 } else { 3 };
1266 let step = if cmyk { 5 } else { 4 };
1267 let length = target.data.len();
1268 let mut p = offset;
1269 while p < length {
1270 target.data[p] = alpha;
1271 p += step;
1272 }
1273}
1274
1275fn decode_layer_image_data(
1277 layer: &mut Layer,
1278 use_image_data: bool,
1279 throw_for_missing_features: bool,
1280) -> ReadResult<()> {
1281 let raw = match layer.raw_data.take() {
1282 Some(r) => r,
1283 None => return Ok(()),
1284 };
1285
1286 let color_mode = raw.color_mode;
1287 let bits_per_channel = raw.bits_per_channel as u32;
1288 let large = raw.large;
1289 let layer_width =
1290 (layer.right.unwrap_or(0.0) - layer.left.unwrap_or(0.0)).max(0.0) as usize;
1291 let layer_height =
1292 (layer.bottom.unwrap_or(0.0) - layer.top.unwrap_or(0.0)).max(0.0) as usize;
1293 let cmyk = color_mode == ColorMode::Cmyk;
1294
1295 let mut image_data: Option<DecodeTarget> = None;
1296 let mut initialized_alpha = false;
1297
1298 if layer_width != 0 && layer_height != 0 {
1299 if cmyk {
1300 if bits_per_channel != 8 {
1301 return Err(ReadError::StrictViolation("bitsPerChannel Not supproted".to_string()));
1302 }
1303 image_data = Some(DecodeTarget::wide(layer_width, layer_height, 5));
1304 } else {
1305 image_data = Some(DecodeTarget::rgba(layer_width, layer_height));
1306 }
1307 }
1308
1309 for ch in &raw.channels {
1310 let data = match &ch.data {
1311 Some(d) => d,
1312 None => continue,
1313 };
1314 let mut data_reader = PsdReader::new(data, None, None);
1315
1316 if ch.id == ChannelId::UserMask || ch.id == ChannelId::RealUserMask {
1317 let mask_ref = if ch.id == ChannelId::UserMask {
1318 layer.additional_info.mask.as_ref()
1319 } else {
1320 layer.additional_info.real_mask.as_ref()
1321 };
1322 let (mtop, mleft, mbottom, mright) = match mask_ref {
1323 Some(m) => (
1324 m.top.unwrap_or(0.0),
1325 m.left.unwrap_or(0.0),
1326 m.bottom.unwrap_or(0.0),
1327 m.right.unwrap_or(0.0),
1328 ),
1329 None => {
1330 return Err(ReadError::StrictViolation(format!(
1331 "Missing layer {} data",
1332 if ch.id == ChannelId::UserMask { "mask" } else { "real mask" }
1333 )))
1334 }
1335 };
1336 let mask_width = (mright - mleft) as i64;
1337 let mask_height = (mbottom - mtop) as i64;
1338 if !(0..=30000).contains(&mask_width) || !(0..=30000).contains(&mask_height) {
1339 return Err(ReadError::StrictViolation("Invalid mask size".to_string()));
1340 }
1341 let mw = mask_width as usize;
1342 let mh = mask_height as usize;
1343 if mw != 0 && mh != 0 {
1344 let mut mask_data = DecodeTarget::rgba(mw, mh);
1345 read_data(
1346 &mut data_reader,
1347 data.len(),
1348 Some(&mut mask_data),
1349 ch.compression,
1350 mw,
1351 mh,
1352 bits_per_channel,
1353 0,
1354 large,
1355 4,
1356 )?;
1357 setup_grayscale(&mut mask_data.data, mw, mh);
1358 reset_alpha(&mut mask_data, false);
1359 let pd = mask_data.into_pixel_data();
1360 let mask = if ch.id == ChannelId::UserMask {
1361 layer.additional_info.mask.as_mut()
1362 } else {
1363 layer.additional_info.real_mask.as_mut()
1364 };
1365 if let Some(mask) = mask {
1366 if use_image_data {
1367 mask.image_data = Some(pd);
1368 } else {
1369 mask.canvas = Some(image_data_to_canvas(&pd));
1370 }
1371 }
1372 }
1373 } else {
1374 let offset = offset_for_channel(ch.id, cmyk);
1375 let target = if offset < 0 {
1376 if throw_for_missing_features {
1377 return Err(ReadError::StrictViolation(format!(
1378 "Channel not supported: {}",
1379 ch.id as i32
1380 )));
1381 }
1382 None
1383 } else {
1384 image_data.as_mut()
1385 };
1386
1387 let step = if cmyk { 5 } else { 4 };
1388 read_data(
1389 &mut data_reader,
1390 data.len(),
1391 target,
1392 ch.compression,
1393 layer_width,
1394 layer_height,
1395 bits_per_channel,
1396 offset.max(0) as usize,
1397 large,
1398 step,
1399 )?;
1400
1401 if offset >= 0 && color_mode == ColorMode::Grayscale {
1402 if let Some(t) = image_data.as_mut() {
1403 setup_grayscale(&mut t.data, t.width, t.height);
1404 }
1405 }
1406 }
1407
1408 if ch.id == ChannelId::Transparency {
1409 initialized_alpha = true;
1410 }
1411 }
1412
1413 if let Some(mut img) = image_data {
1414 if !initialized_alpha {
1415 reset_alpha(&mut img, cmyk);
1416 }
1417
1418 let final_pd = if cmyk {
1419 let mut rgb = create_image_data(img.width as u32, img.height as u32);
1420 cmyk_to_rgb(&img, &mut rgb, false);
1421 rgb
1422 } else {
1423 img.into_pixel_data()
1424 };
1425
1426 if use_image_data {
1427 layer.image_data = Some(final_pd);
1428 } else {
1429 layer.canvas = Some(image_data_to_canvas(&final_pd));
1430 }
1431 }
1432
1433 Ok(())
1434}
1435
1436fn read_data(
1442 reader: &mut PsdReader,
1443 length: usize,
1444 pixels: Option<&mut DecodeTarget>,
1445 compression: Compression,
1446 width: usize,
1447 height: usize,
1448 bit_depth: u32,
1449 offset: usize,
1450 large: bool,
1451 step: usize,
1452) -> ReadResult<()> {
1453 if length == 0 {
1454 return Ok(());
1455 }
1456 match compression {
1457 Compression::RawData => {
1458 let data = read_bytes(reader, length)?;
1459 read_data_raw(&data, pixels, bit_depth, step, offset);
1460 Ok(())
1461 }
1462 Compression::RleCompressed => {
1463 read_data_rle(reader, pixels, width, height, bit_depth, step, &[offset], large)
1464 }
1465 Compression::ZipWithoutPrediction => {
1466 let data = read_bytes(reader, length)?;
1467 read_data_zip(&data, pixels, width, height, bit_depth, step, offset, false);
1468 Ok(())
1469 }
1470 Compression::ZipWithPrediction => {
1471 let data = read_bytes(reader, length)?;
1472 read_data_zip(&data, pixels, width, height, bit_depth, step, offset, true);
1473 Ok(())
1474 }
1475 }
1476}
1477
1478fn copy_channel_to_pixel_data(target: &mut DecodeTarget, channel: &[u8], offset: usize, step: usize) {
1479 let size = target.width * target.height;
1480 let mut p = offset;
1481 for i in 0..size {
1482 if i >= channel.len() || p >= target.data.len() {
1483 break;
1484 }
1485 target.data[p] = channel[i];
1486 p += step;
1487 }
1488}
1489
1490pub fn read_data_raw(
1492 buffer: &[u8],
1493 pixel_data: Option<&mut DecodeTarget>,
1494 bit_depth: u32,
1495 step: usize,
1496 offset: usize,
1497) {
1498 let pixel_data = match pixel_data {
1499 Some(p) => p,
1500 None => return,
1501 };
1502 if offset >= step {
1503 return;
1504 }
1505 let bytes = bytes_to_u8_channel(buffer, bit_depth);
1506 copy_channel_to_pixel_data(pixel_data, &bytes, offset, step);
1507}
1508
1509fn bytes_to_u8_channel(buffer: &[u8], bit_depth: u32) -> Vec<u8> {
1513 match bit_depth {
1514 8 => buffer.to_vec(),
1515 16 => {
1516 let mut out = Vec::with_capacity(buffer.len() / 2);
1518 let mut i = 0;
1519 while i + 1 < buffer.len() {
1520 out.push(buffer[i]);
1521 i += 2;
1522 }
1523 out
1524 }
1525 32 => {
1526 let mut out = Vec::with_capacity(buffer.len() / 4);
1528 let mut i = 0;
1529 while i + 3 < buffer.len() {
1530 let v = f32::from_be_bytes([
1531 buffer[i],
1532 buffer[i + 1],
1533 buffer[i + 2],
1534 buffer[i + 3],
1535 ]);
1536 let c = (v.max(0.0).min(1.0) * 255.0).round() as u8;
1537 out.push(c);
1538 i += 4;
1539 }
1540 out
1541 }
1542 _ => buffer.to_vec(),
1543 }
1544}
1545
1546fn decode_predicted_u8(data: &mut [u8], width: usize, height: usize) {
1547 for y in 0..height {
1548 let offset = y * width;
1549 for x in 1..width {
1550 let o = offset + x;
1551 data[o] = data[o - 1].wrapping_add(data[o]);
1552 }
1553 }
1554}
1555
1556fn decode_predicted_u16(data: &mut [u16], width: usize, height: usize) {
1557 for y in 0..height {
1558 let offset = y * width;
1559 for x in 1..width {
1560 let o = offset + x;
1561 data[o] = data[o - 1].wrapping_add(data[o]);
1562 }
1563 }
1564}
1565
1566pub fn read_data_zip(
1568 compressed: &[u8],
1569 pixel_data: Option<&mut DecodeTarget>,
1570 width: usize,
1571 height: usize,
1572 bit_depth: u32,
1573 step: usize,
1574 offset: usize,
1575 prediction: bool,
1576) {
1577 use flate2::read::ZlibDecoder;
1578 use std::io::Read;
1579
1580 let mut decoder = ZlibDecoder::new(compressed);
1581 let mut decompressed: Vec<u8> = Vec::new();
1582 if decoder.read_to_end(&mut decompressed).is_err() {
1583 return;
1584 }
1585
1586 let pixel_data = match pixel_data {
1587 Some(p) => p,
1588 None => return,
1589 };
1590 if offset >= step {
1591 return;
1592 }
1593
1594 match bit_depth {
1595 8 => {
1596 if prediction {
1597 decode_predicted_u8(&mut decompressed, width, height);
1598 }
1599 copy_channel_to_pixel_data(pixel_data, &decompressed, offset, step);
1600 }
1601 16 => {
1602 let mut samples: Vec<u16> = Vec::with_capacity(decompressed.len() / 2);
1604 let mut i = 0;
1605 while i + 1 < decompressed.len() {
1606 samples.push(u16::from_be_bytes([decompressed[i], decompressed[i + 1]]));
1607 i += 2;
1608 }
1609 if prediction {
1610 decode_predicted_u16(&mut samples, width, height);
1611 }
1612 let bytes: Vec<u8> = samples.iter().map(|&s| (s >> 8) as u8).collect();
1614 copy_channel_to_pixel_data(pixel_data, &bytes, offset, step);
1615 }
1616 32 => {
1617 if prediction {
1619 decode_predicted_u8(&mut decompressed, width * 4, height);
1620 }
1621 let mut p = offset;
1623 for y in 0..height {
1624 let a0 = width * 4 * y;
1625 for x in 0..width {
1626 let a = a0 + x;
1627 let b = a + width;
1628 let c = b + width;
1629 let d = c + width;
1630 if d >= decompressed.len() || p >= pixel_data.data.len() {
1631 break;
1632 }
1633 let v = f32::from_be_bytes([
1634 decompressed[a],
1635 decompressed[b],
1636 decompressed[c],
1637 decompressed[d],
1638 ]);
1639 pixel_data.data[p] = (v.max(0.0).min(1.0) * 255.0).round() as u8;
1640 p += step;
1641 }
1642 }
1643 }
1644 _ => {}
1645 }
1646}
1647
1648pub fn read_data_rle(
1652 reader: &mut PsdReader,
1653 mut pixel_data: Option<&mut DecodeTarget>,
1654 width: usize,
1655 height: usize,
1656 _bit_depth: u32,
1657 step: usize,
1658 offsets: &[usize],
1659 large: bool,
1660) -> ReadResult<()> {
1661 let mut lengths: Vec<usize> = Vec::with_capacity(offsets.len() * height);
1662 if large {
1663 for _ in 0..offsets.len() {
1664 for _ in 0..height {
1665 lengths.push(read_uint32(reader)? as usize);
1666 }
1667 }
1668 } else {
1669 for _ in 0..offsets.len() {
1670 for _ in 0..height {
1671 lengths.push(read_uint16(reader)? as usize);
1672 }
1673 }
1674 }
1675
1676 let extra_limit = step.saturating_sub(1);
1677
1678 let mut li = 0usize;
1679 for c in 0..offsets.len() {
1680 let offset = offsets[c];
1681 let extra = c > extra_limit || offset > extra_limit;
1682
1683 let have_data = pixel_data.is_some() && !extra;
1684 if !have_data {
1685 for _ in 0..height {
1686 let len = lengths[li];
1687 li += 1;
1688 skip_bytes(reader, len);
1689 }
1690 continue;
1691 }
1692
1693 let mut p = offset;
1694 for _ in 0..height {
1695 let length = lengths[li];
1696 li += 1;
1697 let buffer = read_bytes(reader, length)?;
1698
1699 let mut i = 0usize;
1700 let mut x = 0usize;
1701 while i < length {
1702 let header = buffer[i];
1703 if header > 128 {
1704 i += 1;
1705 if i >= buffer.len() {
1706 break;
1707 }
1708 let value = buffer[i];
1709 let count = (256 - header as usize) as usize;
1710 let mut j = 0;
1711 while j <= count && x < width {
1712 let pd = pixel_data.as_deref_mut_unchecked();
1713 if p < pd.data.len() {
1714 pd.data[p] = value;
1715 }
1716 p += step;
1717 j += 1;
1718 x += 1;
1719 }
1720 } else if header < 128 {
1721 let count = header as usize;
1722 let mut j = 0;
1723 while j <= count && x < width {
1724 i += 1;
1725 if i >= buffer.len() {
1726 break;
1727 }
1728 let value = buffer[i];
1729 let pd = pixel_data.as_deref_mut_unchecked();
1730 if p < pd.data.len() {
1731 pd.data[p] = value;
1732 }
1733 p += step;
1734 j += 1;
1735 x += 1;
1736 }
1737 }
1738 i += 1;
1739 }
1740 }
1741 let _ = p;
1744 }
1745
1746 Ok(())
1747}
1748
1749trait OptMutHelper {
1752 fn as_deref_mut_unchecked(&mut self) -> &mut DecodeTarget;
1753}
1754impl OptMutHelper for Option<&mut DecodeTarget> {
1755 #[inline]
1756 fn as_deref_mut_unchecked(&mut self) -> &mut DecodeTarget {
1757 self.as_deref_mut().expect("pixel_data present in RLE write path")
1758 }
1759}
1760
1761fn read_global_layer_mask_info(
1766 reader: &mut PsdReader,
1767) -> ReadResult<Option<GlobalLayerMaskInfo>> {
1768 let res = read_section(
1769 reader,
1770 1,
1771 |reader, left| {
1772 if left(reader) == 0 {
1773 return Ok(None);
1774 }
1775 let overlay_color_space = read_uint16(reader)? as f64;
1776 let color_space1 = read_uint16(reader)? as f64;
1777 let color_space2 = read_uint16(reader)? as f64;
1778 let color_space3 = read_uint16(reader)? as f64;
1779 let color_space4 = read_uint16(reader)? as f64;
1780 let opacity = read_uint16(reader)? as f64 / 0xff as f64;
1781 let kind = read_uint8(reader)? as f64;
1782 skip_bytes(reader, left(reader));
1783 Ok(Some(GlobalLayerMaskInfo {
1784 overlay_color_space,
1785 color_space1,
1786 color_space2,
1787 color_space3,
1788 color_space4,
1789 opacity,
1790 kind,
1791 }))
1792 },
1793 true,
1794 false,
1795 )?;
1796 Ok(res.flatten())
1797}
1798
1799const FIX_OFFSETS: [i32; 9] = [0, 1, -1, 2, -2, 3, -3, 4, -4];
1804
1805fn realign_with_signature(
1807 reader: &mut PsdReader,
1808 is_valid: fn(&str) -> bool,
1809) -> ReadResult<String> {
1810 let sig_offset = reader.offset as i64;
1811 let mut sig = String::new();
1812
1813 for &off in FIX_OFFSETS.iter() {
1814 let new_off = sig_offset + off as i64;
1815 if new_off < 0 || (new_off as usize) + 4 > reader.buffer.len() {
1816 continue;
1817 }
1818 reader.offset = new_off as usize;
1819 if let Ok(s) = read_signature(reader) {
1820 sig = s;
1821 }
1822 if is_valid(&sig) {
1823 break;
1824 }
1825 }
1826
1827 if !is_valid(&sig) {
1828 return Err(ReadError::InvalidSignature {
1829 signature: sig,
1830 offset: sig_offset as usize,
1831 });
1832 }
1833 Ok(sig)
1834}
1835
1836fn is_valid_additional_info_signature(sig: &str) -> bool {
1837 sig == "8BIM" || sig == "8B64"
1838}
1839
1840fn read_additional_layer_info(
1842 reader: &mut PsdReader,
1843 target: &mut LayerAdditionalInfo,
1844) -> ReadResult<()> {
1845 let sig = realign_with_signature(reader, is_valid_additional_info_signature)?;
1846 let key = read_signature(reader)?;
1847
1848 let large = reader.large;
1849 let u64_size = sig == "8B64"
1850 || (large && crate::additional_info::is_large_key(&key));
1851
1852 let options = reader.options.clone();
1853 let throw_for_missing = options.throw_for_missing_features == Some(true);
1854
1855 read_section(
1856 reader,
1857 2,
1858 |reader, left| {
1859 let mut ctx = ReadCtx { options: &options, large };
1860 match read_additional_info_key(&key, reader, target, &left_fn_wrap(left), &mut ctx) {
1861 Ok(handled) => {
1862 if !handled {
1863 skip_bytes(reader, left(reader));
1864 }
1865 }
1866 Err(e) => {
1867 if throw_for_missing {
1868 return Err(e);
1869 }
1870 }
1872 }
1873 if left(reader) > 0 {
1874 skip_bytes(reader, left(reader));
1875 }
1876 Ok(())
1877 },
1878 false,
1879 u64_size,
1880 )?;
1881 Ok(())
1882}
1883
1884fn left_fn_wrap<'a>(left: &'a dyn Fn(&PsdReader) -> usize) -> impl Fn(&PsdReader) -> usize + 'a {
1887 move |r: &PsdReader| left(r)
1888}
1889
1890fn read_image_data(reader: &mut PsdReader, psd: &mut crate::psd::Psd) -> ReadResult<()> {
1895 let compression = compression_from_u16(read_uint16(reader)?);
1896 let bits_per_channel = psd.bits_per_channel.unwrap_or(8.0) as u32;
1897 let color_mode = psd.color_mode.unwrap_or(ColorMode::Rgb);
1898
1899 let width = psd.width as usize;
1900 let height = psd.height as usize;
1901 let channels_count = psd.channels.unwrap_or(0.0) as usize;
1902
1903 if compression != Compression::RawData && compression != Compression::RleCompressed {
1904 return Err(ReadError::StrictViolation(format!(
1905 "Compression type not supported: {:?}",
1906 compression
1907 )));
1908 }
1909
1910 let mut image_data = DecodeTarget::rgba(width, height);
1911 {
1912 let buf = &mut image_data.data;
1914 let mut p = 0;
1915 while p < buf.len() {
1916 buf[p] = 0;
1917 buf[p + 1] = 0;
1918 buf[p + 2] = 0;
1919 buf[p + 3] = 0xff;
1920 p += 4;
1921 }
1922 }
1923
1924 match color_mode {
1925 ColorMode::Bitmap => {
1926 if bits_per_channel != 1 {
1927 return Err(ReadError::StrictViolation(
1928 "Invalid bitsPerChannel for bitmap color mode".to_string(),
1929 ));
1930 }
1931 let bytes: Vec<u8> = match compression {
1932 Compression::RawData => {
1933 read_bytes(reader, ((width + 7) / 8) * height)?
1934 }
1935 Compression::RleCompressed => {
1936 let mut tgt = DecodeTarget {
1937 width,
1938 height,
1939 data: vec![0u8; width * height],
1940 channels: 1,
1941 };
1942 read_data_rle(
1943 reader,
1944 Some(&mut tgt),
1945 width,
1946 height,
1947 8,
1948 1,
1949 &[0],
1950 reader.large,
1951 )?;
1952 tgt.data
1953 }
1954 _ => {
1955 return Err(ReadError::StrictViolation(
1956 "Bitmap compression not supported".to_string(),
1957 ))
1958 }
1959 };
1960 decode_bitmap(&bytes, &mut image_data.data, width, height);
1961 }
1962 ColorMode::Rgb | ColorMode::Grayscale => {
1963 let mut channels: Vec<usize> =
1964 if color_mode == ColorMode::Grayscale { vec![0] } else { vec![0, 1, 2] };
1965
1966 if channels_count > 3 {
1967 for i in 3..channels_count {
1968 channels.push(i);
1969 }
1970 } else if reader.global_alpha {
1971 channels.push(3);
1972 }
1973
1974 match compression {
1975 Compression::RawData => {
1976 for &c in &channels {
1977 let data =
1978 read_bytes(reader, width * height * (bits_per_channel as usize / 8))?;
1979 read_data_raw(&data, Some(&mut image_data), bits_per_channel, 4, c);
1980 }
1981 }
1982 Compression::RleCompressed => {
1983 read_data_rle(
1984 reader,
1985 Some(&mut image_data),
1986 width,
1987 height,
1988 bits_per_channel,
1989 4,
1990 &channels,
1991 reader.large,
1992 )?;
1993 }
1994 _ => {}
1995 }
1996
1997 if color_mode == ColorMode::Grayscale {
1998 setup_grayscale(&mut image_data.data, width, height);
1999 }
2000 }
2001 ColorMode::Indexed => {
2002 if bits_per_channel != 8 {
2003 return Err(ReadError::StrictViolation("bitsPerChannel Not supproted".to_string()));
2004 }
2005 if channels_count != 1 {
2006 return Err(ReadError::StrictViolation("Invalid channel count".to_string()));
2007 }
2008 let palette = psd
2009 .palette
2010 .clone()
2011 .ok_or_else(|| ReadError::StrictViolation("Missing color palette".to_string()))?;
2012
2013 match compression {
2014 Compression::RleCompressed => {
2015 let mut indexed = DecodeTarget {
2016 width,
2017 height,
2018 data: vec![0u8; width * height],
2019 channels: 1,
2020 };
2021 read_data_rle(
2022 reader,
2023 Some(&mut indexed),
2024 width,
2025 height,
2026 bits_per_channel,
2027 1,
2028 &[0],
2029 reader.large,
2030 )?;
2031 indexed_to_rgb(&indexed, &mut image_data, &palette);
2032 }
2033 _ => return Err(ReadError::StrictViolation("Not implemented".to_string())),
2034 }
2035 }
2036 _ => {
2037 return Err(ReadError::StrictViolation(format!(
2038 "Color mode not supported: {:?}",
2039 color_mode
2040 )))
2041 }
2042 }
2043
2044 if reader.global_alpha && bits_per_channel == 8 {
2046 let p = &mut image_data.data;
2047 let size = width * height * 4;
2048 let mut i = 0;
2049 while i < size {
2050 let pa = p[i + 3];
2051 if pa != 0 && pa != 255 {
2052 let a = pa as f64 / 255.0;
2053 let ra = 1.0 / a;
2054 let inv_a = 255.0 * (1.0 - ra);
2055 p[i] = (p[i] as f64 * ra + inv_a) as u8;
2056 p[i + 1] = (p[i + 1] as f64 * ra + inv_a) as u8;
2057 p[i + 2] = (p[i + 2] as f64 * ra + inv_a) as u8;
2058 }
2059 i += 4;
2060 }
2061 }
2062
2063 let pd = image_data.into_pixel_data();
2064 if reader.options.use_image_data == Some(true) {
2065 psd.image_data = Some(pd);
2066 } else {
2067 psd.canvas = Some(image_data_to_canvas(&pd));
2068 }
2069
2070 Ok(())
2071}
2072
2073fn cmyk_to_rgb(cmyk: &DecodeTarget, rgb: &mut PixelData, reverse_alpha: bool) {
2074 let size = (rgb.width as usize) * (rgb.height as usize) * 4;
2075 let src = &cmyk.data;
2076 let dst = &mut rgb.data;
2077 let mut s = 0usize;
2078 let mut d = 0usize;
2079 while d < size && s + 4 < src.len() {
2080 let c = src[s] as u32;
2081 let m = src[s + 1] as u32;
2082 let y = src[s + 2] as u32;
2083 let k = src[s + 3] as u32;
2084 dst[d] = ((c * k) / 255) as u8;
2085 dst[d + 1] = ((m * k) / 255) as u8;
2086 dst[d + 2] = ((y * k) / 255) as u8;
2087 dst[d + 3] = if reverse_alpha { 255 - src[s + 4] } else { src[s + 4] };
2088 s += 5;
2089 d += 4;
2090 }
2091}
2092
2093fn indexed_to_rgb(indexed: &DecodeTarget, rgb: &mut DecodeTarget, palette: &[Rgb]) {
2094 let size = indexed.width * indexed.height;
2095 let mut d = 0usize;
2096 for s in 0..size {
2097 let idx = indexed.data[s] as usize;
2098 if let Some(c) = palette.get(idx) {
2099 rgb.data[d] = c.r as u8;
2100 rgb.data[d + 1] = c.g as u8;
2101 rgb.data[d + 2] = c.b as u8;
2102 rgb.data[d + 3] = 255;
2103 }
2104 d += 4;
2105 }
2106}
2107
2108pub fn read_color(reader: &mut PsdReader) -> ReadResult<Color> {
2117 let color_space = read_uint16(reader)?;
2118 if color_space == ColorSpace::Rgb as u16 {
2119 let r = read_uint16(reader)? as f64 / 257.0;
2120 let g = read_uint16(reader)? as f64 / 257.0;
2121 let b = read_uint16(reader)? as f64 / 257.0;
2122 skip_bytes(reader, 2);
2123 Ok(Color::Rgb(Rgb { r, g, b }))
2124 } else if color_space == ColorSpace::Hsb as u16 {
2125 let h = read_uint16(reader)? as f64 / 0xffff as f64;
2126 let s = read_uint16(reader)? as f64 / 0xffff as f64;
2127 let b = read_uint16(reader)? as f64 / 0xffff as f64;
2128 skip_bytes(reader, 2);
2129 Ok(Color::Hsb(Hsb { h, s, b }))
2130 } else if color_space == ColorSpace::Cmyk as u16 {
2131 let c = read_uint16(reader)? as f64 / 257.0;
2132 let m = read_uint16(reader)? as f64 / 257.0;
2133 let y = read_uint16(reader)? as f64 / 257.0;
2134 let k = read_uint16(reader)? as f64 / 257.0;
2135 Ok(Color::Cmyk(Cmyk { c, m, y, k }))
2136 } else if color_space == ColorSpace::Lab as u16 {
2137 let l = read_int16(reader)? as f64 / 10000.0;
2138 let ta = read_int16(reader)? as f64;
2139 let tb = read_int16(reader)? as f64;
2140 let a = if ta < 0.0 { ta / 12800.0 } else { ta / 12700.0 };
2141 let b = if tb < 0.0 { tb / 12800.0 } else { tb / 12700.0 };
2142 skip_bytes(reader, 2);
2143 Ok(Color::Lab(Lab { l, a, b }))
2144 } else if color_space == ColorSpace::Grayscale as u16 {
2145 let k = read_uint16(reader)? as f64 * 255.0 / 10000.0;
2146 skip_bytes(reader, 6);
2147 Ok(Color::Grayscale(Grayscale { k }))
2148 } else {
2149 Err(ReadError::StrictViolation("Invalid color space".to_string()))
2150 }
2151}
2152
2153pub fn read_pattern(reader: &mut PsdReader) -> ReadResult<PatternInfo> {
2156 let mut length = read_uint32(reader)? as usize;
2157 while length % 4 != 0 {
2158 length += 1;
2159 }
2160 let end = reader.offset + length;
2161 let version = read_uint32(reader)?;
2162 if version != 1 {
2163 return Err(ReadError::StrictViolation(format!(
2164 "Invalid pattern version: {}",
2165 version
2166 )));
2167 }
2168
2169 let color_mode_raw = read_uint32(reader)?;
2170 let color_mode = color_mode_from_u16(color_mode_raw as u16);
2171 let x = read_int16(reader)? as f64;
2172 let y = read_int16(reader)? as f64;
2173
2174 if !matches!(
2175 color_mode,
2176 Some(ColorMode::Rgb) | Some(ColorMode::Grayscale) | Some(ColorMode::Indexed)
2177 ) {
2178 return Err(ReadError::StrictViolation(format!(
2179 "Unsupported pattern color mode: {}",
2180 color_mode_raw
2181 )));
2182 }
2183 let color_mode = color_mode.unwrap();
2184
2185 let name = read_unicode_string(reader)?;
2186 let id = read_pascal_string(reader, 1)?;
2187
2188 let mut palette: Vec<Rgb> = Vec::new();
2189 if color_mode == ColorMode::Indexed {
2190 for _ in 0..256 {
2191 palette.push(Rgb {
2192 r: read_uint8(reader)? as f64,
2193 g: read_uint8(reader)? as f64,
2194 b: read_uint8(reader)? as f64,
2195 });
2196 }
2197 skip_bytes(reader, 4);
2198 }
2199
2200 let version2 = read_uint32(reader)?;
2201 if version2 != 3 {
2202 return Err(ReadError::StrictViolation(format!(
2203 "Invalid pattern VMAL version: {}",
2204 version2
2205 )));
2206 }
2207
2208 read_uint32(reader)?; let top = read_uint32(reader)? as i64;
2210 let left = read_uint32(reader)? as i64;
2211 let bottom = read_uint32(reader)? as i64;
2212 let right = read_uint32(reader)? as i64;
2213 let channels_count = read_uint32(reader)? as usize;
2214 let width = (right - left) as usize;
2215 let height = (bottom - top) as usize;
2216 let mut data = vec![0u8; width * height * 4];
2217 let mut i = 3;
2218 while i < data.len() {
2219 data[i] = 255;
2220 i += 4;
2221 }
2222
2223 let mut ch = 0usize;
2224 for _ in 0..(channels_count + 2) {
2225 let has = read_uint32(reader)?;
2226 if has == 0 {
2227 continue;
2228 }
2229 let length = read_uint32(reader)? as usize;
2230 let pixel_depth = read_uint32(reader)?;
2231 let ctop = read_uint32(reader)? as i64;
2232 let cleft = read_uint32(reader)? as i64;
2233 let cbottom = read_uint32(reader)? as i64;
2234 let cright = read_uint32(reader)? as i64;
2235 let pixel_depth2 = read_uint16(reader)?;
2236 let compression_mode = read_uint8(reader)?;
2237 let data_length = length.saturating_sub(4 + 16 + 2 + 1);
2238 let cdata = read_bytes(reader, data_length)?;
2239
2240 if pixel_depth != 8 || pixel_depth2 != 8 {
2241 return Err(ReadError::StrictViolation(
2242 "16bit pixel depth not supported for patterns".to_string(),
2243 ));
2244 }
2245
2246 let w = (cright - cleft) as usize;
2247 let h = (cbottom - ctop) as usize;
2248 let ox = (cleft - left) as usize;
2249 let oy = (ctop - top) as usize;
2250
2251 if compression_mode == 0 {
2252 if color_mode == ColorMode::Rgb && ch < 3 {
2253 for yy in 0..h {
2254 for xx in 0..w {
2255 let src = xx + yy * w;
2256 let dst = (ox + xx + (yy + oy) * width) * 4;
2257 if dst + ch < data.len() && src < cdata.len() {
2258 data[dst + ch] = cdata[src];
2259 }
2260 }
2261 }
2262 }
2263 if color_mode == ColorMode::Grayscale && ch < 1 {
2264 for yy in 0..h {
2265 for xx in 0..w {
2266 let src = xx + yy * w;
2267 let dst = (ox + xx + (yy + oy) * width) * 4;
2268 if dst + 2 < data.len() && src < cdata.len() {
2269 let value = cdata[src];
2270 data[dst] = value;
2271 data[dst + 1] = value;
2272 data[dst + 2] = value;
2273 }
2274 }
2275 }
2276 }
2277 if color_mode == ColorMode::Indexed {
2278 return Err(ReadError::StrictViolation(
2279 "Indexed pattern color mode not implemented".to_string(),
2280 ));
2281 }
2282 } else if compression_mode == 1 {
2283 let mut temp = DecodeTarget { width: w, height: h, data: vec![0u8; w * h], channels: 1 };
2284 let mut cdata_reader = PsdReader::new(&cdata, None, None);
2285 if color_mode == ColorMode::Rgb && ch < 3 {
2286 read_data_rle(&mut cdata_reader, Some(&mut temp), w, h, 8, 1, &[0], false)?;
2287 copy_channel_to_rgba(&temp, &mut data, width, ox, oy, ch);
2288 }
2289 if color_mode == ColorMode::Grayscale && ch < 1 {
2290 read_data_rle(&mut cdata_reader, Some(&mut temp), w, h, 8, 1, &[0], false)?;
2291 copy_channel_to_rgba(&temp, &mut data, width, ox, oy, 0);
2292 copy_channel_to_rgba(&temp, &mut data, width, ox, oy, 1);
2295 copy_channel_to_rgba(&temp, &mut data, width, ox, oy, 2);
2296 }
2297 if color_mode == ColorMode::Indexed {
2298 return Err(ReadError::StrictViolation(
2299 "Indexed pattern color mode not implemented".to_string(),
2300 ));
2301 }
2302 } else {
2303 return Err(ReadError::StrictViolation(
2304 "Invalid pattern compression mode".to_string(),
2305 ));
2306 }
2307
2308 ch += 1;
2309 }
2310
2311 reader.offset = end;
2312
2313 Ok(PatternInfo {
2314 id,
2315 name,
2316 x,
2317 y,
2318 bounds: PatternBounds {
2319 x: left as f64,
2320 y: top as f64,
2321 w: width as f64,
2322 h: height as f64,
2323 },
2324 data,
2325 })
2326}
2327
2328fn copy_channel_to_rgba(
2329 src: &DecodeTarget,
2330 dst: &mut [u8],
2331 dst_width: usize,
2332 ox: usize,
2333 oy: usize,
2334 offset: usize,
2335) {
2336 let w = src.width;
2337 let h = src.height;
2338 for y in 0..h {
2339 for x in 0..w {
2340 let s = x + y * w;
2341 let d = (ox + x + (y + oy) * dst_width) * 4;
2342 if d + offset < dst.len() && s < src.data.len() {
2343 dst[d + offset] = src.data[s];
2344 }
2345 }
2346 }
2347}
2348
2349#[cfg(test)]
2350mod tests {
2351 use super::*;
2352
2353 #[test]
2354 fn scalar_round_trip_big_endian() {
2355 let buf: Vec<u8> = vec![
2358 0x12, 0xFF, 0xFF, 0xFE, 0x01, 0x02, 0xFF, 0xFF, 0xFF, 0xFD, 0x01, 0x02, 0x03, 0x04, ];
2365 let mut r = PsdReader::new(&buf, None, None);
2366 assert_eq!(read_uint8(&mut r).unwrap(), 0x12);
2367 assert_eq!(read_int8(&mut r).unwrap(), -1);
2368 assert_eq!(read_int16(&mut r).unwrap(), -2);
2369 assert_eq!(read_uint16(&mut r).unwrap(), 0x0102);
2370 assert_eq!(read_int32(&mut r).unwrap(), -3);
2371 assert_eq!(read_uint32(&mut r).unwrap(), 0x0102_0304);
2372 assert_eq!(r.offset, buf.len());
2373 }
2374
2375 #[test]
2376 fn float_round_trip_big_endian() {
2377 let f32v: f32 = 3.5;
2378 let f64v: f64 = -1234.5678;
2379 let mut buf = Vec::new();
2380 buf.extend_from_slice(&f32v.to_be_bytes());
2381 buf.extend_from_slice(&f64v.to_be_bytes());
2382 let mut r = PsdReader::new(&buf, None, None);
2383 assert_eq!(read_float32(&mut r).unwrap(), f32v);
2384 assert_eq!(read_float64(&mut r).unwrap(), f64v);
2385 }
2386
2387 #[test]
2388 fn uint16_le_differs_from_be() {
2389 let buf = vec![0x01, 0x02];
2390 let mut r = PsdReader::new(&buf, None, None);
2391 assert_eq!(read_uint16_le(&mut r).unwrap(), 0x0201);
2392 }
2393
2394 #[test]
2395 fn fixed_point() {
2396 let buf = vec![0x00, 0x01, 0x80, 0x00];
2398 let mut r = PsdReader::new(&buf, None, None);
2399 assert_eq!(read_fixed_point32(&mut r).unwrap(), 1.5);
2400 }
2401
2402 #[test]
2403 fn signature_and_check() {
2404 let buf = b"8BIM".to_vec();
2405 let mut r = PsdReader::new(&buf, None, None);
2406 assert!(valid_signature_at(&r, 0));
2407 check_signature(&mut r, "8BIM", None).unwrap();
2408
2409 let mut r2 = PsdReader::new(&buf, None, None);
2410 let err = check_signature(&mut r2, "8BPS", None).unwrap_err();
2411 assert_eq!(
2412 err,
2413 ReadError::InvalidSignature {
2414 signature: "8BIM".to_string(),
2415 offset: 0
2416 }
2417 );
2418 }
2419
2420 #[test]
2421 fn pascal_string_pad_to_2() {
2422 let buf = vec![0x03, b'a', b'b', b'c'];
2425 let mut r = PsdReader::new(&buf, None, None);
2426 assert_eq!(read_pascal_string(&mut r, 2).unwrap(), "abc");
2427 assert_eq!(r.offset, 4);
2428 }
2429
2430 #[test]
2431 fn pascal_string_with_padding() {
2432 let buf = vec![0x02, b'a', b'b', 0x00, 0xFF];
2434 let mut r = PsdReader::new(&buf, None, None);
2435 assert_eq!(read_pascal_string(&mut r, 4).unwrap(), "ab");
2436 assert_eq!(r.offset, 4);
2438 }
2439
2440 #[test]
2441 fn pascal_string_empty() {
2442 let buf = vec![0x00, 0x00, 0x00, 0x00];
2444 let mut r = PsdReader::new(&buf, None, None);
2445 assert_eq!(read_pascal_string(&mut r, 4).unwrap(), "");
2446 assert_eq!(r.offset, 4);
2448 }
2449
2450 #[test]
2451 fn unicode_string_with_length() {
2452 let buf = vec![
2454 0x00, 0x00, 0x00, 0x03, 0x00, 0x48, 0x00, 0x69, 0x00, 0x00, ];
2459 let mut r = PsdReader::new(&buf, None, None);
2460 assert_eq!(read_unicode_string(&mut r).unwrap(), "Hi");
2461 }
2462
2463 #[test]
2464 fn unicode_string_non_ascii() {
2465 let buf = vec![
2467 0x00, 0x00, 0x00, 0x01, 0x04, 0x2F, ];
2470 let mut r = PsdReader::new(&buf, None, None);
2471 assert_eq!(read_unicode_string(&mut r).unwrap(), "Я");
2472 }
2473
2474 #[test]
2475 fn unicode_string_surrogate_pair() {
2476 let buf = vec![
2478 0x00, 0x00, 0x00, 0x02, 0xD8, 0x3D, 0xDE, 0x00, ];
2482 let mut r = PsdReader::new(&buf, None, None);
2483 assert_eq!(read_unicode_string(&mut r).unwrap(), "😀");
2484 }
2485
2486 #[test]
2487 fn signature_str_is_latin1_codeunits() {
2488 let buf = vec![0xFF, 0x00, b'A', b'B'];
2490 let mut r = PsdReader::new(&buf, None, None);
2491 let sig = read_signature(&mut r).unwrap();
2492 let chars: Vec<u32> = sig.chars().map(|c| c as u32).collect();
2493 assert_eq!(chars, vec![0xFF, 0x00, 0x41, 0x42]);
2494 }
2495
2496 #[test]
2497 fn read_bytes_recovery_past_end() {
2498 let buf = vec![0x01, 0x02];
2499 let mut r = PsdReader::new(&buf, None, None);
2500 let out = read_bytes(&mut r, 4).unwrap();
2502 assert_eq!(out, vec![0x01, 0x02, 0x00, 0x00]);
2503 assert_eq!(r.offset, 4);
2504 }
2505
2506 #[test]
2507 fn read_bytes_strict_errors() {
2508 let buf = vec![0x01, 0x02];
2509 let mut r = PsdReader::new(&buf, None, None);
2510 r.strict = true;
2511 let err = read_bytes(&mut r, 4).unwrap_err();
2513 assert_eq!(
2514 err,
2515 ReadError::StrictViolation("Reading bytes exceeding buffer length".to_string())
2516 );
2517 }
2518
2519 #[test]
2520 fn section_rounding() {
2521 let buf = vec![
2525 0x00, 0x00, 0x00, 0x03, 0xAA, 0xBB, 0xCC, 0xEE, ];
2529 let mut r = PsdReader::new(&buf, None, None);
2530 let collected: Vec<u8> = read_section(
2531 &mut r,
2532 4,
2533 |reader, left| {
2534 assert_eq!(left(reader), 3);
2535 let a = read_uint8(reader)?;
2536 let b = read_uint8(reader)?;
2537 let c = read_uint8(reader)?;
2538 assert_eq!(left(reader), 0);
2539 Ok(vec![a, b, c])
2540 },
2541 true,
2542 false,
2543 )
2544 .unwrap()
2545 .unwrap();
2546 assert_eq!(collected, vec![0xAA, 0xBB, 0xCC]);
2547 assert_eq!(r.offset, 8);
2549 }
2550
2551 #[test]
2552 fn section_empty_skipped() {
2553 let buf = vec![0x00, 0x00, 0x00, 0x00];
2554 let mut r = PsdReader::new(&buf, None, None);
2555 let res: Option<()> =
2556 read_section(&mut r, 4, |_r, _left| Ok(()), true, false).unwrap();
2557 assert!(res.is_none());
2558 }
2559
2560 #[test]
2561 fn section_eight_bytes() {
2562 let buf = vec![
2564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x22, ];
2568 let mut r = PsdReader::new(&buf, None, None);
2569 let res: Option<u16> = read_section(
2570 &mut r,
2571 1,
2572 |reader, _left| read_uint16(reader),
2573 true,
2574 true,
2575 )
2576 .unwrap();
2577 assert_eq!(res, Some(0x1122));
2578 }
2579
2580 #[test]
2581 fn section_exceeds_file() {
2582 let buf = vec![0x00, 0x00, 0x00, 0x10]; let mut r = PsdReader::new(&buf, None, None);
2584 let err = read_section::<(), _>(&mut r, 1, |_r, _l| Ok(()), true, false).unwrap_err();
2585 assert_eq!(err, ReadError::SectionExceedsFileSize);
2586 }
2587
2588 fn read_fixture(rel: &str) -> crate::psd::Psd {
2593 let path = format!(
2594 "{}/../../test/ag-psd/test/read/{}/src.psd",
2595 env!("CARGO_MANIFEST_DIR"),
2596 rel
2597 );
2598 let bytes = std::fs::read(&path).unwrap_or_else(|e| panic!("read {}: {}", path, e));
2599 let opts = ReadOptions::default();
2600 read_psd(&bytes, &opts).unwrap_or_else(|e| panic!("read_psd {}: {:?}", rel, e))
2601 }
2602
2603 fn count_layers(layers: &[Layer]) -> usize {
2604 layers.iter().map(|l| 1 + l.children.as_ref().map_or(0, |c| count_layers(c))).sum()
2605 }
2606
2607 fn any_layer_has_pixels(layers: &[Layer]) -> bool {
2608 layers.iter().any(|l| {
2609 let has = l
2610 .canvas
2611 .as_ref()
2612 .map_or(false, |c| !c.data.is_empty())
2613 || l.image_data.as_ref().map_or(false, |c| !c.data.is_empty());
2614 has || l.children.as_ref().map_or(false, |c| any_layer_has_pixels(c))
2615 })
2616 }
2617
2618 #[test]
2619 fn read_fixture_layers_rgb8() {
2620 let psd = read_fixture("layers");
2621 assert_eq!(psd.width, 300.0);
2622 assert_eq!(psd.height, 200.0);
2623 assert_eq!(psd.color_mode, Some(ColorMode::Rgb));
2624 assert_eq!(psd.bits_per_channel, Some(8.0));
2625 let children = psd.children.as_ref().expect("children");
2626 assert_eq!(children.len(), 3, "top-level children count");
2627 assert!(any_layer_has_pixels(children), "at least one layer has pixel data");
2628 assert!(psd.canvas.as_ref().map_or(false, |c| !c.data.is_empty()));
2630 }
2631
2632 #[test]
2633 fn read_fixture_groups_nesting() {
2634 let psd = read_fixture("groups");
2635 assert_eq!(psd.width, 300.0);
2636 assert_eq!(psd.height, 200.0);
2637 assert_eq!(psd.color_mode, Some(ColorMode::Rgb));
2638 let children = psd.children.as_ref().expect("children");
2639 assert_eq!(children.len(), 2, "top-level children count (2 incl. group)");
2640 assert!(count_layers(children) >= 3);
2642 assert!(any_layer_has_pixels(children));
2643 }
2644
2645 #[test]
2646 fn read_fixture_just_bg_no_layers() {
2647 let psd = read_fixture("just-bg");
2648 assert_eq!(psd.width, 100.0);
2649 assert_eq!(psd.height, 100.0);
2650 assert_eq!(psd.color_mode, Some(ColorMode::Rgb));
2651 let count = psd.children.as_ref().map_or(0, |c| c.len());
2652 assert_eq!(count, 0, "background-only document has no layer children");
2653 assert!(psd.canvas.as_ref().map_or(false, |c| !c.data.is_empty()));
2654 }
2655
2656 #[test]
2657 fn new_with_offset_window() {
2658 let buf = vec![0x00, 0x11, 0x22, 0x33, 0x44];
2659 let mut r = PsdReader::new(&buf, Some(1), Some(2));
2660 assert_eq!(read_uint8(&mut r).unwrap(), 0x11);
2662 assert_eq!(read_uint8(&mut r).unwrap(), 0x22);
2663 assert!(read_uint8(&mut r).is_err());
2664 }
2665}