├── 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 |
--------------------------------------------------------------------------------