Пример #1
0
        ////////////////////////////////////////////////////////////////////
        // Parse inline image
        ////////////////////////////////////////////////////////////////////

        internal PdfOp ParseInlineImage()
        {
            // create empty dictionary
            PdfDictionary ImageDict = ParseDictionary(true);

            // get image width
            if (!ImageDict.FindValue("/W").GetInteger(out int Width) || Width <= 0)
            {
                throw new ApplicationException("Parse inline image: Width error");
            }

            // get image height
            if (!ImageDict.FindValue("/H").GetInteger(out int Height) || Height <= 0)
            {
                throw new ApplicationException("Parse inline image: Height error");
            }

            // get image bits per component
            if (!ImageDict.FindValue("/BPC").GetInteger(out int BitPerComp) ||
                BitPerComp != 1 && BitPerComp != 2 && BitPerComp != 4 && BitPerComp != 8)
            {
                throw new ApplicationException("Parse inline image: BPC error");
            }

            int Components = 0;

            // get color space
            string ColorSpace = ImageDict.FindValue("/CS").ToName;

            if (ColorSpace != null)
            {
                // number of components
                if (ColorSpace == "/G")
                {
                    Components = 1;
                }
                else if (ColorSpace == "/RGB")
                {
                    Components = 3;
                }
                else if (ColorSpace == "/CMYK")
                {
                    Components = 4;
                }
                else
                {
                    throw new ApplicationException("Parse inline image: ColorSpace error");
                }
            }

            ImageDict.FindValue("/IM").GetBoolean(out bool IM);
            if (IM)
            {
                Components = 1;
            }

            PdfBase Filter = ImageDict.FindValue("/F");

            if (!Filter.IsEmpty)
            {
                throw new ApplicationException("Parse inline image: No filter support");
            }

            // no ASCIIHexDecode AHx or ASCII85Decode A85
            if (!PdfBase.IsWhiteSpace(NextChar))
            {
                throw new ApplicationException("Parse inline image: ID must be followed by white space");
            }

            // image width in bytes
            int WidthBytes = 0;

            switch (BitPerComp)
            {
            case 1:
                WidthBytes = (Width + 7) / 8;
                break;

            case 2:
                WidthBytes = (Width + 3) / 4;
                break;

            case 4:
                WidthBytes = (Width + 1) / 2;
                break;

            case 8:
                WidthBytes = Width;
                break;
            }

            // image size
            int Size = WidthBytes * Height * Components;

            // image stream
            byte[] ImageStream = new byte[Size];

            for (int Index = 0; Index < Size; Index++)
            {
                // read next character
                NextChar = ReadChar();

                // end of file error
                if (NextChar == EOF)
                {
                    throw new ApplicationException("Invalid inline image (end of contents)");
                }

                // save it in bitmap
                ImageStream[Index] = (byte)NextChar;
            }

            // get termination
            NextChar = ReadChar();
            SkipWhiteSpace();
            if (NextChar != 'E' || ReadChar() != 'I')
            {
                throw new ApplicationException("Parse inline image: EI is missing");
            }
            NextChar = ReadChar();

            PdfOp InlineImage = new PdfOp(Operator.BeginInlineImage);

            InlineImage.ArgumentArray = new PdfBase[] { ImageDict, new PdfString(ImageStream) };

            // exit
            return(InlineImage);
        }
        /// <summary>
        /// Apply predictor decode
        /// </summary>
        /// <param name="InputBuffer">Input buffer</param>
        /// <returns>Output buffer</returns>
        internal byte[] PredictorDecode
        (
            byte[]          InputBuffer
        )
        {
            // test for /DecodeParams
            PdfDictionary DecodeParms = Dictionary.FindValue("/DecodeParms").ToDictionary;

            // none found
            if (DecodeParms == null)
            {
                return(InputBuffer);
            }

            // look for predictor code. if default (none or 1) do nothing
            if (!DecodeParms.FindValue("/Predictor").GetInteger(out int Predictor) || Predictor == 1)
            {
                return(InputBuffer);
            }

            // we only support predictor code 12
            if (Predictor != 12)
            {
                return(null);
            }

            // get width
            DecodeParms.FindValue("/Columns").GetInteger(out int Width);
            if (Width < 0)
            {
                throw new ApplicationException("/DecodeParms /Columns is negative");
            }
            if (Width == 0)
            {
                Width = 1;
            }

            // calculate rows
            int Rows = InputBuffer.Length / (Width + 1);

            if (Rows < 1)
            {
                throw new ApplicationException("/DecodeParms /Columns is greater than stream length");
            }

            // create output buffer
            byte[] OutputBuffer = new byte[Rows * Width];

            // reset pointers
            int InPtr      = 1;
            int OutPtr     = 0;
            int OutPrevPtr = 0;

            // first row (ignore filter)
            while (OutPtr < Width)
            {
                OutputBuffer[OutPtr++] = InputBuffer[InPtr++];
            }

            // decode loop
            for (int Row = 1; Row < Rows; Row++)
            {
                // first byte is filter
                int Filter = InputBuffer[InPtr++];

                // we support PNG filter up only
                if (Filter != 2)
                {
                    throw new ApplicationException("/DecodeParms Only supported filter is 2");
                }

                // convert input to output
                for (int Index = 0; Index < Width; Index++)
                {
                    OutputBuffer[OutPtr++] = (byte)(OutputBuffer[OutPrevPtr++] + InputBuffer[InPtr++]);
                }
            }

            return(OutputBuffer);
        }