/* File Header Section * Len Description Value * 4 Signature "8BPS" * 2 Version 1 * 6 Reserved not used. * 2 Channels 1 ~ 56 * 4 Height 1 ~ 30,000 * 4 Width 1 ~ 30,000 * 2 Color Depth 1, 8, 16, 32 * 2 Color Mode 1 ~ 9 */ private static void ReadHeader(ref PsdInfo info, PSDReader reader) { // Signature if (reader.ReadByte() != 0x38 || reader.ReadByte() != 0x42 || reader.ReadByte() != 0x50 || reader.ReadByte() != 0x53) { throw new NotSupportedException(); } // Version var version = reader.ReadInt16(); if (version != 1) { throw new NotSupportedException(); } // Reserved reader.Position += 6; // Channels info.Channels = reader.ReadInt16(); // Height info.Height = reader.ReadInt32(); // Width info.Width = reader.ReadInt32(); // Color Depth info.ColorDepth = reader.ReadInt16(); info.ColorDepthBytes = info.ColorDepth / 8; if (info.ColorDepthBytes != 1 && info.ColorDepthBytes != 2 && info.ColorDepthBytes != 4) { throw new NotSupportedException(); } // Color Mode info.ColorMode = (ColorMods)reader.ReadInt16(); if (info.ColorMode == ColorMods.Bitmap) { throw new NotSupportedException(); } info.Pixcels = info.Width * info.Height; info.SizePerChannel = info.Pixcels * info.ColorDepthBytes; }
/* Image Data Section * Len Description Value * 2 Compression Mode CompressionModes * n Image Data */ private static void ReadImageData(ref PsdInfo info, PSDReader reader) { info.CompressionMode = (CompressionModes)reader.ReadInt16(); int i; info.ImageData = new byte[info.Channels][]; switch (info.CompressionMode) { case CompressionModes.Raw: for (i = 0; i < info.Channels; ++i) { info.ImageData[i] = reader.ReadBytes(info.SizePerChannel); } break; case CompressionModes.RLE: reader.Position += info.Height * info.Channels * 2; for (i = 0; i < info.Channels; ++i) { info.ImageData[i] = new byte[info.SizePerChannel]; RLEDecompress(reader, info.ImageData[i], info.SizePerChannel); } break; case CompressionModes.ZipWithoutPrediction: case CompressionModes.ZipWithPrediction: throw new NotSupportedException(); } }
/* Image Data Section * Len Description Value * 2 Compression Mode CompressionModes * n Image Data */ private static void ReadImageData(ref PsdInfo info, PSDReader reader) { info.CompressionMode = (CompressionModes)reader.ReadInt16(); int i; info.ImageData = new byte[info.Channels][]; switch (info.CompressionMode) { case CompressionModes.Raw: for (i = 0; i < info.Channels; ++i) info.ImageData[i] = reader.ReadBytes(info.SizePerChannel); break; case CompressionModes.RLE: reader.Position += info.Height * info.Channels * 2; for (i = 0; i < info.Channels; ++i) { info.ImageData[i] = new byte[info.SizePerChannel]; RLEDecompress(reader, info.ImageData[i], info.SizePerChannel); } break; case CompressionModes.ZipWithoutPrediction: case CompressionModes.ZipWithPrediction: throw new NotSupportedException(); } }
/* Image Resources Section * Len Description Value * 4 Length * n Resource Block Data */ /* Image Resource Blocks * Len Description Value * 4 Signature '8BIM' * 2 Resource Id * n Name * 4 Resource Data Length * n Resource Data */ private static void ReadImageResources(ref PsdInfo info, PSDReader reader) { var length = reader.ReadInt32(); short id; int len; info.TransparencyIndex = -1; long pos = reader.Position + length; while (reader.Position < pos) { // Signature if (reader.ReadByte() != 0x38 || reader.ReadByte() != 0x42 || reader.ReadByte() != 0x49 || reader.ReadByte() != 0x4D) throw new NotSupportedException(); // Resource Id id = reader.ReadInt16(); // Name len = reader.ReadByte(); if (len > 0) { if((len % 2) != 0) len = reader.ReadByte(); reader.Position += len; } reader.Position += 1; // Data Length len = reader.ReadInt32(); if (len % 2 != 0) len++; switch (id) { case 1005: // ResolutionInfo structure info.DpiX = reader.ReadInt16(); reader.Position += 6; info.DpiY = reader.ReadInt16(); reader.Position += 6; break; case 1047: // Transparency Index. 2 bytes for the index of transparent color, if any. info.TransparencyIndex = reader.ReadInt16(); break; default: reader.Position += len; break; } } }
/* File Header Section * Len Description Value * 4 Signature "8BPS" * 2 Version 1 * 6 Reserved not used. * 2 Channels 1 ~ 56 * 4 Height 1 ~ 30,000 * 4 Width 1 ~ 30,000 * 2 Color Depth 1, 8, 16, 32 * 2 Color Mode 1 ~ 9 */ private static void ReadHeader(ref PsdInfo info, PSDReader reader) { // Signature if (reader.ReadByte() != 0x38 || reader.ReadByte() != 0x42 || reader.ReadByte() != 0x50 || reader.ReadByte() != 0x53) throw new NotSupportedException(); // Version var version = reader.ReadInt16(); if (version != 1) throw new NotSupportedException(); // Reserved reader.Position += 6; // Channels info.Channels = reader.ReadInt16(); // Height info.Height = reader.ReadInt32(); // Width info.Width = reader.ReadInt32(); // Color Depth info.ColorDepth = reader.ReadInt16(); info.ColorDepthBytes = info.ColorDepth / 8; if (info.ColorDepthBytes != 1 && info.ColorDepthBytes != 2 && info.ColorDepthBytes != 4) throw new NotSupportedException(); // Color Mode info.ColorMode = (ColorMods)reader.ReadInt16(); if (info.ColorMode == ColorMods.Bitmap) throw new NotSupportedException(); info.Pixcels = info.Width * info.Height; info.SizePerChannel = info.Pixcels * info.ColorDepthBytes; }
/* Image Resources Section * Len Description Value * 4 Length * n Resource Block Data */ /* Image Resource Blocks * Len Description Value * 4 Signature '8BIM' * 2 Resource Id * n Name * 4 Resource Data Length * n Resource Data */ private static void ReadImageResources(ref PsdInfo info, PSDReader reader) { var length = reader.ReadInt32(); short id; int len; info.TransparencyIndex = -1; long pos = reader.Position + length; while (reader.Position < pos) { // Signature if (reader.ReadByte() != 0x38 || reader.ReadByte() != 0x42 || reader.ReadByte() != 0x49 || reader.ReadByte() != 0x4D) { throw new NotSupportedException(); } // Resource Id id = reader.ReadInt16(); // Name len = reader.ReadByte(); if (len > 0) { if ((len % 2) != 0) { len = reader.ReadByte(); } reader.Position += len; } reader.Position += 1; // Data Length len = reader.ReadInt32(); if (len % 2 != 0) { len++; } switch (id) { case 1005: // ResolutionInfo structure info.DpiX = reader.ReadInt16(); reader.Position += 6; info.DpiY = reader.ReadInt16(); reader.Position += 6; break; case 1047: // Transparency Index. 2 bytes for the index of transparent color, if any. info.TransparencyIndex = reader.ReadInt16(); break; default: reader.Position += len; break; } } }