public DirectoryList Extract(SequentialReader reader)
        {
            var directory = new PsdHeaderDirectory();

            // FILE HEADER SECTION

            try
            {
                var signature = reader.GetInt32();
                var version   = reader.GetUInt16();

                if (signature != 0x38425053)
                {
                    // "8BPS"
                    directory.AddError("Invalid PSD file signature");
                }
                else if (version != 1 && version != 2)
                {
                    directory.AddError("Invalid PSD file version (must be 1 or 2)");
                }
                else
                {
                    // 6 reserved bytes are skipped here.  They should be zero.
                    reader.Skip(6);
                    var channelCount = reader.GetUInt16();
                    directory.Set(PsdHeaderDirectory.TagChannelCount, channelCount);
                    // even though this is probably an unsigned int, the max height in practice is 300,000
                    var imageHeight = reader.GetInt32();
                    directory.Set(PsdHeaderDirectory.TagImageHeight, imageHeight);
                    // even though this is probably an unsigned int, the max width in practice is 300,000
                    var imageWidth = reader.GetInt32();
                    directory.Set(PsdHeaderDirectory.TagImageWidth, imageWidth);
                    var bitsPerChannel = reader.GetUInt16();
                    directory.Set(PsdHeaderDirectory.TagBitsPerChannel, bitsPerChannel);
                    var colorMode = reader.GetUInt16();
                    directory.Set(PsdHeaderDirectory.TagColorMode, colorMode);
                }
            }
            catch (IOException)
            {
                directory.AddError("Unable to read PSD header");
            }

            if (directory.HasError)
            {
                return new Directory[] { directory }
            }
            ;

            IEnumerable <Directory>?photoshopDirectories = null;

            try
            {
                // COLOR MODE DATA SECTION

                // Only indexed color and duotone (see the mode field in the File header section) have color mode data.
                // For all other modes, this section is just the 4-byte length field, which is set to zero.
                //
                // Indexed color images: length is 768; color data contains the color table for the image,
                //                       in non-interleaved order.
                // Duotone images: color data contains the duotone specification (the format of which is not documented).
                //                 Other applications that read Photoshop files can treat a duotone image as a gray    image,
                //                 and just preserve the contents of the duotone information when reading and writing the
                //                 file.
                var colorModeSectionLength = reader.GetUInt32();

                reader.Skip(colorModeSectionLength);

                // IMAGE RESOURCES SECTION

                var imageResourcesSectionLength = reader.GetUInt32();
                Debug.Assert(imageResourcesSectionLength <= int.MaxValue);
                photoshopDirectories = new PhotoshopReader().Extract(reader, (int)imageResourcesSectionLength);
            }
            catch (IOException)
            {
            }

            var directories = new List <Directory> {
                directory
            };

            if (photoshopDirectories != null)
            {
                directories.AddRange(photoshopDirectories);
            }

            // LAYER AND MASK INFORMATION SECTION (skipped)

            // IMAGE DATA SECTION (skipped)

            return(directories);
        }
    }
            Extract([NotNull] SequentialReader reader)
        {
            var directory = new PsdHeaderDirectory();

            // FILE HEADER SECTION

            try
            {
                var signature = reader.GetInt32();
                var version = reader.GetUInt16();

                if (signature != 0x38425053)
                {
                    // "8BPS"
                    directory.AddError("Invalid PSD file signature");
                }
                else if (version != 1 && version != 2)
                {
                    directory.AddError("Invalid PSD file version (must be 1 or 2)");
                }
                else
                {
                    // 6 reserved bytes are skipped here.  They should be zero.
                    reader.Skip(6);
                    var channelCount = reader.GetUInt16();
                    directory.Set(PsdHeaderDirectory.TagChannelCount, channelCount);
                    // even though this is probably an unsigned int, the max height in practice is 300,000
                    var imageHeight = reader.GetInt32();
                    directory.Set(PsdHeaderDirectory.TagImageHeight, imageHeight);
                    // even though this is probably an unsigned int, the max width in practice is 300,000
                    var imageWidth = reader.GetInt32();
                    directory.Set(PsdHeaderDirectory.TagImageWidth, imageWidth);
                    var bitsPerChannel = reader.GetUInt16();
                    directory.Set(PsdHeaderDirectory.TagBitsPerChannel, bitsPerChannel);
                    var colorMode = reader.GetUInt16();
                    directory.Set(PsdHeaderDirectory.TagColorMode, colorMode);
                }
            }
            catch (IOException)
            {
                directory.AddError("Unable to read PSD header");
            }

            if (directory.HasError)
                return new[] { directory };

            IEnumerable<Directory> photoshopDirectories = null;

            try
            {
                // COLOR MODE DATA SECTION

                // Only indexed color and duotone (see the mode field in the File header section) have color mode data.
                // For all other modes, this section is just the 4-byte length field, which is set to zero.
                //
                // Indexed color images: length is 768; color data contains the color table for the image,
                //                       in non-interleaved order.
                // Duotone images: color data contains the duotone specification (the format of which is not documented).
                //                 Other applications that read Photoshop files can treat a duotone image as a gray    image,
                //                 and just preserve the contents of the duotone information when reading and writing the
                //                 file.
                var colorModeSectionLength = reader.GetUInt32();
                reader.Skip(colorModeSectionLength);

                // IMAGE RESOURCES SECTION

                var imageResourcesSectionLength = reader.GetUInt32();
                Debug.Assert(imageResourcesSectionLength <= int.MaxValue);
                photoshopDirectories = new PhotoshopReader().Extract(reader, (int)imageResourcesSectionLength);
            }
            catch (IOException)
            {
            }

            var directories = new List<Directory> { directory };

            if (photoshopDirectories != null)
                directories.AddRange(photoshopDirectories);

            // LAYER AND MASK INFORMATION SECTION (skipped)

            // IMAGE DATA SECTION (skipped)

            return directories;
        }