예제 #1
0
        public static Byte[] Decode(Byte[] inp, PdfDictionary prms)
        {
            if (prms == null)
            {
                return(inp);
            }
            var predObj = prms.Get <PdfInteger>("Predictor");

            if (predObj == null)
            {
                return(inp);
            }
            Int32 predictor = predObj.Value;

            if (predictor < 10 && predictor != 2)
            {
                return(inp);
            }
            Int32 width   = 1;
            var   colsObj = prms.Get <PdfInteger>("Columns");

            if (colsObj != null)
            {
                width = colsObj.Value;
            }
            Int32        colors        = 1; // TODO from DICT
            Int32        bpc           = 8; // TODO from DICT
            MemoryStream dataStream    = new MemoryStream(inp);
            MemoryStream fout          = new MemoryStream(inp.Length);
            Int32        bytesPerPixel = colors * bpc / 8;
            Int32        bytesPerRow   = (colors * width * bpc + 7) / 8;

            Byte[] curr  = new Byte[bytesPerRow];
            Byte[] prior = new Byte[bytesPerRow];

            if (predictor == 2)
            {
                if (bpc == 8)
                {
                    Int32 numRows = inp.Length / bytesPerRow;
                    for (Int32 row = 0; row < numRows; row++)
                    {
                        Int32 rowStart = row * bytesPerRow;
                        for (Int32 col = 0 + bytesPerPixel; col < bytesPerRow; col++)
                        {
                            inp[rowStart + col] = (Byte)(inp[rowStart + col] + inp[rowStart + col - bytesPerPixel]);
                        }
                    }
                }
                return(inp);
            }

            // Decode the (sub)image row-by-row
            while (true)
            {
                // Read the filter type byte and a row of data
                Int32 filter = 0;
                try
                {
                    filter = dataStream.ReadByte();
                    if (filter < 0)
                    {
                        return(fout.ToArray());
                    }
                    Int32 tot = 0;
                    while (tot < bytesPerRow)
                    {
                        Int32 n = dataStream.Read(curr, tot, bytesPerRow - tot);
                        if (n <= 0)
                        {
                            return(fout.ToArray());
                        }
                        tot += n;
                    }
                }
                catch
                {
                    return(fout.ToArray());
                }

                switch (filter)
                {
                case 0:                         //PNG_FILTER_NONE
                    break;

                case 1:                         //PNG_FILTER_SUB
                    for (Int32 i = bytesPerPixel; i < bytesPerRow; i++)
                    {
                        curr[i] += curr[i - bytesPerPixel];
                    }
                    break;

                case 2:                         //PNG_FILTER_UP
                    for (Int32 i = 0; i < bytesPerRow; i++)
                    {
                        curr[i] += prior[i];
                    }
                    break;

                case 3:                         //PNG_FILTER_AVERAGE
                    for (Int32 i = 0; i < bytesPerPixel; i++)
                    {
                        curr[i] += (Byte)(prior[i] / 2);
                    }
                    for (Int32 i = bytesPerPixel; i < bytesPerRow; i++)
                    {
                        curr[i] += (Byte)(((curr[i - bytesPerPixel] & 0xff) + (prior[i] & 0xff)) / 2);
                    }
                    break;

                case 4:                         //PNG_FILTER_PAETH
                    for (Int32 i = 0; i < bytesPerPixel; i++)
                    {
                        curr[i] += prior[i];
                    }

                    for (Int32 i = bytesPerPixel; i < bytesPerRow; i++)
                    {
                        Int32 a = curr[i - bytesPerPixel] & 0xff;
                        Int32 b = prior[i] & 0xff;
                        Int32 c = prior[i - bytesPerPixel] & 0xff;

                        Int32 p  = a + b - c;
                        Int32 pa = Math.Abs(p - a);
                        Int32 pb = Math.Abs(p - b);
                        Int32 pc = Math.Abs(p - c);

                        Int32 ret;

                        if ((pa <= pb) && (pa <= pc))
                        {
                            ret = a;
                        }
                        else if (pb <= pc)
                        {
                            ret = b;
                        }
                        else
                        {
                            ret = c;
                        }
                        curr[i] += (Byte)(ret);
                    }
                    break;

                default:
                    // Error -- uknown filter type
                    throw new LexerException("png.filter.unknown");
                }
                fout.Write(curr, 0, curr.Length);

                // Swap curr and prior
                Byte[] tmp = prior;
                prior = curr;
                curr  = tmp;
            }
        }