{"id":135,"date":"2015-10-11T22:06:07","date_gmt":"2015-10-11T22:06:07","guid":{"rendered":"http:\/\/shajisoft.com\/shajisoft_wp\/?p=135"},"modified":"2016-01-07T19:49:15","modified_gmt":"2016-01-07T19:49:15","slug":"why-the-same-screenshot-is-saved-as-different-sized-pngs","status":"publish","type":"post","link":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/","title":{"rendered":"Why the Same Screenshot is Saved as PNG of Different Sizes by Different Tools"},"content":{"rendered":"<p>Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. I am going to show how to parse PNG files by using Python and try to figure out the reason for the difference.<br \/>\n<!--more--><\/p>\n<h2>Introduction<\/h2>\n<p>PNG is one of the commonly used image formats on the Internet. I used to save screenshots as PNG files. Unlike normal photos, screenshots of software applications usually have less colors. Using PNG, we can easily get images with good qualities and small file sizes. What&#8217;s more, it&#8217;s an open source format. For these reasons, I prefer PNG to other formats when creating screenshots.<\/p>\n<p>To be honest, I hadn&#8217;t paid much attention to the actual sizes of PNG files generated by software tools until recently when I need to create some PNG files for my blog and web pages. I mainly use two software tools to create screenshots which are Gimp and Windows Paint. I assumed that these tools would generate PNG files of optimal sizes. Whereas, I noticed recently that Gimp and Windows Paint generate PNG of different sizes of the same screenshot. Although there are no options about PNG format in Windows Paint, it still creates smaller PNG files than Gimp with the highest compression level selected. Then I was curious about the difference. So I did some experiments. In this post, I am going to share something I have learned about PNG from the process.<\/p>\n<h2>PNG format<\/h2>\n<p>Here, PNG refers to Portable Network Graphics. It&#8217;s a raster graphics file format. It was created as a replacement to GIF which uses a patented compression algorithm LZW. Please refer to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Portable_Network_Graphics\">Wikipedia<\/a> for more details of PNG format.<\/p>\n<p>Basically a PNG file starts with 8-byte header followed by chunks. Each chunk consists of four parts:<\/p>\n<ol>\n<li>Length of the chunk &#8211; 4 bytes<\/li>\n<li>Chunk type &#8211; 4 bytes<\/li>\n<li>Chunk data &#8211; (Length of the chunk) bytes<\/li>\n<li>CRC &#8211; 4 bytes<\/li>\n<\/ol>\n<p>That is, if the first four bytes of a chunk is 8192 as an integer, it means that the data of the chunk has 8192 bytes, and the full size of the chunk is 4+4+8192+4 = 8204 bytes.<\/p>\n<p>The second four bytes of a chunk indicates the type of the chunk, which is the case sensitive chunk type in ASCII format. A valid PNG file must have at least the following four critical chunk types:<\/p>\n<ol>\n<li>IHDR: Must be the first chunk. It contains the meta information about the image like width, height etc<\/li>\n<li>PLTE or sRGB: List of colors or the standard sRGB colors depending on the type of PNG<\/li>\n<li>IDAT: Image data<\/li>\n<li>IEND: Marks the end of the image<\/li>\n<\/ol>\n<p>A PNG file can contain multiple IDAT chunks. To decode a PNG file, all IDAT chunks in a PNG file will be concatenated and the combined IDAT data is decompressed to give the image.<\/p>\n<p>The following is a screenshot of TotalCommander Lister showing a PNG file in Hex format. We can see the first 8-byte header followed by IHDR and sRGB chunks:<\/p>\n<figure id=\"attachment_137\" aria-describedby=\"caption-attachment-137\" style=\"width: 698px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png-hex-lister-en-paint.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-137\" src=\"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png-hex-lister-en-paint.png\" alt=\"A PNG file shown in TotalCommander Lister in Hex\" width=\"698\" height=\"720\" \/><\/a><figcaption id=\"caption-attachment-137\" class=\"wp-caption-text\">A PNG file shown in Hex<\/figcaption><\/figure>\n<h2>Parse PNG file using Python<\/h2>\n<p>Firstly, let&#8217;s create a class to model chunks in a PNG file:<\/p>\n<pre title=\"A clsss in Python to model chunks in a PNG file\" class=\"lang:python decode:true \">class Chunk(object):\r\n\r\n    '''Definition of a chunk contained in a PNG file '''\r\n\r\n    def __init__(self, buf):\r\n        '''TODO: to be defined1. '''\r\n        self.__length = 0\r\n        self.__type = 0\r\n        self.__data = []\r\n        self.__crc = 0\r\n        self.__size = 0     # The total size of the chunk in bytes\r\n\r\n        if buf:\r\n            self.load(buf)\r\n\r\n    def load(self, buf):\r\n        '''Load the chunk from the given buffer.\r\n\r\n        @param buf List of bytes read from the PNG file\r\n        @return: None\r\n\r\n        '''\r\n        length_buf = binascii.hexlify(buf[:4])\r\n        #self.__length = int(''.join(length_buf), 16)\r\n        self.__length = int(length_buf, 16)\r\n\r\n        fmt = '4c'\r\n        #self.__type = ''.join(struct.unpack(fmt, ''.join(buf[4:8])))\r\n        self.__type = buf[4:8].decode()\r\n\r\n        end_data = 8+self.__length\r\n        self.__data = buf[8:end_data]\r\n        \r\n        buf = buf[end_data:]\r\n        crc_bytes = binascii.hexlify(buf[:4])\r\n        #self.__crc = int(''.join(crc_bytes), 16)\r\n        self.__crc = int(crc_bytes, 16)\r\n\r\n        self.__size = 8 + self.__length + 4;\r\n\r\n    def totalSize(self):\r\n        '''TODO: Returns the total size of the chunk in bytes.\r\n        @return: TODO\r\n\r\n        '''\r\n        return self.__size\r\n\r\n    def type(self):\r\n        '''TODO: Docstring for type.\r\n        @return: TODO\r\n\r\n        '''\r\n        return self.__type\r\n\r\n    def data(self):\r\n        '''TODO: Docstring for data.\r\n        @return: TODO\r\n\r\n        '''\r\n        return self.__data\r\n\r\n    def length(self):\r\n        '''TODO: Docstring for length.\r\n        @return: TODO\r\n\r\n        '''\r\n        return self.__length<\/pre>\n<p>&nbsp;<\/p>\n<p>To decode a PNG file, firstly open the file, read the content into a buffer, then decode the header and chunks:<\/p>\n<p>&nbsp;<\/p>\n<pre title=\"A class to parse a PNG file\" class=\"lang:python decode:true\">class PNG(object):\r\n\r\n    '''class for a PNG file. '''\r\n\r\n    def __init__(self, file_path):\r\n        '''TODO: to be defined1. '''\r\n        self.__fileName = file_path\r\n        self.__file = None\r\n        self.__fobj = None\r\n        self.size = [0, 0]\r\n        self.__chunks = []  # List of chunks\r\n        self.__width = 0\r\n        self.__height = 0\r\n        self.__bitDepth = 0\r\n        self.__colorType = 0\r\n        self.__cmpMtd = 0\r\n        self.__fltMtd = 0\r\n        self.__itlMtd = 0\r\n        self.__totalIDAT = 0\r\n\r\n        if file_path:\r\n            self.readFile(file_path)\r\n            self.__file = file_path\r\n    \r\n    def loadHeader(self, buf):\r\n        '''TODO: Docstring for loadHeader.\r\n\r\n        @param buf Byte buffer read from the import file\r\n        @return: TODO\r\n\r\n        '''\r\n        pass\r\n\r\n    def readFile(self, file_path):\r\n        '''TODO: Docstring for readFile.\r\n\r\n        @param file_path Full path to the png file\r\n        @return: True if successful, False otherwise\r\n\r\n        '''\r\n        \r\n        if file_path is None and self.__file is None:\r\n          logger.info(\"File name is empty. Nothing to load!\")\r\n          return\r\n          \r\n        if file_path is not None:\r\n          self.__file = file_path\r\n        \r\n        # Open the file for reading\r\n        self.__fobj = open( self.__file, 'rb')\r\n\r\n        fsize = os.path.getsize( file_path )\r\n        # map the file into memory\r\n        fno = self.__fobj.fileno()\r\n        data = mmap.mmap( fno, fsize, access=mmap.ACCESS_READ )\r\n\r\n        fmt = '8c'\r\n        header = struct.unpack( fmt, data[:8] )\r\n\r\n        # Get the header information\r\n        #self.loadHeader() \r\n        #logger.debug(\"Header: %s\" %  header )\r\n        \r\n        #working buffer   \r\n        buf = data[8:]\r\n        ihdr = Chunk(buf)\r\n        self.parseIHDR(ihdr.data() )\r\n\r\n        chunk_size = ihdr.totalSize()\r\n        self.__chunks = [] \r\n        self.__chunks.append(ihdr)\r\n        while len(buf) &gt; chunk_size:\r\n            buf = buf[chunk_size:]\r\n            ck = Chunk(buf)\r\n            chunk_size = ck.totalSize()\r\n            self.__chunks.append(ck)\r\n       \r\n        self.parseIDAT()\r\n\r\n\r\n        ### close the file\r\n        data.close()\r\n        self.__fobj.close() \r\n...\r\n<\/pre>\n<p>A valid PNG file contains at least one IDAT chunk. IDAT chunks contain compressed image data, which is a rectangular pixel array. Each pixel consists of color information. There are mainly three types of pixels in PNG files:<\/p>\n<ol>\n<li>Grayscale pixel. Minimum pixel size: 1 bit<\/li>\n<li>Color-indexed pixel. Minimum pixel size: 1 bit<\/li>\n<li>Truecolor pixel: Minimum pixel size: 24-bit<\/li>\n<\/ol>\n<p>Optionally, each pixel can have transparence information which is 8-bit. Therefore, a truecolor pixel with transparence consists of 4 bytes.<\/p>\n<p>Image data is organized from the top to bottom. Each row of the image data is packed from the left to the right to form a scanline. Each scanline always starts with a single byte indicating the filter type followed by the packed pixel array of the image. All scanlines are then compressed by using DEFLATE algorithm which is the same as in zlib. We can use zlib module in Python to decompress data in IDAT chunk as shown below:<\/p>\n<pre title=\"Decompress IDAT chunks of a PNG file in Python\" class=\"lang:python decode:true \">    def testCompress(self):\r\n        idat_data = b''\r\n        self.__totalIDAT = 0\r\n        for i in range(1, len(self.__chunks)):\r\n            if self.__chunks[i].type() == 'IDAT':\r\n                idat_data += self.__chunks[i].data() \r\n       img_data = zlib.decompress( idat_data ) \r\n       ...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Please refer to <a href=\"http:\/\/tools.ietf.org\/html\/rfc1950\">zlib RFC page<\/a> for more details of the ZLIB compress data format specification. Basically zlib compressed data always has two bytes in the beginning to indicate compression information. For example, the first two bytes of zlib compressed data would appear to be &#8220;78 da&#8221; in hexadecimal. From these two bytes, we can guess some parameters used in DEFLATE algorithm. But can only get possible values for some parameters like compression level, because different compression level may result in the same header values in the compressed data. In order to figure out the actual compression parameters, we can use a try and error method to test the combination of parameters with commonly used values in Python.<\/p>\n<p>There is already a Python module to parse PNG file. But because I want to test different data compression parameters, I wrote a Python script for the purpose. The complete Python script file can be downloaded from <a href=\"https:\/\/shajisoft.com\/download\/sspng.py\">here<\/a>. The downloaded Python script, sspng.py, works with Python 2.7 and 3.4. It accepts one argument as the path to a png file, dumps the image mata information, and tries to figure out the compression parameters used to create the PNG file. If failed, it prints the actual IDAT sizes if using the compression parameters used in the test.<\/p>\n<h2>Exampels<\/h2>\n<p>Let&#8217;s take a screenshot of TotalCommander on Windows 10 x64 as an example, which is shown below.<\/p>\n<figure id=\"attachment_138\" aria-describedby=\"caption-attachment-138\" style=\"width: 1010px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/totalcmd-en-paint.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-138\" src=\"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/totalcmd-en-paint.png\" alt=\"Screenshot of TotalCommander 8.52a on Windows 10\" width=\"1010\" height=\"793\" \/><\/a><figcaption id=\"caption-attachment-138\" class=\"wp-caption-text\">Screenshot of TotalCommander 8.52a on Windows 10<\/figcaption><\/figure>\n<p>To take the screenshot, bring TotalCommander to the front on the desktop, press Alt-PrtScrn. It will copy the screenshot of TotalCommander to the clipboard. Then paste the image in applications which we want to use to edit and save the screenshot. Here, I am going to use Gimp v2.9 development version and the default Windows Paint. When saving the screenshot as a PNG in these two applications, there is no option to select in Paint regarding PNG file, whereas there are options including the compression level in Gimp to select. Take the default options in Gimp which means to use the highest compression level 9. The generated file sizes are shown below:<\/p>\n<ul>\n<li>Paint: 125,149 bytes<\/li>\n<li>Gimp: 162,688 bytes<\/li>\n<\/ul>\n<p>Assume the PNG file of the above screenshot created by Gimp is saved as c:\\users\\wdong\\Pictures\\totalcmd-en-gimp.png, we can run sspng.py on it as shown below:<\/p>\n<p>&nbsp;<\/p>\n<pre title=\"Running sspng.py on a PNG file\" class=\"lang:batch highlight:0 decode:true \">C:\\Users\\dongw\\Pictures&gt;c:\\Python27\\python.exe sspng.py totalcmd-en-gimp.png\r\n\r\n\r\nInformation about totalcmd-en-gimp.png\r\nIHDR information:\r\n        Width: 1010\r\n        Height: 793\r\n        Bit depth: 8\r\n        Color type: 2\r\n        Compression method: 0\r\n        Filter method: 0\r\n        Interlace method: 0\r\n\r\n Chunk pHYs: Data length: 9, total size: 21 bytes\r\n\r\n Chunk tIME: Data length: 7, total size: 19 bytes\r\n\r\n Chunk tEXt: Data length: 25, total size: 37 bytes\r\n\r\n Chunk IDAT: IDAT chunk size: 8192 bytes, total IDAT size: 162326 bytes\r\n\r\n Chunk IEND: Data length: 0, total size: 12 bytes\r\nsize of img_data = 2403583\r\nzlib header in the PNG file = 78, da\r\nWith compression level 9, mem_level 8, strategy 1, zlib.compress gives 162326 bytes<\/pre>\n<p>&nbsp;<\/p>\n<p>From the above information, we know that the image height is 793 pixels. This means that there are 793 scanlines in IDAT chunk. The color type is 2 so there are 3 bytes (24 bits) per pixel. The first byte of each scanline contains filtering information. The uncompressed image data has (1+1010*3)*793=2403583 bytes. The compressed data is split into multiple IDAT chunks in the file. Each IDAT chunk contains 8192 bytes. The total compressed image data has 162326 bytes. It seems that Gimp uses the standard DEFLATE algorithm to compress the image data when creating PNG file, for we can get the same sized data by compressing the same image data using zlib module of Python.<\/p>\n<p>Running the script on the screenshot created by Windows Paint shows the following information:<\/p>\n<pre title=\"Running sspng.py on a PNG file created by Paint on Windows 10\" class=\"lang:batch highlight:0 decode:true \">C:\\Users\\dongw\\Pictures&gt;c:\\Python27\\python.exe sspng.py totalcmd-cn-paint.png\r\n\r\n\r\nInformation about totalcmd-cn-paint.png\r\nIHDR information:\r\n        Width: 1010\r\n        Height: 793\r\n        Bit depth: 8\r\n        Color type: 2\r\n        Compression method: 0\r\n        Filter method: 0\r\n        Interlace method: 0\r\n\r\n Chunk sRGB: Data length: 1, total size: 13 bytes\r\n\r\n Chunk gAMA: Data length: 4, total size: 16 bytes\r\n\r\n Chunk pHYs: Data length: 9, total size: 21 bytes\r\n\r\n Chunk IDAT: IDAT chunk size: 65445 bytes, total IDAT size: 124688 bytes\r\n\r\n Chunk IEND: Data length: 0, total size: 12 bytes\r\nsize of img_data = 2403583\r\nzlib header in the PNG file = 78, 5e\r\nWith compression level 0, mem_level 1, strategy 0, zlib.compress gives 2427294 bytes\r\nWith compression level 1, mem_level 1, strategy 0, zlib.compress gives 176182 bytes\r\nWith compression level 2, mem_level 1, strategy 0, zlib.compress gives 160285 bytes\r\nWith compression level 3, mem_level 1, strategy 0, zlib.compress gives 146284 bytes\r\nWith compression level 4, mem_level 1, strategy 0, zlib.compress gives 134058 bytes\r\nWith compression level 5, mem_level 1, strategy 0, zlib.compress gives 125760 bytes\r\nWith compression level 6, mem_level 1, strategy 0, zlib.compress gives 117158 bytes\r\nWith compression level 7, mem_level 1, strategy 0, zlib.compress gives 116340 bytes\r\nWith compression level 8, mem_level 1, strategy 0, zlib.compress gives 113287 bytes\r\nWith compression level 9, mem_level 1, strategy 0, zlib.compress gives 111966 bytes\r\nWith compression level 0, mem_level 2, strategy 0, zlib.compress gives 2415384 bytes\r\nWith compression level 1, mem_level 2, strategy 0, zlib.compress gives 170222 bytes\r\nWith compression level 2, mem_level 2, strategy 0, zlib.compress gives 155723 bytes\r\nWith compression level 3, mem_level 2, strategy 0, zlib.compress gives 143172 bytes\r\nWith compression level 4, mem_level 2, strategy 0, zlib.compress gives 129169 bytes\r\nWith compression level 5, mem_level 2, strategy 0, zlib.compress gives 122506 bytes\r\nWith compression level 6, mem_level 2, strategy 0, zlib.compress gives 114908 bytes\r\nWith compression level 7, mem_level 2, strategy 0, zlib.compress gives 114331 bytes\r\nWith compression level 8, mem_level 2, strategy 0, zlib.compress gives 111654 bytes\r\nWith compression level 9, mem_level 2, strategy 0, zlib.compress gives 110420 bytes\r\nWith compression level 0, mem_level 3, strategy 0, zlib.compress gives 2409474 bytes\r\nWith compression level 1, mem_level 3, strategy 0, zlib.compress gives 164668 bytes\r\nWith compression level 2, mem_level 3, strategy 0, zlib.compress gives 150928 bytes\r\nWith compression level 3, mem_level 3, strategy 0, zlib.compress gives 139918 bytes\r\nWith compression level 4, mem_level 3, strategy 0, zlib.compress gives 124791 bytes\r\nWith compression level 5, mem_level 3, strategy 0, zlib.compress gives 118426 bytes\r\nWith compression level 6, mem_level 3, strategy 0, zlib.compress gives 112056 bytes\r\nWith compression level 7, mem_level 3, strategy 0, zlib.compress gives 111606 bytes\r\nWith compression level 8, mem_level 3, strategy 0, zlib.compress gives 108879 bytes\r\nWith compression level 9, mem_level 3, strategy 0, zlib.compress gives 107891 bytes\r\nWith compression level 0, mem_level 4, strategy 0, zlib.compress gives 2406529 bytes\r\nWith compression level 1, mem_level 4, strategy 0, zlib.compress gives 161203 bytes\r\nWith compression level 2, mem_level 4, strategy 0, zlib.compress gives 148187 bytes\r\nWith compression level 3, mem_level 4, strategy 0, zlib.compress gives 137649 bytes\r\nWith compression level 4, mem_level 4, strategy 0, zlib.compress gives 121817 bytes\r\nWith compression level 5, mem_level 4, strategy 0, zlib.compress gives 115812 bytes\r\nWith compression level 6, mem_level 4, strategy 0, zlib.compress gives 110109 bytes\r\nWith compression level 7, mem_level 4, strategy 0, zlib.compress gives 109712 bytes\r\nWith compression level 8, mem_level 4, strategy 0, zlib.compress gives 107154 bytes\r\nWith compression level 9, mem_level 4, strategy 0, zlib.compress gives 106122 bytes\r\nWith compression level 0, mem_level 5, strategy 0, zlib.compress gives 2405059 bytes\r\nWith compression level 1, mem_level 5, strategy 0, zlib.compress gives 159511 bytes\r\nWith compression level 2, mem_level 5, strategy 0, zlib.compress gives 146528 bytes\r\nWith compression level 3, mem_level 5, strategy 0, zlib.compress gives 136218 bytes\r\nWith compression level 4, mem_level 5, strategy 0, zlib.compress gives 120177 bytes\r\nWith compression level 5, mem_level 5, strategy 0, zlib.compress gives 114230 bytes\r\nWith compression level 6, mem_level 5, strategy 0, zlib.compress gives 108545 bytes\r\nWith compression level 7, mem_level 5, strategy 0, zlib.compress gives 108230 bytes\r\nWith compression level 8, mem_level 5, strategy 0, zlib.compress gives 105560 bytes\r\nWith compression level 9, mem_level 5, strategy 0, zlib.compress gives 104583 bytes\r\nWith compression level 0, mem_level 6, strategy 0, zlib.compress gives 2404324 bytes\r\nWith compression level 1, mem_level 6, strategy 0, zlib.compress gives 158833 bytes\r\nWith compression level 2, mem_level 6, strategy 0, zlib.compress gives 146029 bytes\r\nWith compression level 3, mem_level 6, strategy 0, zlib.compress gives 135299 bytes\r\nWith compression level 4, mem_level 6, strategy 0, zlib.compress gives 120105 bytes\r\nWith compression level 5, mem_level 6, strategy 0, zlib.compress gives 114075 bytes\r\nWith compression level 6, mem_level 6, strategy 0, zlib.compress gives 108182 bytes\r\nWith compression level 7, mem_level 6, strategy 0, zlib.compress gives 107714 bytes\r\nWith compression level 8, mem_level 6, strategy 0, zlib.compress gives 104922 bytes\r\nWith compression level 9, mem_level 6, strategy 0, zlib.compress gives 103967 bytes\r\nWith compression level 0, mem_level 7, strategy 0, zlib.compress gives 2403959 bytes\r\nWith compression level 1, mem_level 7, strategy 0, zlib.compress gives 157836 bytes\r\nWith compression level 2, mem_level 7, strategy 0, zlib.compress gives 145142 bytes\r\nWith compression level 3, mem_level 7, strategy 0, zlib.compress gives 134822 bytes\r\nWith compression level 4, mem_level 7, strategy 0, zlib.compress gives 119127 bytes\r\nWith compression level 5, mem_level 7, strategy 0, zlib.compress gives 113359 bytes\r\nWith compression level 6, mem_level 7, strategy 0, zlib.compress gives 107632 bytes\r\nWith compression level 7, mem_level 7, strategy 0, zlib.compress gives 107275 bytes\r\nWith compression level 8, mem_level 7, strategy 0, zlib.compress gives 104603 bytes\r\nWith compression level 9, mem_level 7, strategy 0, zlib.compress gives 103742 bytes\r\nWith compression level 0, mem_level 8, strategy 0, zlib.compress gives 2403954 bytes\r\nWith compression level 1, mem_level 8, strategy 0, zlib.compress gives 157680 bytes\r\nWith compression level 2, mem_level 8, strategy 0, zlib.compress gives 145059 bytes\r\nWith compression level 3, mem_level 8, strategy 0, zlib.compress gives 134853 bytes\r\nWith compression level 4, mem_level 8, strategy 0, zlib.compress gives 118942 bytes\r\nWith compression level 5, mem_level 8, strategy 0, zlib.compress gives 113425 bytes\r\nWith compression level 6, mem_level 8, strategy 0, zlib.compress gives 107872 bytes\r\nWith compression level 7, mem_level 8, strategy 0, zlib.compress gives 107516 bytes\r\nWith compression level 8, mem_level 8, strategy 0, zlib.compress gives 104837 bytes\r\nWith compression level 9, mem_level 8, strategy 0, zlib.compress gives 103848 bytes\r\nWith compression level 0, mem_level 9, strategy 0, zlib.compress gives 2403954 bytes\r\nWith compression level 1, mem_level 9, strategy 0, zlib.compress gives 158120 bytes\r\nWith compression level 2, mem_level 9, strategy 0, zlib.compress gives 145273 bytes\r\nWith compression level 3, mem_level 9, strategy 0, zlib.compress gives 134947 bytes\r\nWith compression level 4, mem_level 9, strategy 0, zlib.compress gives 119473 bytes\r\nWith compression level 5, mem_level 9, strategy 0, zlib.compress gives 114064 bytes\r\nWith compression level 6, mem_level 9, strategy 0, zlib.compress gives 108411 bytes\r\nWith compression level 7, mem_level 9, strategy 0, zlib.compress gives 108041 bytes\r\nWith compression level 8, mem_level 9, strategy 0, zlib.compress gives 105321 bytes\r\nWith compression level 9, mem_level 9, strategy 0, zlib.compress gives 104264 bytes\r\nWith compression level 0, mem_level 1, strategy 1, zlib.compress gives 2427294 bytes\r\nWith compression level 1, mem_level 1, strategy 1, zlib.compress gives 176182 bytes\r\nWith compression level 2, mem_level 1, strategy 1, zlib.compress gives 160285 bytes\r\nWith compression level 3, mem_level 1, strategy 1, zlib.compress gives 146284 bytes\r\nWith compression level 4, mem_level 1, strategy 1, zlib.compress gives 138646 bytes\r\nWith compression level 5, mem_level 1, strategy 1, zlib.compress gives 129359 bytes\r\nWith compression level 6, mem_level 1, strategy 1, zlib.compress gives 120436 bytes\r\nWith compression level 7, mem_level 1, strategy 1, zlib.compress gives 119583 bytes\r\nWith compression level 8, mem_level 1, strategy 1, zlib.compress gives 116264 bytes\r\nWith compression level 9, mem_level 1, strategy 1, zlib.compress gives 115021 bytes\r\nWith compression level 0, mem_level 2, strategy 1, zlib.compress gives 2415384 bytes\r\nWith compression level 1, mem_level 2, strategy 1, zlib.compress gives 170222 bytes\r\nWith compression level 2, mem_level 2, strategy 1, zlib.compress gives 155723 bytes\r\nWith compression level 3, mem_level 2, strategy 1, zlib.compress gives 143172 bytes\r\nWith compression level 4, mem_level 2, strategy 1, zlib.compress gives 134176 bytes\r\nWith compression level 5, mem_level 2, strategy 1, zlib.compress gives 126207 bytes\r\nWith compression level 6, mem_level 2, strategy 1, zlib.compress gives 118319 bytes\r\nWith compression level 7, mem_level 2, strategy 1, zlib.compress gives 117738 bytes\r\nWith compression level 8, mem_level 2, strategy 1, zlib.compress gives 114529 bytes\r\nWith compression level 9, mem_level 2, strategy 1, zlib.compress gives 113488 bytes\r\nWith compression level 0, mem_level 3, strategy 1, zlib.compress gives 2409474 bytes\r\nWith compression level 1, mem_level 3, strategy 1, zlib.compress gives 164668 bytes\r\nWith compression level 2, mem_level 3, strategy 1, zlib.compress gives 150928 bytes\r\nWith compression level 3, mem_level 3, strategy 1, zlib.compress gives 139918 bytes\r\nWith compression level 4, mem_level 3, strategy 1, zlib.compress gives 128996 bytes\r\nWith compression level 5, mem_level 3, strategy 1, zlib.compress gives 121984 bytes\r\nWith compression level 6, mem_level 3, strategy 1, zlib.compress gives 115209 bytes\r\nWith compression level 7, mem_level 3, strategy 1, zlib.compress gives 114679 bytes\r\nWith compression level 8, mem_level 3, strategy 1, zlib.compress gives 111747 bytes\r\nWith compression level 9, mem_level 3, strategy 1, zlib.compress gives 110594 bytes\r\nWith compression level 0, mem_level 4, strategy 1, zlib.compress gives 2406529 bytes\r\nWith compression level 1, mem_level 4, strategy 1, zlib.compress gives 161203 bytes\r\nWith compression level 2, mem_level 4, strategy 1, zlib.compress gives 148187 bytes\r\nWith compression level 3, mem_level 4, strategy 1, zlib.compress gives 137649 bytes\r\nWith compression level 4, mem_level 4, strategy 1, zlib.compress gives 125905 bytes\r\nWith compression level 5, mem_level 4, strategy 1, zlib.compress gives 119155 bytes\r\nWith compression level 6, mem_level 4, strategy 1, zlib.compress gives 113051 bytes\r\nWith compression level 7, mem_level 4, strategy 1, zlib.compress gives 112575 bytes\r\nWith compression level 8, mem_level 4, strategy 1, zlib.compress gives 109749 bytes\r\nWith compression level 9, mem_level 4, strategy 1, zlib.compress gives 108727 bytes\r\nWith compression level 0, mem_level 5, strategy 1, zlib.compress gives 2405059 bytes\r\nWith compression level 1, mem_level 5, strategy 1, zlib.compress gives 159511 bytes\r\nWith compression level 2, mem_level 5, strategy 1, zlib.compress gives 146528 bytes\r\nWith compression level 3, mem_level 5, strategy 1, zlib.compress gives 136218 bytes\r\nWith compression level 4, mem_level 5, strategy 1, zlib.compress gives 124186 bytes\r\nWith compression level 5, mem_level 5, strategy 1, zlib.compress gives 117731 bytes\r\nWith compression level 6, mem_level 5, strategy 1, zlib.compress gives 111589 bytes\r\nWith compression level 7, mem_level 5, strategy 1, zlib.compress gives 111112 bytes\r\nWith compression level 8, mem_level 5, strategy 1, zlib.compress gives 108285 bytes\r\nWith compression level 9, mem_level 5, strategy 1, zlib.compress gives 107157 bytes\r\nWith compression level 0, mem_level 6, strategy 1, zlib.compress gives 2404324 bytes\r\nWith compression level 1, mem_level 6, strategy 1, zlib.compress gives 158833 bytes\r\nWith compression level 2, mem_level 6, strategy 1, zlib.compress gives 146029 bytes\r\nWith compression level 3, mem_level 6, strategy 1, zlib.compress gives 135299 bytes\r\nWith compression level 4, mem_level 6, strategy 1, zlib.compress gives 123926 bytes\r\nWith compression level 5, mem_level 6, strategy 1, zlib.compress gives 117330 bytes\r\nWith compression level 6, mem_level 6, strategy 1, zlib.compress gives 111161 bytes\r\nWith compression level 7, mem_level 6, strategy 1, zlib.compress gives 110609 bytes\r\nWith compression level 8, mem_level 6, strategy 1, zlib.compress gives 107642 bytes\r\nWith compression level 9, mem_level 6, strategy 1, zlib.compress gives 106434 bytes\r\nWith compression level 0, mem_level 7, strategy 1, zlib.compress gives 2403959 bytes\r\nWith compression level 1, mem_level 7, strategy 1, zlib.compress gives 157836 bytes\r\nWith compression level 2, mem_level 7, strategy 1, zlib.compress gives 145142 bytes\r\nWith compression level 3, mem_level 7, strategy 1, zlib.compress gives 134822 bytes\r\nWith compression level 4, mem_level 7, strategy 1, zlib.compress gives 122917 bytes\r\nWith compression level 5, mem_level 7, strategy 1, zlib.compress gives 116738 bytes\r\nWith compression level 6, mem_level 7, strategy 1, zlib.compress gives 110681 bytes\r\nWith compression level 7, mem_level 7, strategy 1, zlib.compress gives 110313 bytes\r\nWith compression level 8, mem_level 7, strategy 1, zlib.compress gives 107484 bytes\r\nWith compression level 9, mem_level 7, strategy 1, zlib.compress gives 106377 bytes\r\nWith compression level 0, mem_level 8, strategy 1, zlib.compress gives 2403954 bytes\r\nWith compression level 1, mem_level 8, strategy 1, zlib.compress gives 157680 bytes\r\nWith compression level 2, mem_level 8, strategy 1, zlib.compress gives 145059 bytes\r\nWith compression level 3, mem_level 8, strategy 1, zlib.compress gives 134853 bytes\r\nWith compression level 4, mem_level 8, strategy 1, zlib.compress gives 123086 bytes\r\nWith compression level 5, mem_level 8, strategy 1, zlib.compress gives 116643 bytes\r\nWith compression level 6, mem_level 8, strategy 1, zlib.compress gives 110820 bytes\r\nWith compression level 7, mem_level 8, strategy 1, zlib.compress gives 110508 bytes\r\nWith compression level 8, mem_level 8, strategy 1, zlib.compress gives 107777 bytes\r\nWith compression level 9, mem_level 8, strategy 1, zlib.compress gives 106770 bytes\r\nWith compression level 0, mem_level 9, strategy 1, zlib.compress gives 2403954 bytes\r\nWith compression level 1, mem_level 9, strategy 1, zlib.compress gives 158120 bytes\r\nWith compression level 2, mem_level 9, strategy 1, zlib.compress gives 145273 bytes\r\nWith compression level 3, mem_level 9, strategy 1, zlib.compress gives 134947 bytes\r\nWith compression level 4, mem_level 9, strategy 1, zlib.compress gives 123774 bytes\r\nWith compression level 5, mem_level 9, strategy 1, zlib.compress gives 117299 bytes\r\nWith compression level 6, mem_level 9, strategy 1, zlib.compress gives 111406 bytes\r\nWith compression level 7, mem_level 9, strategy 1, zlib.compress gives 111126 bytes\r\nWith compression level 8, mem_level 9, strategy 1, zlib.compress gives 108399 bytes\r\nWith compression level 9, mem_level 9, strategy 1, zlib.compress gives 107291 bytes<\/pre>\n<p>&nbsp;<\/p>\n<p>This means that we can&#8217;t reproduce the same compressed data by using the standard implementation of DEFLATE algorithm using the zlib module in Python. Compare the above test results, we can see the following differences between PNG files created by Gimp and Windows Paint on Windows 10:<\/p>\n<ul>\n<li>IDAT chunks are in 8192-byte blocks in Gimp and 65445-byte blocks in Paint<\/li>\n<li>Windows Paint on Windows 10 must have applied a kind of pre-compression filtering to optimize the PNG file.<\/li>\n<li>Windows Paint on Windows 10 doesn&#8217;t use the optimal compression parameters.<\/li>\n<\/ul>\n<p>Further experiments with Gimp 2.8 and Windows Paint on Windows 7 have shown that those applications use the standard DEFLATE algorithm to compress data in PNG files.<\/p>\n<h2>Optimize PNG files<\/h2>\n<p>Basically, there are three ways to optimize PNG files, namely,<\/p>\n<ol>\n<li>Use indexed colors instead of truecolors<\/li>\n<li>Filter image data before compression<\/li>\n<li>Use different implementations of DEFLATE algorithm which give better compression ratios, ie, 7-zip DEFLATE and Zopfli released by Google<\/li>\n<\/ol>\n<p>Please refer to the following pages for more information about how to optimize PNG files:<\/p>\n<ol>\n<li><a href=\"https:\/\/zoompf.com\/blog\/2010\/01\/top-png-optimizers-dont-use-zlib\">https:\/\/zoompf.com\/blog\/2010\/01\/top-png-optimizers-dont-use-zlib<\/a>\n<\/li>\n<li><a href=\"http:\/\/www.smashingmagazine.com\/2009\/07\/clever-png-optimization-techniques\/\">http:\/\/www.smashingmagazine.com\/2009\/07\/clever-png-optimization-techniques\/<\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. I am going to show how to parse PNG files by using Python and try to figure out the reason for the difference.<\/p>\n","protected":false},"author":1,"featured_media":145,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":{"0":"post-135","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-uncategorized","8":"czr-hentry"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Why the Same Screenshot is Saved as Different Sized PNGs<\/title>\n<meta name=\"description\" content=\"Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. Use Python to figure out why\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why the Same Screenshot is Saved as Different Sized PNGs\" \/>\n<meta property=\"og:description\" content=\"Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. Use Python to figure out why\" \/>\n<meta property=\"og:url\" content=\"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/\" \/>\n<meta property=\"og:site_name\" content=\"Shajisoft\" \/>\n<meta property=\"article:published_time\" content=\"2015-10-11T22:06:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2016-01-07T19:49:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png_post_en_feature.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1170\" \/>\n\t<meta property=\"og:image:height\" content=\"500\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"taohe\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"taohe\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/\"},\"author\":{\"name\":\"taohe\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/#\\\/schema\\\/person\\\/076c9b498ded94485f1258125cf44852\"},\"headline\":\"Why the Same Screenshot is Saved as PNG of Different Sizes by Different Tools\",\"datePublished\":\"2015-10-11T22:06:07+00:00\",\"dateModified\":\"2016-01-07T19:49:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/\"},\"wordCount\":1417,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/#\\\/schema\\\/person\\\/076c9b498ded94485f1258125cf44852\"},\"image\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/png_post_en_feature.png\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/\",\"url\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/\",\"name\":\"Why the Same Screenshot is Saved as Different Sized PNGs\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/png_post_en_feature.png\",\"datePublished\":\"2015-10-11T22:06:07+00:00\",\"dateModified\":\"2016-01-07T19:49:15+00:00\",\"description\":\"Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. Use Python to figure out why\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#primaryimage\",\"url\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/png_post_en_feature.png\",\"contentUrl\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/10\\\/png_post_en_feature.png\",\"width\":1170,\"height\":500,\"caption\":\"PNG file shown in Hex\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/why-the-same-screenshot-is-saved-as-different-sized-pngs\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Why the Same Screenshot is Saved as PNG of Different Sizes by Different Tools\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/#website\",\"url\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/\",\"name\":\"Shajisoft\",\"description\":\"Home of simple tools for simple tasks and weblogs\",\"publisher\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/#\\\/schema\\\/person\\\/076c9b498ded94485f1258125cf44852\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/#\\\/schema\\\/person\\\/076c9b498ded94485f1258125cf44852\",\"name\":\"taohe\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/05\\\/shajisoft_logo.png\",\"url\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/05\\\/shajisoft_logo.png\",\"contentUrl\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/05\\\/shajisoft_logo.png\",\"width\":250,\"height\":64,\"caption\":\"taohe\"},\"logo\":{\"@id\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/wp-content\\\/uploads\\\/2015\\\/05\\\/shajisoft_logo.png\"},\"url\":\"https:\\\/\\\/shajisoft.com\\\/shajisoft_wp\\\/author\\\/taohe\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Why the Same Screenshot is Saved as Different Sized PNGs","description":"Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. Use Python to figure out why","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/","og_locale":"en_US","og_type":"article","og_title":"Why the Same Screenshot is Saved as Different Sized PNGs","og_description":"Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. Use Python to figure out why","og_url":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/","og_site_name":"Shajisoft","article_published_time":"2015-10-11T22:06:07+00:00","article_modified_time":"2016-01-07T19:49:15+00:00","og_image":[{"width":1170,"height":500,"url":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png_post_en_feature.png","type":"image\/png"}],"author":"taohe","twitter_card":"summary_large_image","twitter_misc":{"Written by":"taohe","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#article","isPartOf":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/"},"author":{"name":"taohe","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/#\/schema\/person\/076c9b498ded94485f1258125cf44852"},"headline":"Why the Same Screenshot is Saved as PNG of Different Sizes by Different Tools","datePublished":"2015-10-11T22:06:07+00:00","dateModified":"2016-01-07T19:49:15+00:00","mainEntityOfPage":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/"},"wordCount":1417,"commentCount":0,"publisher":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/#\/schema\/person\/076c9b498ded94485f1258125cf44852"},"image":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#primaryimage"},"thumbnailUrl":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png_post_en_feature.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/","url":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/","name":"Why the Same Screenshot is Saved as Different Sized PNGs","isPartOf":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/#website"},"primaryImageOfPage":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#primaryimage"},"image":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#primaryimage"},"thumbnailUrl":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png_post_en_feature.png","datePublished":"2015-10-11T22:06:07+00:00","dateModified":"2016-01-07T19:49:15+00:00","description":"Different applications like Gimp and Windows Paint create PNG files of different sizes for the same screenshot. Use Python to figure out why","breadcrumb":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#primaryimage","url":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png_post_en_feature.png","contentUrl":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/10\/png_post_en_feature.png","width":1170,"height":500,"caption":"PNG file shown in Hex"},{"@type":"BreadcrumbList","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/why-the-same-screenshot-is-saved-as-different-sized-pngs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/shajisoft.com\/shajisoft_wp\/"},{"@type":"ListItem","position":2,"name":"Why the Same Screenshot is Saved as PNG of Different Sizes by Different Tools"}]},{"@type":"WebSite","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/#website","url":"https:\/\/shajisoft.com\/shajisoft_wp\/","name":"Shajisoft","description":"Home of simple tools for simple tasks and weblogs","publisher":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/#\/schema\/person\/076c9b498ded94485f1258125cf44852"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/shajisoft.com\/shajisoft_wp\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/#\/schema\/person\/076c9b498ded94485f1258125cf44852","name":"taohe","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/05\/shajisoft_logo.png","url":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/05\/shajisoft_logo.png","contentUrl":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/05\/shajisoft_logo.png","width":250,"height":64,"caption":"taohe"},"logo":{"@id":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-content\/uploads\/2015\/05\/shajisoft_logo.png"},"url":"https:\/\/shajisoft.com\/shajisoft_wp\/author\/taohe\/"}]}},"_links":{"self":[{"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/posts\/135","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/comments?post=135"}],"version-history":[{"count":3,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/posts\/135\/revisions"}],"predecessor-version":[{"id":173,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/posts\/135\/revisions\/173"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/media\/145"}],"wp:attachment":[{"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/media?parent=135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/categories?post=135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shajisoft.com\/shajisoft_wp\/wp-json\/wp\/v2\/tags?post=135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}