png_conform 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +143 -12
- data/Gemfile +1 -1
- data/benchmarks/lib/benchmark_runner.rb +1 -1
- data/benchmarks/lib/metrics_collector.rb +3 -3
- data/benchmarks/lib/report_generator.rb +8 -9
- data/config/validation_profiles.yml +105 -0
- data/lib/png_conform/analyzers/comparison_analyzer.rb +46 -12
- data/lib/png_conform/analyzers/metrics_analyzer.rb +6 -9
- data/lib/png_conform/analyzers/optimization_analyzer.rb +33 -27
- data/lib/png_conform/analyzers/resolution_analyzer.rb +31 -32
- data/lib/png_conform/bindata/chunk_structure.rb +1 -1
- data/lib/png_conform/cli.rb +12 -7
- data/lib/png_conform/commands/check_command.rb +121 -55
- data/lib/png_conform/configuration.rb +147 -0
- data/lib/png_conform/container.rb +113 -0
- data/lib/png_conform/models/chunk_info.rb +1 -1
- data/lib/png_conform/models/validation_result.rb +30 -4
- data/lib/png_conform/pipelines/pipeline_result.rb +39 -0
- data/lib/png_conform/pipelines/stages/analysis_stage.rb +35 -0
- data/lib/png_conform/pipelines/stages/base_stage.rb +23 -0
- data/lib/png_conform/pipelines/stages/chunk_validation_stage.rb +74 -0
- data/lib/png_conform/pipelines/stages/sequence_validation_stage.rb +77 -0
- data/lib/png_conform/pipelines/stages/signature_validation_stage.rb +41 -0
- data/lib/png_conform/pipelines/validation_pipeline.rb +90 -0
- data/lib/png_conform/readers/full_load_reader.rb +13 -4
- data/lib/png_conform/readers/streaming_reader.rb +27 -2
- data/lib/png_conform/reporters/color_reporter.rb +17 -14
- data/lib/png_conform/reporters/visual_elements.rb +22 -16
- data/lib/png_conform/services/analysis_manager.rb +120 -0
- data/lib/png_conform/services/chunk_processor.rb +195 -0
- data/lib/png_conform/services/file_signature.rb +226 -0
- data/lib/png_conform/services/file_strategy.rb +78 -0
- data/lib/png_conform/services/lru_cache.rb +170 -0
- data/lib/png_conform/services/parallel_validator.rb +118 -0
- data/lib/png_conform/services/profile_manager.rb +41 -12
- data/lib/png_conform/services/result_builder.rb +299 -0
- data/lib/png_conform/services/validation_cache.rb +210 -0
- data/lib/png_conform/services/validation_orchestrator.rb +188 -0
- data/lib/png_conform/services/validation_service.rb +53 -337
- data/lib/png_conform/services/validator_pool.rb +142 -0
- data/lib/png_conform/services/zlib_validator.rb +2 -2
- data/lib/png_conform/utils/colorizer.rb +149 -0
- data/lib/png_conform/validators/ancillary/trns_validator.rb +1 -1
- data/lib/png_conform/validators/base_validator.rb +1 -1
- data/lib/png_conform/validators/chunk_registry.rb +12 -0
- data/lib/png_conform/validators/critical/ihdr_validator.rb +2 -2
- data/lib/png_conform/validators/streaming_idat_validator.rb +123 -0
- data/lib/png_conform/version.rb +1 -1
- data/lib/png_conform.rb +38 -0
- data/png_conform.gemspec +2 -0
- metadata +39 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f40907ca0fa307f62da38b9fecdd97fa05e6f9953315d3bc197a6c1385c1c490
|
|
4
|
+
data.tar.gz: 27891ced82861b1ff72ac09ef12fcc6801c1f28b46cb849e1a4d6100a6ad9f6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f58ca78ca13ca9934b677118c06cd67d362b96af38863b943dc0f60b757d0685435c450261ee1107d4eebbc5aa95e494c877cf6f55faccccb0dc89fdb0dd9bfc
|
|
7
|
+
data.tar.gz: 4479d1b4a79ee5d97fc49c297297f11818443e1f7c29e612131520d7037293951488a8fc8ec6af8772d7b49f833d45973ee21817e4bcaa34f98a4f88117818ff
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,18 +1,64 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on
|
|
3
|
+
# on 2026-04-04 06:26:35 UTC using RuboCop version 1.86.0.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
-
# Offense count:
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
+
Gemspec/RequireMFA:
|
|
12
|
+
Exclude:
|
|
13
|
+
- 'png_conform.gemspec'
|
|
14
|
+
|
|
15
|
+
# Offense count: 1
|
|
16
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
17
|
+
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
|
|
18
|
+
Layout/ExtraSpacing:
|
|
19
|
+
Exclude:
|
|
20
|
+
- 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
|
|
21
|
+
|
|
22
|
+
# Offense count: 1
|
|
23
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
24
|
+
# Configuration parameters: EnforcedStyle.
|
|
25
|
+
# SupportedStyles: normal, indented_internal_methods
|
|
26
|
+
Layout/IndentationConsistency:
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'png_conform.gemspec'
|
|
29
|
+
|
|
30
|
+
# Offense count: 6
|
|
10
31
|
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
-
# Configuration parameters:
|
|
32
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
33
|
+
# SupportedStyles: aligned, indented
|
|
34
|
+
Layout/LineEndStringConcatenationIndentation:
|
|
35
|
+
Exclude:
|
|
36
|
+
- 'lib/png_conform/analyzers/optimization_analyzer.rb'
|
|
37
|
+
|
|
38
|
+
# Offense count: 263
|
|
39
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
40
|
+
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
12
41
|
# URISchemes: http, https
|
|
13
42
|
Layout/LineLength:
|
|
14
43
|
Enabled: false
|
|
15
44
|
|
|
45
|
+
# Offense count: 1
|
|
46
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
47
|
+
# Configuration parameters: AllowInHeredoc.
|
|
48
|
+
Layout/TrailingWhitespace:
|
|
49
|
+
Exclude:
|
|
50
|
+
- 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
|
|
51
|
+
|
|
52
|
+
# Offense count: 14
|
|
53
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
54
|
+
Lint/AmbiguousOperatorPrecedence:
|
|
55
|
+
Exclude:
|
|
56
|
+
- 'benchmarks/lib/benchmark_runner.rb'
|
|
57
|
+
- 'benchmarks/lib/report_generator.rb'
|
|
58
|
+
- 'lib/png_conform/services/result_builder.rb'
|
|
59
|
+
- 'lib/png_conform/services/zlib_validator.rb'
|
|
60
|
+
- 'lib/png_conform/validators/critical/ihdr_validator.rb'
|
|
61
|
+
|
|
16
62
|
# Offense count: 1
|
|
17
63
|
Lint/BinaryOperatorWithIdenticalOperands:
|
|
18
64
|
Exclude:
|
|
@@ -27,7 +73,22 @@ Lint/DuplicateBranch:
|
|
|
27
73
|
- 'lib/png_conform/validators/ancillary/sbit_validator.rb'
|
|
28
74
|
- 'spec/pngsuite/helpers/semantic_validator.rb'
|
|
29
75
|
|
|
30
|
-
# Offense count:
|
|
76
|
+
# Offense count: 1
|
|
77
|
+
# Configuration parameters: AllowComments, AllowEmptyLambdas.
|
|
78
|
+
Lint/EmptyBlock:
|
|
79
|
+
Exclude:
|
|
80
|
+
- 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
|
|
81
|
+
|
|
82
|
+
# Offense count: 4
|
|
83
|
+
# Configuration parameters: AllowedParentClasses.
|
|
84
|
+
Lint/MissingSuper:
|
|
85
|
+
Exclude:
|
|
86
|
+
- 'lib/png_conform/pipelines/stages/analysis_stage.rb'
|
|
87
|
+
- 'lib/png_conform/pipelines/stages/chunk_validation_stage.rb'
|
|
88
|
+
- 'lib/png_conform/pipelines/stages/sequence_validation_stage.rb'
|
|
89
|
+
- 'lib/png_conform/pipelines/stages/signature_validation_stage.rb'
|
|
90
|
+
|
|
91
|
+
# Offense count: 124
|
|
31
92
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
32
93
|
Metrics/AbcSize:
|
|
33
94
|
Enabled: false
|
|
@@ -36,14 +97,14 @@ Metrics/AbcSize:
|
|
|
36
97
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
37
98
|
# AllowedMethods: refine
|
|
38
99
|
Metrics/BlockLength:
|
|
39
|
-
Max:
|
|
100
|
+
Max: 52
|
|
40
101
|
|
|
41
|
-
# Offense count:
|
|
102
|
+
# Offense count: 62
|
|
42
103
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
43
104
|
Metrics/CyclomaticComplexity:
|
|
44
105
|
Enabled: false
|
|
45
106
|
|
|
46
|
-
# Offense count:
|
|
107
|
+
# Offense count: 193
|
|
47
108
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
48
109
|
Metrics/MethodLength:
|
|
49
110
|
Max: 66
|
|
@@ -58,6 +119,13 @@ Metrics/ParameterLists:
|
|
|
58
119
|
Metrics/PerceivedComplexity:
|
|
59
120
|
Enabled: false
|
|
60
121
|
|
|
122
|
+
# Offense count: 132
|
|
123
|
+
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
|
124
|
+
# AllowedMethods: call
|
|
125
|
+
# WaywardPredicates: infinite?, nonzero?
|
|
126
|
+
Naming/PredicateMethod:
|
|
127
|
+
Enabled: false
|
|
128
|
+
|
|
61
129
|
# Offense count: 1
|
|
62
130
|
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
63
131
|
# SupportedStyles: snake_case, normalcase, non_integer
|
|
@@ -72,6 +140,13 @@ Performance/CollectionLiteralInLoop:
|
|
|
72
140
|
Exclude:
|
|
73
141
|
- 'examples/advanced_usage.rb'
|
|
74
142
|
|
|
143
|
+
# Offense count: 4
|
|
144
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
145
|
+
Performance/MapCompact:
|
|
146
|
+
Exclude:
|
|
147
|
+
- 'benchmarks/lib/metrics_collector.rb'
|
|
148
|
+
- 'lib/png_conform/services/file_signature.rb'
|
|
149
|
+
|
|
75
150
|
# Offense count: 70
|
|
76
151
|
# Configuration parameters: Prefixes, AllowedPatterns.
|
|
77
152
|
# Prefixes: when, with, without
|
|
@@ -103,25 +178,81 @@ RSpec/MultipleMemoizedHelpers:
|
|
|
103
178
|
Max: 6
|
|
104
179
|
|
|
105
180
|
# Offense count: 2
|
|
106
|
-
#
|
|
181
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
182
|
+
RSpec/Output:
|
|
183
|
+
Exclude:
|
|
184
|
+
- 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
|
|
185
|
+
|
|
186
|
+
# Offense count: 2
|
|
187
|
+
# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
|
|
188
|
+
# SupportedInflectors: default, active_support
|
|
107
189
|
RSpec/SpecFilePathFormat:
|
|
108
190
|
Exclude:
|
|
109
191
|
- 'spec/png_conform/bindata/chunk_structure_spec.rb'
|
|
110
192
|
- 'spec/png_conform/bindata/png_file_spec.rb'
|
|
111
193
|
|
|
112
|
-
# Offense count:
|
|
194
|
+
# Offense count: 44
|
|
113
195
|
# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
|
|
114
196
|
RSpec/VerifiedDoubles:
|
|
115
197
|
Enabled: false
|
|
116
198
|
|
|
117
|
-
# Offense count:
|
|
199
|
+
# Offense count: 2
|
|
200
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
201
|
+
Style/BitwisePredicate:
|
|
202
|
+
Exclude:
|
|
203
|
+
- 'lib/png_conform/bindata/chunk_structure.rb'
|
|
204
|
+
- 'lib/png_conform/services/chunk_processor.rb'
|
|
205
|
+
|
|
206
|
+
# Offense count: 2
|
|
207
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
208
|
+
Style/ComparableBetween:
|
|
209
|
+
Exclude:
|
|
210
|
+
- 'lib/png_conform/validators/ancillary/trns_validator.rb'
|
|
211
|
+
- 'lib/png_conform/validators/base_validator.rb'
|
|
212
|
+
|
|
213
|
+
# Offense count: 1
|
|
214
|
+
Style/FileOpen:
|
|
215
|
+
Exclude:
|
|
216
|
+
- 'lib/png_conform/container.rb'
|
|
217
|
+
|
|
218
|
+
# Offense count: 36
|
|
118
219
|
# This cop supports safe autocorrection (--autocorrect).
|
|
119
220
|
# Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
|
|
120
221
|
# SupportedStyles: annotated, template, unannotated
|
|
121
222
|
Style/FormatStringToken:
|
|
122
223
|
EnforcedStyle: unannotated
|
|
123
224
|
|
|
225
|
+
# Offense count: 4
|
|
226
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
227
|
+
Style/MapToSet:
|
|
228
|
+
Exclude:
|
|
229
|
+
- 'lib/png_conform/analyzers/comparison_analyzer.rb'
|
|
230
|
+
|
|
124
231
|
# Offense count: 1
|
|
125
|
-
|
|
232
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
233
|
+
Style/RedundantFormat:
|
|
234
|
+
Exclude:
|
|
235
|
+
- 'benchmarks/lib/report_generator.rb'
|
|
236
|
+
|
|
237
|
+
# Offense count: 2
|
|
238
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
239
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
240
|
+
Style/ReturnNilInPredicateMethodDefinition:
|
|
241
|
+
Exclude:
|
|
242
|
+
- 'lib/png_conform/analyzers/comparison_analyzer.rb'
|
|
243
|
+
- 'spec/pngsuite/helpers/pngcheck_parser.rb'
|
|
244
|
+
|
|
245
|
+
# Offense count: 2
|
|
246
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
247
|
+
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
|
|
248
|
+
# SupportedStyles: single_quotes, double_quotes
|
|
249
|
+
Style/StringLiterals:
|
|
250
|
+
Exclude:
|
|
251
|
+
- 'png_conform.gemspec'
|
|
252
|
+
|
|
253
|
+
# Offense count: 2
|
|
254
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
255
|
+
Style/SuperArguments:
|
|
126
256
|
Exclude:
|
|
127
|
-
- 'lib/png_conform/
|
|
257
|
+
- 'lib/png_conform/models/chunk_info.rb'
|
|
258
|
+
- 'lib/png_conform/models/validation_result.rb'
|
data/Gemfile
CHANGED
|
@@ -165,7 +165,7 @@ class BenchmarkRunner
|
|
|
165
165
|
pct = (current.to_f / total * 100).round(1)
|
|
166
166
|
bar_width = 40
|
|
167
167
|
filled = (bar_width * current / total).to_i
|
|
168
|
-
bar = "=" * filled + " " * (bar_width - filled)
|
|
168
|
+
bar = ("=" * filled) + (" " * (bar_width - filled))
|
|
169
169
|
|
|
170
170
|
print "\r [#{bar}] #{pct}% (#{current}/#{total}) #{label} "
|
|
171
171
|
$stdout.flush
|
|
@@ -46,8 +46,8 @@ class MetricsCollector
|
|
|
46
46
|
tool_runs = runs_for_tool(tool)
|
|
47
47
|
return nil if tool_runs.empty?
|
|
48
48
|
|
|
49
|
-
execution_times = tool_runs.
|
|
50
|
-
memory_values = tool_runs.
|
|
49
|
+
execution_times = tool_runs.filter_map { |r| r[:execution_time] }
|
|
50
|
+
memory_values = tool_runs.filter_map { |r| r[:peak_memory] }
|
|
51
51
|
|
|
52
52
|
{
|
|
53
53
|
tool: tool,
|
|
@@ -118,7 +118,7 @@ class MetricsCollector
|
|
|
118
118
|
total_runs: @runs.size,
|
|
119
119
|
tools: tools,
|
|
120
120
|
files_tested: @runs.map { |r| r[:file] }.uniq.size,
|
|
121
|
-
tool_statistics: tools.
|
|
121
|
+
tool_statistics: tools.filter_map { |tool| calculate_statistics(tool) },
|
|
122
122
|
}
|
|
123
123
|
end
|
|
124
124
|
|
|
@@ -42,9 +42,9 @@ class ReportGenerator
|
|
|
42
42
|
return "No benchmark data available.\n" if tools.empty?
|
|
43
43
|
|
|
44
44
|
output = []
|
|
45
|
-
output << "=" * 80
|
|
45
|
+
output << ("=" * 80)
|
|
46
46
|
output << "PNG Validation Tool Benchmark Comparison"
|
|
47
|
-
output << "=" * 80
|
|
47
|
+
output << ("=" * 80)
|
|
48
48
|
output << ""
|
|
49
49
|
output << "Configuration:"
|
|
50
50
|
output << " Files tested: #{summary[:files_tested]} PNG files"
|
|
@@ -62,9 +62,9 @@ class ReportGenerator
|
|
|
62
62
|
# Performance comparison (if we have 2 tools)
|
|
63
63
|
if tools.size == 2
|
|
64
64
|
comparison = metrics_collector.compare_tools(tools[0], tools[1])
|
|
65
|
-
output << "-" * 80
|
|
65
|
+
output << ("-" * 80)
|
|
66
66
|
output << "PERFORMANCE SUMMARY"
|
|
67
|
-
output << "-" * 80
|
|
67
|
+
output << ("-" * 80)
|
|
68
68
|
output << ""
|
|
69
69
|
output << format_comparison_table(comparison)
|
|
70
70
|
output << ""
|
|
@@ -73,9 +73,9 @@ class ReportGenerator
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
# Detailed statistics per tool
|
|
76
|
-
output << "-" * 80
|
|
76
|
+
output << ("-" * 80)
|
|
77
77
|
output << "DETAILED STATISTICS"
|
|
78
|
-
output << "-" * 80
|
|
78
|
+
output << ("-" * 80)
|
|
79
79
|
output << ""
|
|
80
80
|
|
|
81
81
|
tools.each do |tool|
|
|
@@ -176,9 +176,8 @@ class ReportGenerator
|
|
|
176
176
|
# Format comparison table for text output.
|
|
177
177
|
def format_comparison_table(comparison)
|
|
178
178
|
lines = []
|
|
179
|
-
lines <<
|
|
180
|
-
|
|
181
|
-
lines << "-" * 80
|
|
179
|
+
lines << "Tool Avg Time Files/sec Peak Memory Winner"
|
|
180
|
+
lines << ("-" * 80)
|
|
182
181
|
|
|
183
182
|
[comparison[:tool1], comparison[:tool2]].each do |tool|
|
|
184
183
|
stats = comparison[:stats][tool]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# PNG Conform Validation Profiles
|
|
2
|
+
#
|
|
3
|
+
# This file defines validation profiles for PNG files. Each profile specifies
|
|
4
|
+
# which chunks are required, optional, or prohibited.
|
|
5
|
+
#
|
|
6
|
+
# Profile structure:
|
|
7
|
+
# name: Display name
|
|
8
|
+
# description: Human-readable description
|
|
9
|
+
# required_chunks: List of chunk types that MUST be present
|
|
10
|
+
# optional_chunks: List of chunk types that MAY be present (use "*" for all)
|
|
11
|
+
# prohibited_chunks: List of chunk types that MUST NOT be present
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
minimal:
|
|
15
|
+
name: "Minimal validation"
|
|
16
|
+
description: "Only critical chunks required"
|
|
17
|
+
required_chunks:
|
|
18
|
+
- IHDR
|
|
19
|
+
- IDAT
|
|
20
|
+
- IEND
|
|
21
|
+
optional_chunks: "*"
|
|
22
|
+
prohibited_chunks: []
|
|
23
|
+
|
|
24
|
+
web:
|
|
25
|
+
name: "Web-optimized"
|
|
26
|
+
description: "Recommended for web images"
|
|
27
|
+
required_chunks:
|
|
28
|
+
- IHDR
|
|
29
|
+
- IDAT
|
|
30
|
+
- IEND
|
|
31
|
+
- gAMA
|
|
32
|
+
- sRGB
|
|
33
|
+
optional_chunks:
|
|
34
|
+
- tRNS
|
|
35
|
+
- bKGD
|
|
36
|
+
- tEXt
|
|
37
|
+
- iTXt
|
|
38
|
+
- zTXt
|
|
39
|
+
- pHYs
|
|
40
|
+
prohibited_chunks: []
|
|
41
|
+
|
|
42
|
+
print:
|
|
43
|
+
name: "Print-ready"
|
|
44
|
+
description: "For high-quality print output"
|
|
45
|
+
required_chunks:
|
|
46
|
+
- IHDR
|
|
47
|
+
- IDAT
|
|
48
|
+
- IEND
|
|
49
|
+
- pHYs
|
|
50
|
+
optional_chunks:
|
|
51
|
+
- gAMA
|
|
52
|
+
- cHRM
|
|
53
|
+
- sRGB
|
|
54
|
+
- iCCP
|
|
55
|
+
- tRNS
|
|
56
|
+
- bKGD
|
|
57
|
+
prohibited_chunks: []
|
|
58
|
+
|
|
59
|
+
archive:
|
|
60
|
+
name: "Archive quality"
|
|
61
|
+
description: "For long-term image storage"
|
|
62
|
+
required_chunks:
|
|
63
|
+
- IHDR
|
|
64
|
+
- IDAT
|
|
65
|
+
- IEND
|
|
66
|
+
optional_chunks:
|
|
67
|
+
- gAMA
|
|
68
|
+
- cHRM
|
|
69
|
+
- sRGB
|
|
70
|
+
- iCCP
|
|
71
|
+
- tEXt
|
|
72
|
+
- iTXt
|
|
73
|
+
- zTXt
|
|
74
|
+
- tIME
|
|
75
|
+
prohibited_chunks: []
|
|
76
|
+
|
|
77
|
+
strict:
|
|
78
|
+
name: "Strict PNG specification"
|
|
79
|
+
description: "Full compliance with PNG specification"
|
|
80
|
+
required_chunks:
|
|
81
|
+
- IHDR
|
|
82
|
+
- IDAT
|
|
83
|
+
- IEND
|
|
84
|
+
optional_chunks:
|
|
85
|
+
- PLTE
|
|
86
|
+
- gAMA
|
|
87
|
+
- cHRM
|
|
88
|
+
- sRGB
|
|
89
|
+
- iCCP
|
|
90
|
+
- tRNS
|
|
91
|
+
- bKGD
|
|
92
|
+
- hIST
|
|
93
|
+
- tEXt
|
|
94
|
+
- zTXt
|
|
95
|
+
- iTXt
|
|
96
|
+
- pHYs
|
|
97
|
+
- sPLT
|
|
98
|
+
- sBIT
|
|
99
|
+
- oFFs
|
|
100
|
+
- pCAL
|
|
101
|
+
- sCAL
|
|
102
|
+
- tIME
|
|
103
|
+
- cICP
|
|
104
|
+
- mDCv
|
|
105
|
+
prohibited_chunks: []
|
|
@@ -1,18 +1,51 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../configuration"
|
|
4
|
+
require_relative "../services/file_signature"
|
|
5
|
+
|
|
3
6
|
module PngConform
|
|
4
7
|
module Analyzers
|
|
5
8
|
# Compares two PNG files and reports differences
|
|
6
9
|
class ComparisonAnalyzer
|
|
7
|
-
|
|
8
|
-
METADATA_CHUNKS = %w[tEXt zTXt iTXt tIME].freeze
|
|
9
|
-
|
|
10
|
-
def initialize(result1, result2)
|
|
10
|
+
def initialize(result1, result2, config: Configuration.instance)
|
|
11
11
|
@result1 = result1
|
|
12
12
|
@result2 = result2
|
|
13
|
+
@config = config
|
|
14
|
+
|
|
15
|
+
# Fast path: compute signatures for quick equality check
|
|
16
|
+
@sig1 = Services::FileSignature.from_result(result1).compute_signature
|
|
17
|
+
@sig2 = Services::FileSignature.from_result(result2).compute_signature
|
|
13
18
|
end
|
|
14
19
|
|
|
15
20
|
def analyze
|
|
21
|
+
# Fast return if signatures are identical
|
|
22
|
+
return identical_result if @sig1 == @sig2
|
|
23
|
+
|
|
24
|
+
# Full comparison for different files
|
|
25
|
+
full_comparison
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Return result for identical files
|
|
31
|
+
#
|
|
32
|
+
# @return [Hash] Analysis result for identical files
|
|
33
|
+
def identical_result
|
|
34
|
+
{
|
|
35
|
+
files: {
|
|
36
|
+
file1: @result1.filename,
|
|
37
|
+
file2: @result2.filename,
|
|
38
|
+
identical: true,
|
|
39
|
+
signature: @sig1.short_signature,
|
|
40
|
+
},
|
|
41
|
+
summary: ["Files are binary identical"],
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Full comparison for different files
|
|
46
|
+
#
|
|
47
|
+
# @return [Hash] Complete comparison analysis
|
|
48
|
+
def full_comparison
|
|
16
49
|
{
|
|
17
50
|
files: file_comparison,
|
|
18
51
|
image: image_comparison,
|
|
@@ -23,8 +56,6 @@ module PngConform
|
|
|
23
56
|
}
|
|
24
57
|
end
|
|
25
58
|
|
|
26
|
-
private
|
|
27
|
-
|
|
28
59
|
def file_comparison
|
|
29
60
|
size1 = @result1.file_size
|
|
30
61
|
size2 = @result2.file_size
|
|
@@ -144,19 +175,19 @@ module PngConform
|
|
|
144
175
|
end
|
|
145
176
|
|
|
146
177
|
def new_errors
|
|
147
|
-
errors1 = @result1.errors.
|
|
148
|
-
errors2 = @result2.errors.
|
|
178
|
+
errors1 = @result1.errors.to_set(&:message)
|
|
179
|
+
errors2 = @result2.errors.to_set(&:message)
|
|
149
180
|
(errors2 - errors1).to_a
|
|
150
181
|
end
|
|
151
182
|
|
|
152
183
|
def resolved_errors
|
|
153
|
-
errors1 = @result1.errors.
|
|
154
|
-
errors2 = @result2.errors.
|
|
184
|
+
errors1 = @result1.errors.to_set(&:message)
|
|
185
|
+
errors2 = @result2.errors.to_set(&:message)
|
|
155
186
|
(errors1 - errors2).to_a
|
|
156
187
|
end
|
|
157
188
|
|
|
158
189
|
def compression_improved?
|
|
159
|
-
return
|
|
190
|
+
return false unless @result1.compression_ratio && @result2.compression_ratio
|
|
160
191
|
|
|
161
192
|
@result2.compression_ratio > @result1.compression_ratio
|
|
162
193
|
end
|
|
@@ -166,7 +197,10 @@ module PngConform
|
|
|
166
197
|
end
|
|
167
198
|
|
|
168
199
|
def metadata_count(result)
|
|
169
|
-
|
|
200
|
+
# Use only text and time chunks from metadata (excluding pHYs which is physical)
|
|
201
|
+
result.chunks.count do |c|
|
|
202
|
+
@config.text_chunks.include?(c.type) || c.type == "tIME"
|
|
203
|
+
end
|
|
170
204
|
end
|
|
171
205
|
|
|
172
206
|
def format_size_change(diff, percent)
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../configuration"
|
|
4
|
+
|
|
3
5
|
module PngConform
|
|
4
6
|
module Analyzers
|
|
5
7
|
# Generates comprehensive metrics for CI/CD and automation
|
|
6
8
|
class MetricsAnalyzer
|
|
7
|
-
|
|
8
|
-
TEXT_CHUNKS = %w[tEXt zTXt iTXt].freeze
|
|
9
|
-
|
|
10
|
-
# Metadata chunk types including time
|
|
11
|
-
METADATA_CHUNKS = %w[tEXt zTXt iTXt tIME].freeze
|
|
12
|
-
|
|
13
|
-
def initialize(result)
|
|
9
|
+
def initialize(result, config: Configuration.instance)
|
|
14
10
|
@result = result
|
|
11
|
+
@config = config
|
|
15
12
|
ihdr = result.ihdr_chunk
|
|
16
13
|
@width = ihdr ? get_width(ihdr) : 0
|
|
17
14
|
@height = ihdr ? get_height(ihdr) : 0
|
|
@@ -149,10 +146,10 @@ module PngConform
|
|
|
149
146
|
has_iccp: @result.has_chunk?("iCCP"),
|
|
150
147
|
has_transparency: @result.has_chunk?("tRNS"),
|
|
151
148
|
has_metadata: @result.chunks.any? do |c|
|
|
152
|
-
|
|
149
|
+
@config.text_chunks.include?(c.type)
|
|
153
150
|
end,
|
|
154
151
|
metadata_chunks_count: @result.chunks.count do |c|
|
|
155
|
-
|
|
152
|
+
@config.metadata_chunks.include?(c.type)
|
|
156
153
|
end,
|
|
157
154
|
bytes_per_pixel: calculate_bytes_per_pixel,
|
|
158
155
|
}
|