コード例 #1
0
        private bool is_valid_chunk_order()
        {
            bool IDAT_reached = false;

            if (!PNG_Chunks[0].chunk_name.Equals("IHDR"))
            {
                return(false);
            }

            for (int i = 1; i < PNG_Chunks.Length; i++)
            {
                PNG_Chunk chunk = PNG_Chunks[i];
                if (chunk.chunk_name.Equals("IDAT"))
                {
                    IDAT_reached = true;
                }
                else if (chunk.chunk_name.Equals("IEND") &&
                         !IDAT_reached)
                {
                    return(false);
                }
                else if (IDAT_reached)
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #2
0
        private bool is_valid_chunk_count()
        {
            string[] chunk_names = { "IHDR",
                                     "tIME",
                                     "pHYs",
                                     "iCCP",
                                     "sRGB",
                                     "sBIT",
                                     "gAMA",
                                     "cHRM",
                                     "PLTE",
                                     "tRNS",
                                     "hIST",
                                     "bKGD",
                                     "IDAT",
                                     "IEND" };
            int[]    chunk_counts = new int[chunk_names.Length];

            // gather the counts
            for (int i = 0; i < PNG_Chunks.Length; i++)
            {
                PNG_Chunk chunk = PNG_Chunks[i];
                for (int j = 0; j < chunk_names.Length; j++)
                {
                    if (chunk.chunk_name.Equals(chunk_names[j]))
                    {
                        chunk_counts[j]++;
                        break;
                    }
                }
            }

            for (int i = 0; i < chunk_counts.Length; i++)
            {
                if (chunk_names[i].Equals("IHDR") ||
                    chunk_names[i].Equals("IEND"))
                {
                    if (chunk_counts[i] != 1)
                    {
                        return(false);
                    }
                }
                else if (chunk_names[i].Equals("IDAT"))
                {
                    if (chunk_counts[i] < 1)
                    {
                        return(false);
                    }
                }
                else
                {
                    if (chunk_counts[i] > 1)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #3
0
        private PNG_Chunk[] parse_chunk_string(string chunk_string)
        {
            // the layout of each chunk is supposed to be
            List <PNG_Chunk> chunk_list = new List <PNG_Chunk>();

            while (chunk_string.Length >= 12)
            {
                // interpret the chunks
                chunk_list.Add(new PNG_Chunk(ref chunk_string));
            }

            // turn the list into an array
            PNG_Chunk[] chunk_arr = new PNG_Chunk[chunk_list.Count];

            int index = 0;

            foreach (PNG_Chunk chunk in chunk_list)
            {
                chunk_arr[index++] = chunk;
            }

            return(chunk_arr);
        }
コード例 #4
0
        private void set_chunk_info()
        {
            PNG_Chunks = get_png_chunks();

            IDHR_p = null;
            PLTE_p = null;
            List <PNG_Chunk> IDAT_chunk_list = new List <PNG_Chunk>();

            IDAT_chunks_p = null;
            CRCs_p        = new byte[PNG_Chunks.Length][];

            PNG_Chunks = get_png_chunks();
            for (int i = 0; i < PNG_Chunks.Length; i++)
            {
                PNG_Chunk chunk = PNG_Chunks[i];
                if (chunk.chunk_name.Equals("IHDR"))
                {
                    if (IDHR_p != null)
                    {
                        throw new Exception("PNGFileReader: Multiple IDHR chunks detected.");
                    }
                    else
                    {
                        if (chunk.chunk_length != 13)
                        {
                            throw new Exception("PNGFileReader: Invalid IDHR chunk length detected.");
                        }
                        IDHR_p = chunk;
                    }
                }
                else if (chunk.chunk_name.Equals("PLTE_p"))
                {
                    if (PLTE_p != null)
                    {
                        throw new Exception("PNGFileReader: Multiple PLTE chunks detected.");
                    }
                    else
                    {
                        PLTE_p = chunk;
                    }
                }
                else if (chunk.chunk_name.Equals("IDAT"))
                {
                    IDAT_chunk_list.Add(chunk);
                }
                else if (chunk.is_IEND())
                {
                    // convert IDAT chunk list to chunk array
                    IDAT_chunks_p = new PNG_Chunk[IDAT_chunk_list.Count];
                    int index = 0;
                    foreach (PNG_Chunk IDAT_chunk in IDAT_chunk_list)
                    {
                        IDAT_chunks_p[index++] = IDAT_chunk;
                    }

                    if (i != PNG_Chunks.Length - 1)
                    {
                        throw new Exception("PNGFileReader: Extra chunks after the IEND chunk.");
                    }
                    break;
                }

                // add the CRC to the CRC array
                CRCs_p[i] = chunk.chunk_CRC;
            }

            set_IDHR_info();
            set_PLTE_info();
            set_IDAT_info();
        }
コード例 #5
0
        private void set_chunk_info()
        {
            PNG_Chunks = get_png_chunks();

            IDHR_p = null;
            PLTE_p = null;
            List<PNG_Chunk> IDAT_chunk_list = new List<PNG_Chunk>();
            IDAT_chunks_p = null;
            CRCs_p = new byte[PNG_Chunks.Length][];

            PNG_Chunks = get_png_chunks();
            for (int i = 0; i < PNG_Chunks.Length; i++)
            {
               PNG_Chunk chunk = PNG_Chunks[i];
               if (chunk.chunk_name.Equals("IHDR"))
               {
                  if(IDHR_p != null){
                     throw new Exception("PNGFileReader: Multiple IDHR chunks detected.");
                  }
                  else{
                     if (chunk.chunk_length != 13)
                     {
                        throw new Exception("PNGFileReader: Invalid IDHR chunk length detected.");
                     }
                     IDHR_p = chunk;
                  }
               }
               else if (chunk.chunk_name.Equals("PLTE_p"))
               {
                  if (PLTE_p != null)
                  {
                     throw new Exception("PNGFileReader: Multiple PLTE chunks detected.");
                  }
                  else
                  {
                     PLTE_p = chunk;
                  }
               }
               else if (chunk.chunk_name.Equals("IDAT"))
               {
                  IDAT_chunk_list.Add(chunk);
               }
               else if (chunk.is_IEND())
               {
                  // convert IDAT chunk list to chunk array
                  IDAT_chunks_p = new PNG_Chunk[IDAT_chunk_list.Count];
                  int index = 0;
                  foreach (PNG_Chunk IDAT_chunk in IDAT_chunk_list)
                  {
                     IDAT_chunks_p[index++] = IDAT_chunk;
                  }

                  if (i != PNG_Chunks.Length - 1)
                  {
                     throw new Exception("PNGFileReader: Extra chunks after the IEND chunk.");
                  }
                  break;
               }

               // add the CRC to the CRC array
               CRCs_p[i] = chunk.chunk_CRC;
            }

            set_IDHR_info();
            set_PLTE_info();
            set_IDAT_info();
        }
コード例 #6
0
        private PNG_Chunk[] parse_chunk_string(string chunk_string)
        {
            // the layout of each chunk is supposed to be
               List<PNG_Chunk> chunk_list = new List<PNG_Chunk>();

               while (chunk_string.Length >= 12)
               {
                  // interpret the chunks
                  chunk_list.Add(new PNG_Chunk(ref chunk_string));
               }

               // turn the list into an array
               PNG_Chunk[] chunk_arr = new PNG_Chunk[chunk_list.Count];

               int index = 0;
               foreach (PNG_Chunk chunk in chunk_list)
               {
                  chunk_arr[index++] = chunk;
               }

               return chunk_arr;
        }
コード例 #7
0
        // Methods
        /// <summary>
        /// Returns an array of PNG_Chunk objects that each store information
        /// related to that conceptual chunk. The chunks are constructed based
        /// off of the PNG specification and the raw PNG file data is passed in
        /// for parsing.
        ///
        /// AREAS OF IMPROVEMENT: The checking that the passed in data aligns with
        /// the specifications of a PNG file are rather light. If completely invalid
        /// data were to be passed in, the method would continue checking regardless
        /// of the many potential opportunities to discover the file is invalid and
        /// impossible to parse.
        /// </summary>
        /// <param name="file_data">The raw file data from the PNG format file.</param>
        /// <param name="is_valid_png_file">An uninitialized boolean that will determine
        /// whether the passed in data represents a valid PNG file.</param>
        /// <returns></returns>
        private PNG_Chunk[] get_png_chunks(byte[] file_data, out bool is_valid_png_file)
        {
            if (data_p == null)
            {
                is_valid_png_file = false;
                return(null);
            }

            Dictionary <string, int> chunk_map = new Dictionary <string, int>();

            System.Collections.Generic.List <PNG_Chunk> chunk_list =
                new System.Collections.Generic.List <PNG_Chunk>();

            string[] expected_headers      = { "IHDR", "PLTE", "IDAT", "IEND" };
            int      expected_header_index = 0;

            is_valid_png_file = true;
            bool palette_present = false;

            // move index past the file header (8 bytes)
            int byte_index = 8;

            while (byte_index < file_data.Length)
            {
                PNG_Chunk chunk = new PNG_Chunk(file_data, ref byte_index);
                if (chunk_map.ContainsKey(chunk.chunk_name))
                {
                    chunk_map[chunk.chunk_name] += 1;
                }
                else
                {
                    chunk_map.Add(chunk.chunk_name, 1);
                }

                if (chunk.chunk_name.Equals("PLTE"))
                {
                    palette_present = true;
                    if (chunk_map.ContainsKey("bKGD") ||
                        chunk_map.ContainsKey("hIST") ||
                        chunk_map.ContainsKey("tRNS"))
                    {
                        is_valid_png_file = false;
                    }
                    PLTE_p = chunk;
                }

                // handle flagging the cases where the png file
                // has an invalid ordering of the chunks
                if (expected_headers[expected_header_index].Equals("IHDR"))
                {
                    if (!chunk.chunk_name.Equals("IHDR"))
                    {
                        is_valid_png_file = false;
                    }
                    else
                    {
                        ++expected_header_index;
                        IHDR_p = chunk;
                    }
                }
                else if (expected_headers[expected_header_index].Equals("IDAT"))
                {
                    if (chunk.chunk_name.Equals("IEND"))
                    {
                        ++expected_header_index;
                        break;
                    }

                    string[] invalid_chunk_names = { "pHYs", "sPLT" };

                    for (int i = 0; i < invalid_chunk_names.Length; i++)
                    {
                        if (chunk.chunk_name.Equals(invalid_chunk_names[i]))
                        {
                            is_valid_png_file = false;
                        }
                        if (!is_valid_png_file)
                        {
                            break;
                        }
                    }
                }
                // handle PLTE sections
                else if (!expected_headers[expected_header_index].Equals("PLTE"))
                {
                    if (chunk.chunk_name.Equals("IDAT"))
                    {
                        ++expected_header_index;
                    }
                    // before the palette chunk is found...
                    else if (!palette_present)
                    {
                        string[] invalid_chunk_names = { "bKGD", "hIST", "tRNS" };

                        for (int i = 0; i < invalid_chunk_names.Length; i++)
                        {
                            if (chunk.chunk_name.Equals(invalid_chunk_names[i]))
                            {
                                is_valid_png_file = false;
                            }
                            if (!is_valid_png_file)
                            {
                                break;
                            }
                        }

                        if (chunk.chunk_name.Equals("iCCP") &&
                            chunk_map.ContainsKey("sBIT"))
                        {
                            is_valid_png_file = false;
                        }
                        else if (chunk.chunk_name.Equals("sBIT") &&
                                 chunk_map.ContainsKey("iCCP"))
                        {
                            is_valid_png_file = false;
                        }
                    }
                    // after the palette chunk is found
                    else
                    {
                        string[] invalid_chunk_names = { "cHRM", "gAMA", "iCCP", "sBIT", "sRGB" };

                        for (int i = 0; i < invalid_chunk_names.Length; i++)
                        {
                            if (chunk.chunk_name.Equals(invalid_chunk_names[i]))
                            {
                                is_valid_png_file = false;
                            }
                            if (!is_valid_png_file)
                            {
                                break;
                            }
                        }
                    }

                    // add the ancillary chunks coming before PLTE if they exist
                    if (chunk.chunk_name.Equals("cHRM"))
                    {
                        cHRM_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("gAMA"))
                    {
                        gAMA_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("iCCP"))
                    {
                        iCCP_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("sBIT"))
                    {
                        sBIT_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("sRGB"))
                    {
                        sRGB_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("bKGD"))
                    {
                        bKGD_p = chunk;
                        if (colour_type == Colour_Types.GREYSCALE ||
                            colour_type == Colour_Types.GREYSCALE_WITH_ALPHA)
                        {
                            bg_greyscale_p = chunk.chunk_data[1];
                        }
                        else if (colour_type == Colour_Types.TRUECOLOR ||
                                 colour_type == Colour_Types.TRUECOLOUR_WITH_ALPHA)
                        {
                            bg_R_p = chunk.chunk_data[1];
                            bg_G_p = chunk.chunk_data[3];
                            bg_B_p = chunk.chunk_data[5];
                        }
                        else
                        {
                            bg_palette_index_p = chunk.chunk_data[0];
                        }
                    }
                    else if (chunk.chunk_name.Equals("hIST"))
                    {
                        hIST_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("tRNS"))
                    {
                        tRNS_p = chunk;
                        if (colour_type == Colour_Types.GREYSCALE)
                        {
                            trns_grey_p = chunk.chunk_data[1];
                        }
                        else if (colour_type == Colour_Types.TRUECOLOR)
                        {
                            trns_R_p = chunk.chunk_data[1];
                            trns_G_p = chunk.chunk_data[3];
                            trns_B_p = chunk.chunk_data[5];
                        }
                    }
                    else if (chunk.chunk_name.Equals("pHYs"))
                    {
                        pHYs_p = chunk;
                    }
                    else if (chunk.chunk_name.Equals("sPLT"))
                    {
                        if (sPLT_p == null)
                        {
                            sPLT_p = new List <PNG_Chunk>();
                        }
                        sPLT_p.Add(chunk);
                    }
                }

                else
                {
                    // should have reached end of file already, there is extra
                    // junk at the end of the file
                }

                // check the CRC
                if (!is_correct_CRC(chunk.chunk_data, chunk.chunk_CRC))
                {
                    is_valid_png_file = false;
                    // break out of the loop...?
                }

                // add the chunk to the list
                chunk_list.Add(chunk);

                // if it's an ancillary chunk where order doesn't matter...record it
                if (chunk.chunk_name.Equals("tIME"))
                {
                    tIME_p = chunk;
                }
                else if (chunk.chunk_name.Equals("iTXt"))
                {
                    if (iTXt_p == null)
                    {
                        iTXt_p = new List <PNG_Chunk>();
                    }
                    iTXt_p.Add(chunk);
                }
                else if (chunk.chunk_name.Equals("tEXt"))
                {
                    if (tEXt_p == null)
                    {
                        tEXt_p = new List <PNG_Chunk>();
                    }
                    tEXt_p.Add(chunk);
                }
                else if (chunk.chunk_name.Equals("zTXt"))
                {
                    if (zTXt_p == null)
                    {
                        zTXt_p = new List <PNG_Chunk>();
                    }
                    zTXt_p.Add(chunk);
                }
            }

            // verify the # of each type of chunk
            // check the necessary ones first
            if (!chunk_map.ContainsKey("IHDR") ||
                chunk_map["IHDR"] != 1)
            {
                is_valid_png_file = false;
            }
            else if (!chunk_map.ContainsKey("IDAT") ||
                     chunk_map["IDAT"] < 1)
            {
                is_valid_png_file = false;
            }
            else if (!chunk_map.ContainsKey("IEND") ||
                     chunk_map["IEND"] != 1)
            {
                is_valid_png_file = false;
            }

            // check the ancillary chunks now that have 0 or 1 present
            string[] ancillary_names = { "tIME", "pHYs", "sBIT", "gAMA", "cHRM", "tRNS", "hIST", "bKGD",
                                         "PLTE" };
            foreach (string name in ancillary_names)
            {
                if (chunk_map.ContainsKey(name) &&
                    chunk_map[name] != 1)
                {
                    is_valid_png_file = false;
                    break;
                }
            }

            return(chunk_list.ToArray());
        }