origami-docspring 2.2.0 → 2.3.0
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/CHANGELOG.md +18 -0
- data/examples/attachments/attachment.rb +7 -8
- data/examples/attachments/nested_document.rb +6 -5
- data/examples/encryption/encryption.rb +5 -4
- data/examples/events/events.rb +7 -6
- data/examples/flash/flash.rb +10 -9
- data/examples/forms/javascript.rb +14 -13
- data/examples/forms/xfa.rb +67 -66
- data/examples/javascript/hello_world.rb +6 -5
- data/examples/javascript/js_emulation.rb +26 -26
- data/examples/loop/goto.rb +12 -11
- data/examples/loop/named.rb +17 -16
- data/examples/signature/signature.rb +11 -11
- data/examples/uri/javascript.rb +25 -24
- data/examples/uri/open-uri.rb +5 -4
- data/examples/uri/submitform.rb +11 -10
- data/lib/origami/3d.rb +330 -334
- data/lib/origami/acroform.rb +267 -268
- data/lib/origami/actions.rb +266 -278
- data/lib/origami/annotations.rb +659 -670
- data/lib/origami/array.rb +192 -196
- data/lib/origami/boolean.rb +66 -70
- data/lib/origami/catalog.rb +360 -363
- data/lib/origami/collections.rb +132 -133
- data/lib/origami/compound.rb +125 -129
- data/lib/origami/destinations.rb +226 -237
- data/lib/origami/dictionary.rb +155 -154
- data/lib/origami/encryption.rb +967 -923
- data/lib/origami/extensions/fdf.rb +270 -275
- data/lib/origami/extensions/ppklite.rb +323 -328
- data/lib/origami/filespec.rb +170 -173
- data/lib/origami/filters/ascii.rb +162 -167
- data/lib/origami/filters/ccitt/tables.rb +248 -252
- data/lib/origami/filters/ccitt.rb +309 -312
- data/lib/origami/filters/crypt.rb +31 -34
- data/lib/origami/filters/dct.rb +47 -50
- data/lib/origami/filters/flate.rb +57 -60
- data/lib/origami/filters/jbig2.rb +50 -53
- data/lib/origami/filters/jpx.rb +40 -43
- data/lib/origami/filters/lzw.rb +151 -155
- data/lib/origami/filters/predictors.rb +250 -255
- data/lib/origami/filters/runlength.rb +111 -115
- data/lib/origami/filters.rb +319 -325
- data/lib/origami/font.rb +173 -177
- data/lib/origami/functions.rb +62 -66
- data/lib/origami/graphics/colors.rb +203 -208
- data/lib/origami/graphics/instruction.rb +79 -81
- data/lib/origami/graphics/path.rb +141 -144
- data/lib/origami/graphics/patterns.rb +156 -160
- data/lib/origami/graphics/render.rb +51 -47
- data/lib/origami/graphics/state.rb +144 -142
- data/lib/origami/graphics/text.rb +185 -188
- data/lib/origami/graphics/xobject.rb +818 -804
- data/lib/origami/graphics.rb +25 -26
- data/lib/origami/header.rb +63 -65
- data/lib/origami/javascript.rb +718 -651
- data/lib/origami/linearization.rb +284 -285
- data/lib/origami/metadata.rb +156 -135
- data/lib/origami/name.rb +98 -100
- data/lib/origami/null.rb +49 -51
- data/lib/origami/numeric.rb +133 -135
- data/lib/origami/obfuscation.rb +180 -182
- data/lib/origami/object.rb +634 -631
- data/lib/origami/optionalcontent.rb +147 -149
- data/lib/origami/outline.rb +46 -48
- data/lib/origami/outputintents.rb +76 -77
- data/lib/origami/page.rb +637 -596
- data/lib/origami/parser.rb +214 -221
- data/lib/origami/parsers/fdf.rb +44 -45
- data/lib/origami/parsers/pdf/lazy.rb +147 -154
- data/lib/origami/parsers/pdf/linear.rb +104 -109
- data/lib/origami/parsers/pdf.rb +109 -107
- data/lib/origami/parsers/ppklite.rb +44 -46
- data/lib/origami/pdf.rb +886 -896
- data/lib/origami/reference.rb +116 -120
- data/lib/origami/signature.rb +617 -625
- data/lib/origami/stream.rb +560 -558
- data/lib/origami/string.rb +366 -368
- data/lib/origami/template/patterns.rb +50 -52
- data/lib/origami/template/widgets.rb +111 -114
- data/lib/origami/trailer.rb +153 -157
- data/lib/origami/tree.rb +55 -57
- data/lib/origami/version.rb +19 -19
- data/lib/origami/webcapture.rb +87 -90
- data/lib/origami/xfa/config.rb +409 -414
- data/lib/origami/xfa/connectionset.rb +113 -117
- data/lib/origami/xfa/datasets.rb +38 -42
- data/lib/origami/xfa/localeset.rb +33 -37
- data/lib/origami/xfa/package.rb +49 -52
- data/lib/origami/xfa/pdf.rb +54 -59
- data/lib/origami/xfa/signature.rb +33 -37
- data/lib/origami/xfa/sourceset.rb +34 -38
- data/lib/origami/xfa/stylesheet.rb +35 -39
- data/lib/origami/xfa/template.rb +1630 -1634
- data/lib/origami/xfa/xdc.rb +33 -37
- data/lib/origami/xfa/xfa.rb +132 -123
- data/lib/origami/xfa/xfdf.rb +34 -38
- data/lib/origami/xfa/xmpmeta.rb +34 -38
- data/lib/origami/xfa.rb +50 -53
- data/lib/origami/xreftable.rb +462 -462
- data/lib/origami.rb +37 -38
- data/test/test_actions.rb +22 -20
- data/test/test_annotations.rb +54 -52
- data/test/test_forms.rb +23 -21
- data/test/test_native_types.rb +82 -78
- data/test/test_object_tree.rb +25 -24
- data/test/test_pages.rb +43 -41
- data/test/test_pdf.rb +2 -0
- data/test/test_pdf_attachment.rb +23 -21
- data/test/test_pdf_create.rb +16 -15
- data/test/test_pdf_encrypt.rb +69 -66
- data/test/test_pdf_parse.rb +131 -129
- data/test/test_pdf_parse_lazy.rb +53 -53
- data/test/test_pdf_sign.rb +67 -67
- data/test/test_streams.rb +145 -143
- data/test/test_xrefs.rb +46 -45
- metadata +64 -8
@@ -1,292 +1,287 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This file is part of Origami, PDF manipulation framework for Ruby
|
5
|
+
# Copyright (C) 2016 Guillaume Delugré.
|
6
|
+
#
|
7
|
+
# Origami is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Origami is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
20
|
|
21
21
|
module Origami
|
22
|
+
module Filter
|
23
|
+
class PredictorError < Error # :nodoc:
|
24
|
+
end
|
22
25
|
|
23
|
-
module
|
24
|
-
|
25
|
-
|
26
|
+
module Predictor
|
27
|
+
NONE = 1
|
28
|
+
TIFF = 2
|
29
|
+
PNG_NONE = 10
|
30
|
+
PNG_SUB = 11
|
31
|
+
PNG_UP = 12
|
32
|
+
PNG_AVERAGE = 13
|
33
|
+
PNG_PAETH = 14
|
34
|
+
PNG_OPTIMUM = 15
|
35
|
+
|
36
|
+
class DecodeParms < Dictionary
|
37
|
+
include StandardObject
|
38
|
+
|
39
|
+
field :Predictor, Type: Integer, Default: 1
|
40
|
+
field :Colors, Type: Integer, Default: 1
|
41
|
+
field :BitsPerComponent, Type: Integer, Default: 8
|
42
|
+
field :Columns, Type: Integer, Default: 1
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.included(receiver)
|
46
|
+
raise TypeError, "Predictors only applies to Filters" unless receiver.include?(Filter)
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Create a new predictive Filter.
|
51
|
+
# _parameters_:: A hash of filter options.
|
52
|
+
#
|
53
|
+
def initialize(parameters = {})
|
54
|
+
super(DecodeParms.new(parameters))
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def pre_prediction(data)
|
60
|
+
return data unless @params.Predictor.is_a?(Integer)
|
61
|
+
|
62
|
+
apply_pre_prediction(data, **prediction_parameters)
|
63
|
+
end
|
64
|
+
|
65
|
+
def post_prediction(data)
|
66
|
+
return data unless @params.Predictor.is_a?(Integer)
|
67
|
+
|
68
|
+
apply_post_prediction(data, **prediction_parameters)
|
69
|
+
end
|
70
|
+
|
71
|
+
def prediction_parameters
|
72
|
+
{
|
73
|
+
predictor: @params.Predictor.to_i,
|
74
|
+
colors: @params.Colors.is_a?(Integer) ? @params.Colors.to_i : 1,
|
75
|
+
bpc: @params.BitsPerComponent.is_a?(Integer) ? @params.BitsPerComponent.to_i : 8,
|
76
|
+
columns: @params.Columns.is_a?(Integer) ? @params.Columns.to_i : 1,
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def apply_pre_prediction(data, predictor: NONE, colors: 1, bpc: 8, columns: 1)
|
81
|
+
return data if data.empty? || (predictor == NONE)
|
82
|
+
|
83
|
+
bpp, bpr = compute_bpp_bpr(data, columns, colors, bpc)
|
84
|
+
|
85
|
+
unless data.size % bpr == 0
|
86
|
+
raise PredictorError.new("Invalid data size #{data.size}, should be multiple of bpr=#{bpr}",
|
87
|
+
input_data: data)
|
26
88
|
end
|
27
89
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
PNG_PAETH = 14
|
37
|
-
PNG_OPTIMUM = 15
|
38
|
-
|
39
|
-
class DecodeParms < Dictionary
|
40
|
-
include StandardObject
|
41
|
-
|
42
|
-
field :Predictor, :Type => Integer, :Default => 1
|
43
|
-
field :Colors, :Type => Integer, :Default => 1
|
44
|
-
field :BitsPerComponent, :Type => Integer, :Default => 8
|
45
|
-
field :Columns, :Type => Integer, :Default => 1
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.included(receiver)
|
49
|
-
raise TypeError, "Predictors only applies to Filters" unless receiver.include?(Filter)
|
50
|
-
end
|
51
|
-
|
52
|
-
#
|
53
|
-
# Create a new predictive Filter.
|
54
|
-
# _parameters_:: A hash of filter options.
|
55
|
-
#
|
56
|
-
def initialize(parameters = {})
|
57
|
-
super(DecodeParms.new(parameters))
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
def pre_prediction(data)
|
63
|
-
return data unless @params.Predictor.is_a?(Integer)
|
64
|
-
|
65
|
-
apply_pre_prediction(data, **prediction_parameters)
|
66
|
-
end
|
90
|
+
if predictor == TIFF
|
91
|
+
tiff_pre_prediction(data, colors, bpc, columns)
|
92
|
+
elsif predictor >= 10 # PNG
|
93
|
+
png_pre_prediction(data, predictor, bpp, bpr)
|
94
|
+
else
|
95
|
+
raise PredictorError.new("Unknown predictor : #{predictor}", input_data: data)
|
96
|
+
end
|
97
|
+
end
|
67
98
|
|
68
|
-
|
69
|
-
|
99
|
+
def apply_post_prediction(data, predictor: NONE, colors: 1, bpc: 8, columns: 1)
|
100
|
+
return data if data.empty? || (predictor == NONE)
|
70
101
|
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
def prediction_parameters
|
75
|
-
{
|
76
|
-
predictor: @params.Predictor.to_i,
|
77
|
-
colors: @params.Colors.is_a?(Integer) ? @params.Colors.to_i : 1,
|
78
|
-
bpc: @params.BitsPerComponent.is_a?(Integer) ? @params.BitsPerComponent.to_i : 8,
|
79
|
-
columns: @params.Columns.is_a?(Integer) ? @params.Columns.to_i : 1,
|
80
|
-
}
|
81
|
-
end
|
102
|
+
bpp, bpr = compute_bpp_bpr(data, columns, colors, bpc)
|
82
103
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
104
|
+
if predictor == TIFF
|
105
|
+
tiff_post_prediction(data, colors, bpc, columns)
|
106
|
+
elsif predictor >= 10 # PNG
|
107
|
+
# Each line has an extra predictor byte.
|
108
|
+
png_post_prediction(data, bpp, bpr + 1)
|
109
|
+
else
|
110
|
+
raise PredictorError.new("Unknown predictor : #{predictor}", input_data: data)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Computes the number of bytes per pixel and number of bytes per row.
|
116
|
+
#
|
117
|
+
def compute_bpp_bpr(data, columns, colors, bpc)
|
118
|
+
unless colors.between?(1, 4)
|
119
|
+
raise PredictorError.new("Colors must be between 1 and 4", input_data: data)
|
120
|
+
end
|
87
121
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
122
|
+
unless [1, 2, 4, 8, 16].include?(bpc)
|
123
|
+
raise PredictorError.new("BitsPerComponent must be in 1, 2, 4, 8 or 16", input_data: data)
|
124
|
+
end
|
92
125
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
126
|
+
# components per line
|
127
|
+
nvals = columns * colors
|
128
|
+
|
129
|
+
# bytes per pixel
|
130
|
+
bpp = (colors * bpc + 7) >> 3
|
131
|
+
|
132
|
+
# bytes per row
|
133
|
+
bpr = (nvals * bpc + 7) >> 3
|
134
|
+
|
135
|
+
[bpp, bpr]
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Decodes the PNG input data.
|
140
|
+
# Each line should be prepended by a byte identifying a PNG predictor.
|
141
|
+
#
|
142
|
+
def png_post_prediction(data, bpp, bpr)
|
143
|
+
result = +""
|
144
|
+
uprow = +"\0" * bpr
|
145
|
+
thisrow = +"\0" * bpr
|
146
|
+
nrows = (data.size + bpr - 1) / bpr
|
147
|
+
|
148
|
+
nrows.times do |irow|
|
149
|
+
line = data[irow * bpr, bpr]
|
150
|
+
predictor = 10 + line[0].ord
|
151
|
+
line[0] = "\0"
|
152
|
+
|
153
|
+
(1..line.size - 1).each do |i|
|
154
|
+
up = uprow[i].ord
|
155
|
+
|
156
|
+
if bpp > i
|
157
|
+
left = upleft = 0
|
158
|
+
else
|
159
|
+
left = line[i - bpp].ord
|
160
|
+
upleft = uprow[i - bpp].ord
|
100
161
|
end
|
101
162
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
163
|
+
begin
|
164
|
+
thisrow[i] = png_apply_prediction(predictor, line[i].ord, up, left, upleft, &:+)
|
165
|
+
rescue PredictorError => error
|
166
|
+
thisrow[i] = line[i] if Origami::OPTIONS[:ignore_png_errors]
|
106
167
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# Each line has an extra predictor byte.
|
111
|
-
png_post_prediction(data, bpp, bpr + 1)
|
112
|
-
else
|
113
|
-
raise PredictorError.new("Unknown predictor : #{predictor}", input_data: data)
|
114
|
-
end
|
168
|
+
error.input_data = data
|
169
|
+
error.decoded_data = result
|
170
|
+
raise(error)
|
115
171
|
end
|
172
|
+
end
|
116
173
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
def compute_bpp_bpr(data, columns, colors, bpc)
|
121
|
-
unless colors.between?(1, 4)
|
122
|
-
raise PredictorError.new("Colors must be between 1 and 4", input_data: data)
|
123
|
-
end
|
124
|
-
|
125
|
-
unless [1,2,4,8,16].include?(bpc)
|
126
|
-
raise PredictorError.new("BitsPerComponent must be in 1, 2, 4, 8 or 16", input_data: data)
|
127
|
-
end
|
128
|
-
|
129
|
-
# components per line
|
130
|
-
nvals = columns * colors
|
174
|
+
result << thisrow[1..]
|
175
|
+
uprow = thisrow
|
176
|
+
end
|
131
177
|
|
132
|
-
|
133
|
-
|
178
|
+
result
|
179
|
+
end
|
134
180
|
|
135
|
-
|
136
|
-
|
181
|
+
#
|
182
|
+
# Encodes the input data given a PNG predictor.
|
183
|
+
#
|
184
|
+
def png_pre_prediction(data, predictor, bpp, bpr)
|
185
|
+
result = ""
|
186
|
+
nrows = data.size / bpr
|
137
187
|
|
138
|
-
|
139
|
-
end
|
188
|
+
line = "\0" + data[-bpr, bpr]
|
140
189
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
uprow = "\0" * bpr
|
148
|
-
thisrow = "\0" * bpr
|
149
|
-
nrows = (data.size + bpr - 1) / bpr
|
150
|
-
|
151
|
-
nrows.times do |irow|
|
152
|
-
line = data[irow * bpr, bpr]
|
153
|
-
predictor = 10 + line[0].ord
|
154
|
-
line[0] = "\0"
|
155
|
-
|
156
|
-
for i in (1..line.size-1)
|
157
|
-
up = uprow[i].ord
|
158
|
-
|
159
|
-
if bpp > i
|
160
|
-
left = upleft = 0
|
161
|
-
else
|
162
|
-
left = line[i - bpp].ord
|
163
|
-
upleft = uprow[i - bpp].ord
|
164
|
-
end
|
165
|
-
|
166
|
-
begin
|
167
|
-
thisrow[i] = png_apply_prediction(predictor, line[i].ord, up, left, upleft, &:+)
|
168
|
-
rescue PredictorError => error
|
169
|
-
thisrow[i] = line[i] if Origami::OPTIONS[:ignore_png_errors]
|
170
|
-
|
171
|
-
error.input_data = data
|
172
|
-
error.decoded_data = result
|
173
|
-
raise(error)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
result << thisrow[1..-1]
|
178
|
-
uprow = thisrow
|
179
|
-
end
|
180
|
-
|
181
|
-
result
|
190
|
+
(nrows - 1).downto(0) do |irow|
|
191
|
+
uprow =
|
192
|
+
if irow == 0
|
193
|
+
"\0" * (bpr + 1)
|
194
|
+
else
|
195
|
+
"\0" + data[(irow - 1) * bpr, bpr]
|
182
196
|
end
|
183
197
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
result = ""
|
189
|
-
nrows = data.size / bpr
|
198
|
+
bpr.downto(1) do |i|
|
199
|
+
up = uprow[i].ord
|
200
|
+
left = line[i - bpp].ord
|
201
|
+
upleft = uprow[i - bpp].ord
|
190
202
|
|
191
|
-
|
203
|
+
line[i] = png_apply_prediction(predictor, line[i].ord, up, left, upleft, &:-)
|
204
|
+
end
|
192
205
|
|
193
|
-
|
194
|
-
|
195
|
-
if irow == 0
|
196
|
-
"\0" * (bpr + 1)
|
197
|
-
else
|
198
|
-
"\0" + data[(irow - 1) * bpr, bpr]
|
199
|
-
end
|
206
|
+
line[0] = (predictor - 10).chr
|
207
|
+
result = line + result
|
200
208
|
|
201
|
-
|
202
|
-
|
203
|
-
left = line[i - bpp].ord
|
204
|
-
upleft = uprow[i - bpp].ord
|
205
|
-
|
206
|
-
line[i] = png_apply_prediction(predictor, line[i].ord, up, left, upleft, &:-)
|
207
|
-
end
|
209
|
+
line = uprow
|
210
|
+
end
|
208
211
|
|
209
|
-
|
210
|
-
|
212
|
+
result
|
213
|
+
end
|
214
|
+
|
215
|
+
#
|
216
|
+
# Computes the next component value given a predictor and adjacent components.
|
217
|
+
# A block must be passed to apply the operation.
|
218
|
+
#
|
219
|
+
def png_apply_prediction(predictor, value, up, left, upleft)
|
220
|
+
result =
|
221
|
+
case predictor
|
222
|
+
when PNG_NONE
|
223
|
+
value
|
224
|
+
when PNG_SUB
|
225
|
+
yield(value, left)
|
226
|
+
when PNG_UP
|
227
|
+
yield(value, up)
|
228
|
+
when PNG_AVERAGE
|
229
|
+
yield(value, (left + up) / 2)
|
230
|
+
when PNG_PAETH
|
231
|
+
yield(value, png_paeth_choose(up, left, upleft))
|
232
|
+
else
|
233
|
+
raise PredictorError, "Unsupported PNG predictor : #{predictor}"
|
234
|
+
end
|
235
|
+
|
236
|
+
(result & 0xFF).chr
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Choose the preferred value in a PNG paeth predictor given the left, up and up left samples.
|
241
|
+
#
|
242
|
+
def png_paeth_choose(left, up, upleft)
|
243
|
+
p = left + up - upleft
|
244
|
+
pa, pb, pc = (p - left).abs, (p - up).abs, (p - upleft).abs
|
245
|
+
|
246
|
+
case [pa, pb, pc].min
|
247
|
+
when pa then left
|
248
|
+
when pb then up
|
249
|
+
when pc then upleft
|
250
|
+
end
|
251
|
+
end
|
211
252
|
|
212
|
-
|
213
|
-
|
253
|
+
def tiff_post_prediction(data, colors, bpc, columns) # :nodoc:
|
254
|
+
tiff_apply_prediction(data, colors, bpc, columns, &:+)
|
255
|
+
end
|
214
256
|
|
215
|
-
|
216
|
-
|
257
|
+
def tiff_pre_prediction(data, colors, bpc, columns) # :nodoc:
|
258
|
+
tiff_apply_prediction(data, colors, bpc, columns, &:-)
|
259
|
+
end
|
217
260
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
result =
|
225
|
-
case predictor
|
226
|
-
when PNG_NONE
|
227
|
-
value
|
228
|
-
when PNG_SUB
|
229
|
-
yield(value, left)
|
230
|
-
when PNG_UP
|
231
|
-
yield(value, up)
|
232
|
-
when PNG_AVERAGE
|
233
|
-
yield(value, (left + up) / 2)
|
234
|
-
when PNG_PAETH
|
235
|
-
yield(value, png_paeth_choose(up, left, upleft))
|
236
|
-
else
|
237
|
-
raise PredictorError, "Unsupported PNG predictor : #{predictor}"
|
238
|
-
end
|
239
|
-
|
240
|
-
(result & 0xFF).chr
|
241
|
-
end
|
261
|
+
def tiff_apply_prediction(data, colors, bpc, columns) # :nodoc:
|
262
|
+
bpr = (colors * bpc * columns + 7) >> 3
|
263
|
+
nrows = data.size / bpr
|
264
|
+
bitmask = (1 << bpc) - 1
|
265
|
+
result = Utils::BitWriter.new
|
242
266
|
|
243
|
-
|
244
|
-
|
245
|
-
#
|
246
|
-
def png_paeth_choose(left, up, upleft)
|
247
|
-
p = left + up - upleft
|
248
|
-
pa, pb, pc = (p - left).abs, (p - up).abs, (p - upleft).abs
|
249
|
-
|
250
|
-
case [pa, pb, pc].min
|
251
|
-
when pa then left
|
252
|
-
when pb then up
|
253
|
-
when pc then upleft
|
254
|
-
end
|
255
|
-
end
|
267
|
+
nrows.times do |irow|
|
268
|
+
line = Utils::BitReader.new(data[irow * bpr, bpr])
|
256
269
|
|
257
|
-
|
258
|
-
|
259
|
-
|
270
|
+
diffpixel = ::Array.new(colors, 0)
|
271
|
+
columns.times do
|
272
|
+
pixel = ::Array.new(colors) { line.read(bpc) }
|
273
|
+
diffpixel = diffpixel.zip(pixel).map! { |diff, c| yield(c, diff) & bitmask }
|
260
274
|
|
261
|
-
|
262
|
-
|
275
|
+
diffpixel.each do |c|
|
276
|
+
result.write(c, bpc)
|
263
277
|
end
|
278
|
+
end
|
264
279
|
|
265
|
-
|
266
|
-
bpr = (colors * bpc * columns + 7) >> 3
|
267
|
-
nrows = data.size / bpr
|
268
|
-
bitmask = (1 << bpc) - 1
|
269
|
-
result = Utils::BitWriter.new
|
270
|
-
|
271
|
-
nrows.times do |irow|
|
272
|
-
line = Utils::BitReader.new(data[irow * bpr, bpr])
|
273
|
-
|
274
|
-
diffpixel = ::Array.new(colors, 0)
|
275
|
-
columns.times do
|
276
|
-
pixel = ::Array.new(colors) { line.read(bpc) }
|
277
|
-
diffpixel = diffpixel.zip(pixel).map!{|diff, c| yield(c, diff) & bitmask}
|
278
|
-
|
279
|
-
diffpixel.each do |c|
|
280
|
-
result.write(c, bpc)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
result.final
|
285
|
-
end
|
286
|
-
|
287
|
-
result.final.to_s
|
288
|
-
end
|
280
|
+
result.final
|
289
281
|
end
|
290
282
|
|
283
|
+
result.final.to_s
|
284
|
+
end
|
291
285
|
end
|
286
|
+
end
|
292
287
|
end
|