├── vc14 ├── .gitignore ├── pngcmp.vcxproj.filters ├── pngcmp.sln └── pngcmp.vcxproj ├── README.org ├── LICENSE.txt └── main.cpp /vc14/.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Release 3 | .vs 4 | *.VC.db 5 | *.VC.VC.opendb 6 | *.vcxproj.user 7 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * pngcmp 2 | 3 | Pngcmp compares two .png files and outputs the number of matching pixels and total number of pixels. 4 | 5 | #+BEGIN_SRC sh 6 | pngcmp a.png b.png 7 | # => 303916 307200 8 | #+END_SRC 9 | -------------------------------------------------------------------------------- /vc14/pngcmp.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | ソース ファイル 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 AKIYAMA Kouhei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vc14/pngcmp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngcmp", "pngcmp.vcxproj", "{377ECAED-6A48-4FF8-B39B-772B33EE7C82}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Debug|x64.ActiveCfg = Debug|x64 17 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Debug|x64.Build.0 = Debug|x64 18 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Debug|x86.ActiveCfg = Debug|Win32 19 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Debug|x86.Build.0 = Debug|Win32 20 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Release|x64.ActiveCfg = Release|x64 21 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Release|x64.Build.0 = Release|x64 22 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Release|x86.ActiveCfg = Release|Win32 23 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * pngcmp main 3 | * 4 | * @author AKIYAMA Kouhei 5 | * @since 2017-02-02 6 | */ 7 | 8 | #ifndef PNGCMP_LINK_STATIC_LIBRARY 9 | # define PNGCMP_LINK_STATIC_LIBRARY 1 10 | #endif 11 | #if PNGCMP_LINK_STATIC_LIBRARY 12 | # ifdef _DEBUG 13 | # pragma comment(lib, "Debug Library/libpng16.lib") 14 | # pragma comment(lib, "ZlibStatDebug/zlibstat.lib") 15 | # else 16 | # pragma comment(lib, "Release Library/libpng16.lib") 17 | # pragma comment(lib, "ZlibStatRelease/zlibstat.lib") 18 | # endif 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | struct PngStruct 28 | { 29 | png_structp png_ptr; 30 | png_infop info_ptr; 31 | png_infop end_info; 32 | PngStruct() 33 | : png_ptr(png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr)) 34 | , info_ptr(png_ptr ? png_create_info_struct(png_ptr) : nullptr) 35 | , end_info(png_ptr ? png_create_info_struct(png_ptr) : nullptr) 36 | { 37 | } 38 | ~PngStruct() 39 | { 40 | if(png_ptr){ 41 | png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); 42 | } 43 | } 44 | bool hasError() const 45 | { 46 | return !png_ptr || !info_ptr || !end_info; 47 | } 48 | }; 49 | 50 | struct File 51 | { 52 | FILE *fp; 53 | File(const char *filename) : fp(std::fopen(filename, "rb")){} 54 | ~File(){if(fp){std::fclose(fp);}} 55 | operator FILE *() const {return fp;} 56 | }; 57 | 58 | class PngFile 59 | { 60 | std::string filename; 61 | File fp; 62 | PngStruct png; 63 | public: 64 | PngFile(const char * const filename) 65 | : filename(filename) 66 | , fp(filename) 67 | , png() 68 | { 69 | } 70 | void error(const std::string &msg) 71 | { 72 | std::cerr << filename << ":: " << msg << std::endl; 73 | } 74 | bool read() 75 | { 76 | if(!fp){ 77 | error("File cannot open."); 78 | return false; 79 | } 80 | if(png.hasError()){ 81 | error("Failed to initialize libpng."); 82 | return false; 83 | } 84 | 85 | png_init_io(png.png_ptr, fp); 86 | 87 | // read image. 88 | int transform 89 | = PNG_TRANSFORM_STRIP_16 90 | | PNG_TRANSFORM_EXPAND 91 | | PNG_TRANSFORM_BGR; 92 | 93 | png_read_png(png.png_ptr, png.info_ptr, transform, NULL); 94 | 95 | const int color_type = png_get_color_type(png.png_ptr, png.info_ptr); 96 | const int bit_depth = png_get_bit_depth(png.png_ptr, png.info_ptr); 97 | 98 | const std::size_t pixelBytes = 99 | color_type == PNG_COLOR_TYPE_RGB ? 3 : 100 | color_type == PNG_COLOR_TYPE_RGB_ALPHA ? 4 : 101 | 0; 102 | if (pixelBytes == 0){ 103 | error("unsupported color type found."); 104 | return false; 105 | } 106 | ///@todo 16bit-depth 107 | ///@todo PNG_COLOR_TYPE_PALETTE 108 | return true; 109 | } 110 | const png_bytep *rows(){return png_get_rows(png.png_ptr, png.info_ptr);} 111 | png_uint_32 width(){return png_get_image_width(png.png_ptr, png.info_ptr);} 112 | png_uint_32 height(){return png_get_image_height(png.png_ptr, png.info_ptr);} 113 | int color_type(){return png_get_color_type(png.png_ptr, png.info_ptr);} 114 | }; 115 | 116 | 117 | 118 | int main(int argc, char *argv[]) 119 | { 120 | if(argc < 3){ 121 | std::cout << "usage: " << argv[0] << " " << std::endl; 122 | return -1; 123 | } 124 | 125 | // read png 126 | PngFile img1(argv[1]); 127 | if(!img1.read()){return -1;} 128 | PngFile img2(argv[2]); 129 | if(!img2.read()){return -1;} 130 | 131 | // compare width, height, color_type 132 | if(img1.width() != img2.width() || img1.height() != img2.height()){ 133 | std::cerr << "Image size mismatch." << std::endl; 134 | return -1; 135 | } 136 | if(img1.color_type() != img2.color_type()){ 137 | std::cerr << "Image color type mismatch." << std::endl; 138 | return -1; 139 | } 140 | 141 | // compare pixels 142 | const unsigned int width = img1.width(); 143 | const unsigned int height = img1.height(); 144 | const int color_type = img1.color_type(); 145 | const png_bytep * const rows1 = img1.rows(); 146 | const png_bytep * const rows2 = img2.rows(); 147 | 148 | int error_count = 0; 149 | for(unsigned int y = 0; y < height; ++y){ 150 | png_bytep p1 = rows1[y]; 151 | png_bytep p2 = rows2[y]; 152 | 153 | if(color_type == PNG_COLOR_TYPE_RGB){ 154 | for(unsigned int x = 0; x < width; ++x){ 155 | if(p1[0] != p2[0] || 156 | p1[1] != p2[1] || 157 | p1[2] != p2[2]){ 158 | ++error_count; 159 | } 160 | p1 += 3; 161 | p2 += 3; 162 | } 163 | } 164 | else if(color_type == PNG_COLOR_TYPE_RGB_ALPHA){ 165 | for(unsigned int x = 0; x < width; ++x){ 166 | if(p1[0] != p2[0] || 167 | p1[1] != p2[1] || 168 | p1[2] != p2[2] || 169 | p1[3] != p2[3]){ 170 | ++error_count; 171 | } 172 | p1 += 4; 173 | p2 += 4; 174 | } 175 | } 176 | else{ 177 | return -1; 178 | } 179 | } 180 | 181 | // output result 182 | const unsigned int total = width * height; 183 | const unsigned int matched = total - error_count; 184 | std::cout << matched << "\t" << total << std::endl; 185 | //std::cout << (100 * matched / total) << std::endl; 186 | 187 | return 0; 188 | } 189 | -------------------------------------------------------------------------------- /vc14/pngcmp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {377ECAED-6A48-4FF8-B39B-772B33EE7C82} 23 | Win32Proj 24 | pngcmp 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | true 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | false 87 | 88 | 89 | 90 | 91 | 92 | Level3 93 | Disabled 94 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 95 | MultiThreadedDebug 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | 105 | 106 | Level3 107 | Disabled 108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | 110 | 111 | Console 112 | true 113 | 114 | 115 | 116 | 117 | Level3 118 | 119 | 120 | MaxSpeed 121 | true 122 | true 123 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | MultiThreaded 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | Level3 136 | 137 | 138 | MaxSpeed 139 | true 140 | true 141 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | 143 | 144 | Console 145 | true 146 | true 147 | true 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | --------------------------------------------------------------------------------