Beispiel #1
0
        internal static void ReadChunk(Stream PngImageData, TPdfPngData OutData)
        {
            if (PngImageData.Length - PngImageData.Position < 3 * 4)
            {
                PngImageData.Position = PngImageData.Length;
                return;
            }
            UInt32 Len       = GetUInt32(PngImageData);
            UInt32 ChunkType = GetUInt32(PngImageData);

            switch ((TChunkType)ChunkType)
            {
            case TChunkType.IHDR: ReadIHDR(Len, PngImageData, OutData); break;

            case TChunkType.IDAT: ReadIDAT(Len, PngImageData, OutData); break;

            case TChunkType.PLTE: ReadPLTE(Len, PngImageData, OutData); break;

            case TChunkType.tRNS: ReadtRNS(Len, PngImageData, OutData); break;

            default: PngImageData.Position += Len; break;                  //ignore chunk
            }

            /*UInt32 CRC = */ GetUInt32(PngImageData);
        }
Beispiel #2
0
 internal TPngInformation(TPdfPngData Data)
 {
     FHeight            = Data.Height;
     FWidth             = Data.Width;
     FBitDepth          = Data.BitDepth;
     FColorType         = Data.ColorType;
     FCompressionMethod = Data.CompressionMethod;
     FFilterMethod      = Data.FilterMethod;
     FInterlaceMethod   = Data.InterlaceMethod;
 }
Beispiel #3
0
        internal static void ReadIHDR(UInt32 Len, Stream PngImageData, TPdfPngData OutData)
        {
            OutData.Width  = GetUInt32(PngImageData);
            OutData.Height = GetUInt32(PngImageData);

            OutData.BitDepth          = (byte)PngImageData.ReadByte();
            OutData.ColorType         = (byte)PngImageData.ReadByte();
            OutData.CompressionMethod = (byte)PngImageData.ReadByte();
            OutData.FilterMethod      = (byte)PngImageData.ReadByte();
            OutData.InterlaceMethod   = (byte)PngImageData.ReadByte();
        }
Beispiel #4
0
        /// <summary>
        /// Returns the basic information on a png file. Null if the file is not PNG.
        /// </summary>
        /// <param name="PngImageData">Stream with the image data.</param>
        /// <returns>Null if the image is invalid, or the image properties otherwise.</returns>
        public static TPngInformation GetPngInfo(Stream PngImageData)
        {
            if (!CheckHeaders(PngImageData))
            {
                return(null);
            }

            TPdfPngData OutData = new TPdfPngData(null);

            ReadChunk(PngImageData, OutData);
            return(new TPngInformation(OutData));
        }
Beispiel #5
0
        internal static void ReadIDAT(UInt32 Len, Stream PngImageData, TPdfPngData OutData)
        {
            const int size = 4096;

            byte[] bytes     = new byte[size];
            int    Remaining = (int)Len;
            int    numBytes;

            while (Remaining > 0)
            {
                numBytes = PngImageData.Read(bytes, 0, Math.Min(size, Remaining));
                OutData.Data.Write(bytes, 0, numBytes);
                Remaining -= numBytes;
            }
        }
Beispiel #6
0
        internal static bool IsOkPng(Stream PngImageData)
        {
            if (!CheckHeaders(PngImageData))
            {
                return(false);
            }

            TPdfPngData OutData = new TPdfPngData(null);

            ReadChunk(PngImageData, OutData);
            if (OutData.InterlaceMethod != 0 || OutData.BitDepth > 8)
            {
                return(false);
            }

            return(true);
        }
Beispiel #7
0
        internal static void ProcessPng(Stream PngImageData, TPdfPngData OutData)
        {
            if (!CheckHeaders(PngImageData))
            {
                PdfMessages.ThrowException(PdfErr.ErrInvalidPngImage);
            }

            while (PngImageData.Position < PngImageData.Length)
            {
                ReadChunk(PngImageData, OutData);
            }

            if (OutData.ColorType == 4)
            {
                SuppressAlpha(OutData, 1);
            }

            if (OutData.ColorType == 6)
            {
                SuppressAlpha(OutData, 3);
            }
        }
Beispiel #8
0
        private void ReadPng(Stream Ms)
        {
            using (MemoryStream OutMs = new MemoryStream())
            {
                TPdfPngData ImgParsedData = new TPdfPngData(OutMs);
                TPdfPng.ProcessPng(Ms, ImgParsedData);

                FImage            = OutMs.ToArray();
                FImageWidth       = (int)ImgParsedData.Width;
                FImageHeight      = (int)ImgParsedData.Height;
                FBitsPerComponent = ImgParsedData.BitDepth;

                if (FBitsPerComponent == 16)
                {
                    PdfMessages.ThrowException(PdfErr.ErrInvalidPngImage);
                }

                int Colors = 1;
                switch (ImgParsedData.ColorType)
                {
                case 0:                         //GrayScale
                    FColorSpace = TPdfTokens.GetString(TPdfToken.DeviceGrayName);
                    if (ImgParsedData.tRNS != null && ImgParsedData.tRNS.Length >= 2)
                    {
                        FMask =
                            TPdfTokens.GetString(TPdfToken.OpenArray) +
                            String.Format(CultureInfo.InvariantCulture, "{0} {0}", (ImgParsedData.tRNS[0] << 8) + ImgParsedData.tRNS[1]) +
                            TPdfTokens.GetString(TPdfToken.CloseArray);
                    }

                    break;

                case 2:                          //TrueColor
                    FColorSpace = TPdfTokens.GetString(TPdfToken.DeviceRGBName);
                    Colors      = 3;
                    if (ImgParsedData.tRNS != null && ImgParsedData.tRNS.Length >= 6)
                    {
                        FMask =
                            TPdfTokens.GetString(TPdfToken.OpenArray) +
                            String.Format(CultureInfo.InvariantCulture,
                                          "{0} {0} {1} {1} {2} {2}", (ImgParsedData.tRNS[0] << 8) + ImgParsedData.tRNS[1],
                                          (ImgParsedData.tRNS[2] << 8) + ImgParsedData.tRNS[3],
                                          (ImgParsedData.tRNS[4] << 8) + ImgParsedData.tRNS[5]
                                          ) +
                            TPdfTokens.GetString(TPdfToken.CloseArray);
                    }
                    break;

                case 3:                         //Indexed Color
                    FColorSpace = GetPalette(ImgParsedData.PLTE);
                    if (ImgParsedData.tRNS != null && ImgParsedData.tRNS.Length > 0)
                    {
                        ImgParsedData.SMask = TPdfPng.GetIndexedSMask(FImage, FImageWidth, FImageHeight, ImgParsedData.tRNS, FBitsPerComponent);
                    }
                    break;

                case 4:                          //GrayScale + Alpha
                    FColorSpace = TPdfTokens.GetString(TPdfToken.DeviceGrayName);
                    break;

                case 6:                         //TrueColor + Alpha
                    FColorSpace = TPdfTokens.GetString(TPdfToken.DeviceRGBName);
                    Colors      = 3;
                    break;

                default: PdfMessages.ThrowException(PdfErr.ErrInvalidPngImage); break;
                }

                FSMask     = ImgParsedData.SMask;
                OneBitMask = ImgParsedData.OneBitMask;

                if (ImgParsedData.InterlaceMethod != 0)
                {
                    PdfMessages.ThrowException(PdfErr.ErrInvalidPngImage);
                }

                FFilterName = TPdfTokens.GetString(TPdfToken.FlateDecodeName);

                FDecodeParmsName =
                    TPdfTokens.GetString(TPdfToken.StartDictionary) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.PredictorName) + " {0} ", 15) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.ColorsName) + " {0} ", Colors) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.BitsPerComponentName) + " {0} ", FBitsPerComponent) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.ColumnsName) + " {0} ", FImageWidth) +
                    TPdfTokens.GetString(TPdfToken.EndDictionary);

                FDecodeParmsSMask =
                    TPdfTokens.GetString(TPdfToken.StartDictionary) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.PredictorName) + " {0} ", 15) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.ColorsName) + " {0} ", 1) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.BitsPerComponentName) + " {0} ", 8) +
                    String.Format(CultureInfo.InvariantCulture, TPdfTokens.GetString(TPdfToken.ColumnsName) + " {0} ", FImageWidth) +
                    TPdfTokens.GetString(TPdfToken.EndDictionary);
            }
        }
Beispiel #9
0
        //We can't crop the image here, without changing the filters.
        private static void SuppressAlpha(TPdfPngData OutData, byte IntBytes)
        {
            using (TCompressor Cmp = new TCompressor())
            {
                using (TCompressor Cmp2 = new TCompressor())
                {
                    using (TCompressor Cmp3 = new TCompressor())
                    {
                        const int BuffLen = 4096;

                        bool MaskEmpty    = true;
                        bool IsOneBitMask = true;

                        int h = (int)OutData.Height;
                        int w = (int)OutData.Width;

#if (FRAMEWORK20 || ICSHARP) && !COMPACTFRAMEWORK
                        byte[] NewData    = new byte[BuffLen + IntBytes];
                        byte[] SMask      = new byte[BuffLen + 1];
                        byte[] OneBitMask = new byte[BuffLen + 1];
#else
                        sbyte[] NewData    = new sbyte[BuffLen + IntBytes];
                        sbyte[] SMask      = new sbyte[BuffLen + 1];
                        sbyte[] OneBitMask = new sbyte[BuffLen + 1];
#endif

                        using (MemoryStream InflatedStream = new MemoryStream())
                        {
                            unchecked
                            {
                                int NewDataPos    = 0;
                                int SMaskPos      = 0;
                                int OneBitMaskPos = 0;

                                Cmp.Inflate(OutData.Data.ToArray(), 0, InflatedStream);
                                InflatedStream.Position = 0;

                                Cmp.BeginDeflate();
                                Cmp2.BeginDeflate();
                                Cmp3.BeginDeflate();

                                OutData.Data.SetLength(0); Stream OutStream = OutData.Data;
                                using (MemoryStream SMaskStream = new MemoryStream())
                                {
                                    using (MemoryStream OneBitMaskStream = new MemoryStream())
                                    {
                                        int OneBitMaskInnerPos = 128;
                                        for (int r = 0; r < h; r++)
                                        {
                                            byte LastSMask = 0;

#if (FRAMEWORK20 || ICSHARP) && !COMPACTFRAMEWORK
                                            byte RowFilter = (byte)InflatedStream.ReadByte();
#else
                                            sbyte RowFilter = (sbyte)InflatedStream.ReadByte();
#endif

                                            #region inlined                                             //for speed on debug mode
                                            if (NewDataPos >= BuffLen)
                                            {
                                                Cmp.IncDeflate(NewData, 0, NewDataPos, OutStream);
                                                NewDataPos = 0;
                                            }
                                            if (SMaskPos >= BuffLen)
                                            {
                                                Cmp2.IncDeflate(SMask, 0, SMaskPos, SMaskStream);
                                                SMaskPos = 0;
                                            }
                                            if (OneBitMaskPos >= BuffLen)
                                            {
                                                Cmp3.IncDeflate(OneBitMask, 0, OneBitMaskPos, OneBitMaskStream);
                                                OneBitMaskPos             = 0;
                                                OneBitMask[OneBitMaskPos] = 0;
                                                OneBitMaskInnerPos        = 128;
                                            }
                                            #endregion

                                            NewData[NewDataPos++] = RowFilter;
                                            SMask[SMaskPos++]     = RowFilter;
                                            if (IsOneBitMask)
                                            {
                                                if (OneBitMaskInnerPos < 128)
                                                {
                                                    OneBitMaskPos++;                                                     //finish row.
                                                    OneBitMask[OneBitMaskPos] = 0;
                                                    OneBitMaskInnerPos        = 128;
                                                }
                                            }

                                            for (int c = 0; c < w; c++)
                                            {
                                                #region inlined                                                 //for speed on debug mode
                                                if (NewDataPos >= BuffLen)
                                                {
                                                    Cmp.IncDeflate(NewData, 0, NewDataPos, OutStream);
                                                    NewDataPos = 0;
                                                }
                                                if (SMaskPos >= BuffLen)
                                                {
                                                    Cmp2.IncDeflate(SMask, 0, SMaskPos, SMaskStream);
                                                    SMaskPos = 0;
                                                }
                                                if (OneBitMaskPos >= BuffLen)
                                                {
                                                    Cmp3.IncDeflate(OneBitMask, 0, OneBitMaskPos, OneBitMaskStream);
                                                    OneBitMaskPos             = 0;
                                                    OneBitMask[OneBitMaskPos] = 0;
                                                    OneBitMaskInnerPos        = 128;
                                                }
                                                #endregion

                                                for (int b = 0; b < IntBytes; b++)
#if (FRAMEWORK20 || ICSHARP) && !COMPACTFRAMEWORK
                                                {
                                                    NewData[NewDataPos++] = (byte)InflatedStream.ReadByte();
                                                }

                                                byte SMaskData = (byte)InflatedStream.ReadByte();
                                                SMask[SMaskPos++] = SMaskData;
#else
                                                {
                                                    NewData[NewDataPos++] = (sbyte)InflatedStream.ReadByte();
                                                }

                                                byte SMaskData = (byte)InflatedStream.ReadByte();
                                                SMask[SMaskPos++] = (sbyte)SMaskData;
#endif
                                                if (MaskEmpty && SMaskData != 0xFF)
                                                {
                                                    MaskEmpty = false;
                                                }

                                                if (IsOneBitMask)
                                                {
                                                    //SMaskData might have been flushed, and so contain invalid data.
                                                    //So we need a separate LastSMask for sub filter, and the whole last scanline for the others.
                                                    //As this is only an optimization (it will work the same with an SMask), we will only contemplate filters 0 and 1.
                                                    if (RowFilter == 1)                                                     //sub
                                                    {
                                                        unchecked { SMaskData += LastSMask; }
                                                        LastSMask = SMaskData;
                                                    }

                                                    if (RowFilter > 1 || (SMaskData != 0xFF && SMaskData != 0))
                                                    {
                                                        IsOneBitMask = false;
                                                    }
                                                    else
                                                    {
#if (FRAMEWORK20 || ICSHARP) && !COMPACTFRAMEWORK
                                                        OneBitMask[OneBitMaskPos] |= (byte)(~SMaskData & OneBitMaskInnerPos);
#else
                                                        OneBitMask[OneBitMaskPos] = (sbyte)((byte)OneBitMask[OneBitMaskPos] | (~(byte)SMaskData & OneBitMaskInnerPos));
#endif
                                                        if (OneBitMaskInnerPos > 1)
                                                        {
                                                            OneBitMaskInnerPos >>= 1;
                                                        }
                                                        else
                                                        {
                                                            OneBitMaskPos++;
                                                            OneBitMask[OneBitMaskPos] = 0;
                                                            OneBitMaskInnerPos        = 128;
                                                        }
                                                    }
                                                }
                                            }
                                        }


                                        #region inlined                                         //for speed on debug mode
                                        if (NewDataPos > 0)
                                        {
                                            Cmp.IncDeflate(NewData, 0, NewDataPos, OutStream);
                                            NewDataPos = 0;
                                        }
                                        if (SMaskPos > 0)
                                        {
                                            Cmp2.IncDeflate(SMask, 0, SMaskPos, SMaskStream);
                                            SMaskPos = 0;
                                        }
                                        if (OneBitMaskPos > 0)
                                        {
                                            if (OneBitMaskInnerPos < 128)
                                            {
                                                OneBitMaskPos++;                                                                       //finish row.
                                            }
                                            Cmp3.IncDeflate(OneBitMask, 0, OneBitMaskPos, OneBitMaskStream);
                                            OneBitMaskPos             = 0;
                                            OneBitMask[OneBitMaskPos] = 0;
                                        }
                                        #endregion

                                        Cmp.EndDeflate(OutStream);
                                        Cmp2.EndDeflate(SMaskStream);
                                        Cmp3.EndDeflate(OneBitMaskStream);

                                        if (!MaskEmpty)
                                        {
                                            if (IsOneBitMask)
                                            {
                                                OutData.OneBitMask = OneBitMaskStream.ToArray();
                                            }
                                            OutData.SMask = SMaskStream.ToArray();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #10
0
 internal static void ReadtRNS(UInt32 Len, Stream PngImageData, TPdfPngData OutData)
 {
     OutData.tRNS = new byte[Len];
     Sh.Read(PngImageData, OutData.tRNS, 0, (int)Len);
 }