Example #1
0
        private static ReadOnlyCollection <Brush> DecodeVersion6(BinaryReverseReader reader, short majorVersion)
        {
            short minorVersion = reader.ReadInt16();
            long  unusedDataLength;

            switch (minorVersion)
            {
            case 1:
                // Skip the Int16 bounds rectangle and the unknown Int16.
                unusedDataLength = 10L;
                break;

            case 2:
                // Skip the unknown bytes.
                unusedDataLength = 264L;
                break;

            default:
                throw new FormatException(string.Format(CultureInfo.CurrentCulture, Resources.UnsupportedABRSubVersion, majorVersion, minorVersion));
            }

            BrushSectionParser parser = new BrushSectionParser(reader);

            List <Brush> brushes = new List <Brush>(parser.SampledBrushes.Count);

            long sampleSectionOffset = parser.SampleSectionOffset;

            if (parser.SampledBrushes.Count > 0 && sampleSectionOffset >= 0)
            {
                reader.BaseStream.Position = sampleSectionOffset;

                uint sectionLength = reader.ReadUInt32();

                long sectionEnd = reader.BaseStream.Position + sectionLength;

                while (reader.BaseStream.Position < sectionEnd)
                {
                    uint brushLength = reader.ReadUInt32();

                    // The brush data is padded to 4 byte alignment.
                    long paddedBrushLength = ((long)brushLength + 3) & ~3;

                    long endOffset = reader.BaseStream.Position + paddedBrushLength;

                    string tag = reader.ReadPascalString();

                    // Skip the unneeded data that comes before the Int32 bounds rectangle.
                    reader.BaseStream.Position += unusedDataLength;

                    Rectangle bounds = reader.ReadInt32Rectangle();
                    if (bounds.Width <= 0 || bounds.Height <= 0)
                    {
                        // Skip any brushes that have invalid dimensions.
                        reader.BaseStream.Position += (endOffset - reader.BaseStream.Position);
                        continue;
                    }

                    short depth = reader.ReadInt16();
                    if (depth != 8 && depth != 16)
                    {
                        // Skip any brushes with an unknown bit depth.
                        reader.BaseStream.Position += (endOffset - reader.BaseStream.Position);
                        continue;
                    }

                    SampledBrush sampledBrush = parser.SampledBrushes.FindBrush(tag);
                    if (sampledBrush != null)
                    {
                        AbrImageCompression compression = (AbrImageCompression)reader.ReadByte();

                        int height = bounds.Height;
                        int width  = bounds.Width;

                        byte[] alphaData = null;

                        if (compression == AbrImageCompression.RLE)
                        {
                            short[] compressedRowLengths = new short[height];

                            for (int y = 0; y < height; y++)
                            {
                                compressedRowLengths[y] = reader.ReadInt16();
                            }

                            int alphaDataSize = width * height;
                            int bytesPerRow   = width;

                            if (depth == 16)
                            {
                                alphaDataSize *= 2;
                                bytesPerRow   *= 2;
                            }

                            alphaData = new byte[alphaDataSize];

                            for (int y = 0; y < height; y++)
                            {
                                RLEHelper.DecodedRow(reader, alphaData, y * width, bytesPerRow);
                            }
                        }
                        else
                        {
                            int alphaDataSize = width * height;

                            if (depth == 16)
                            {
                                alphaDataSize *= 2;
                            }

                            alphaData = reader.ReadBytes(alphaDataSize);
                        }

                        var brush = CreateSampledBrush(width, height, depth, alphaData, sampledBrush.Name, sampledBrush.Spacing);

                        brushes.Add(brush);

                        // Some brushes only store the largest item and scale it down.
                        var scaledBrushes = parser.SampledBrushes.Where(i => i.Tag.Equals(tag, StringComparison.Ordinal) && i.Diameter < sampledBrush.Diameter);
                        if (scaledBrushes.Any())
                        {
                            int originalWidth  = brush.Surface.Width;
                            int originalHeight = brush.Surface.Height;

                            foreach (var item in scaledBrushes.OrderByDescending(p => p.Diameter))
                            {
                                Size size = ComputeBrushSize(originalWidth, originalHeight, item.Diameter);

                                Brush scaledBrush = new Brush(size.Width, size.Height, item.Name, item.Spacing);
                                scaledBrush.Surface.FitSurface(ResamplingAlgorithm.SuperSampling, brush.Surface);

                                brushes.Add(scaledBrush);
                            }
                        }
                    }

                    long remaining = endOffset - reader.BaseStream.Position;
                    // Skip any remaining bytes until the next sampled brush.
                    if (remaining > 0)
                    {
                        reader.BaseStream.Position += remaining;
                    }
                }
            }

            return(brushes.AsReadOnly());
        }
Example #2
0
        private static ReadOnlyCollection <Brush> DecodeVersion1(BinaryReverseReader reader, short version)
        {
            short count = reader.ReadInt16();

            List <Brush> brushes = new List <Brush>(count);

            for (int i = 0; i < count; i++)
            {
                AbrBrushType type = (AbrBrushType)reader.ReadInt16();
                int          size = reader.ReadInt32();

                long endOffset = reader.BaseStream.Position + size;

#if DEBUG
                System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Brush: {0}, type: {1}, size: {2} bytes", i, type, size));
#endif
                if (type == AbrBrushType.Computed)
                {
#if DEBUG
                    int   misc    = reader.ReadInt32();
                    short spacing = reader.ReadInt16();

                    string name = string.Empty;
                    if (version == 2)
                    {
                        name = reader.ReadUnicodeString();
                    }

                    short diameter  = reader.ReadInt16();
                    short roundness = reader.ReadInt16();
                    short angle     = reader.ReadInt16();
                    short hardness  = reader.ReadInt16();
#else
                    reader.BaseStream.Position += size;
#endif
                }
                else if (type == AbrBrushType.Sampled)
                {
                    int   misc    = reader.ReadInt32();
                    short spacing = reader.ReadInt16();

                    string name = string.Empty;
                    if (version == 2)
                    {
                        name = reader.ReadUnicodeString();
                    }

                    bool antiAlias = reader.ReadByte() != 0;

                    // Skip the Int16 bounds.
                    reader.BaseStream.Position += 8L;

                    Rectangle bounds = reader.ReadInt32Rectangle();
                    if (bounds.Width <= 0 || bounds.Height <= 0)
                    {
                        // Skip any brushes that have invalid dimensions.
                        reader.BaseStream.Position += (endOffset - reader.BaseStream.Position);
                        continue;
                    }

                    short depth = reader.ReadInt16();

                    if (depth != 8)
                    {
                        // The format specs state that brushes must be 8-bit, skip any that are not.
                        reader.BaseStream.Position += (endOffset - reader.BaseStream.Position);
                        continue;
                    }
                    int height = bounds.Height;
                    int width  = bounds.Width;

                    int rowsRemaining = height;
                    int rowsRead      = 0;

                    byte[] alphaData = new byte[width * height];
                    do
                    {
                        // Sampled brush data is broken into repeating chunks for brushes taller that 16384 pixels.
                        int chunkHeight = Math.Min(rowsRemaining, 16384);
                        // The format specs state that compression is stored as a 2-byte field, but it is written as a 1-byte field in actual files.
                        AbrImageCompression compression = (AbrImageCompression)reader.ReadByte();

                        if (compression == AbrImageCompression.RLE)
                        {
                            short[] compressedRowLengths = new short[height];

                            for (int y = 0; y < height; y++)
                            {
                                compressedRowLengths[y] = reader.ReadInt16();
                            }

                            for (int y = 0; y < chunkHeight; y++)
                            {
                                int row = rowsRead + y;
                                RLEHelper.DecodedRow(reader, alphaData, row * width, width);
                            }
                        }
                        else
                        {
                            int rowByteOffset  = rowsRead * width;
                            int numBytesToRead = chunkHeight * width;
                            int numBytesRead   = 0;
                            while (numBytesToRead > 0)
                            {
                                // Read may return anything from 0 to numBytesToRead.
                                int n = reader.Read(alphaData, rowByteOffset + numBytesRead, numBytesToRead);
                                // The end of the file is reached.
                                if (n == 0)
                                {
                                    break;
                                }
                                numBytesRead   += n;
                                numBytesToRead -= n;
                            }
                        }

                        rowsRemaining -= 16384;
                        rowsRead      += 16384;
                    } while (rowsRemaining > 0);

                    brushes.Add(CreateSampledBrush(width, height, depth, alphaData, name, spacing));
                }
                else
                {
                    // Skip any unknown brush types.
                    reader.BaseStream.Position += size;
                }
            }

            return(brushes.AsReadOnly());
        }