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,357 +1,354 @@
|
|
1
|
-
|
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
|
+
#
|
2
20
|
|
3
|
-
|
4
|
-
Copyright (C) 2016 Guillaume Delugré.
|
21
|
+
require 'origami/filters/ccitt/tables'
|
5
22
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
23
|
+
module Origami
|
24
|
+
module Filter
|
25
|
+
class InvalidCCITTFaxDataError < DecodeError # :nodoc:
|
26
|
+
end
|
10
27
|
|
11
|
-
|
12
|
-
|
13
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
-
GNU Lesser General Public License for more details.
|
28
|
+
class CCITTFaxFilterError < Error # :nodoc:
|
29
|
+
end
|
15
30
|
|
16
|
-
|
17
|
-
|
31
|
+
#
|
32
|
+
# Class representing a Filter used to encode and decode data with CCITT-facsimile compression algorithm.
|
33
|
+
#
|
34
|
+
class CCITTFax
|
35
|
+
include Filter
|
36
|
+
|
37
|
+
class DecodeParms < Dictionary
|
38
|
+
include StandardObject
|
39
|
+
|
40
|
+
field :K, Type: Integer, Default: 0
|
41
|
+
field :EndOfLine, Type: Boolean, Default: false
|
42
|
+
field :EncodedByteAlign, Type: Boolean, Default: false
|
43
|
+
field :Columns, Type: Integer, Default: 1728
|
44
|
+
field :Rows, Type: Integer, Default: 0
|
45
|
+
field :EndOfBlock, Type: Boolean, Default: true
|
46
|
+
field :BlackIs1, Type: Boolean, Default: false
|
47
|
+
field :DamagedRowsBeforeError, Type: :Integer, Default: 0
|
48
|
+
end
|
49
|
+
|
50
|
+
EOL = codeword('000000000001')
|
51
|
+
RTC = codeword('000000000001' * 6)
|
52
|
+
|
53
|
+
#
|
54
|
+
# Creates a new CCITT Fax Filter.
|
55
|
+
#
|
56
|
+
def initialize(parameters = {})
|
57
|
+
super(DecodeParms.new(parameters))
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Encodes data using CCITT-facsimile compression method.
|
62
|
+
#
|
63
|
+
def encode(stream)
|
64
|
+
mode = @params.key?(:K) ? @params.K.value : 0
|
65
|
+
colors = (@params.BlackIs1 == true) ? [0, 1] : [1, 0]
|
66
|
+
use_eob = (@params.EndOfBlock.nil? or @params.EndOfBlock == true)
|
67
|
+
use_eol = (@params.EndOfLine == true)
|
68
|
+
white, _black = colors
|
69
|
+
|
70
|
+
bitr = Utils::BitReader.new(stream)
|
71
|
+
bitw = Utils::BitWriter.new
|
72
|
+
|
73
|
+
unless mode.is_a?(::Integer) && (mode <= 0)
|
74
|
+
raise NotImplementedError.new("CCITT encoding scheme not supported", input_data: stream)
|
75
|
+
end
|
18
76
|
|
19
|
-
|
77
|
+
# Use a single row if no width has been set.
|
78
|
+
@params[:Columns] ||= stream.size * 8
|
79
|
+
columns = @params.Columns.value
|
20
80
|
|
21
|
-
|
81
|
+
unless columns.is_a?(::Integer) && (columns >= 0)
|
82
|
+
raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
|
83
|
+
end
|
22
84
|
|
23
|
-
|
85
|
+
if columns > 0
|
86
|
+
# Group 4 requires an imaginary white line
|
87
|
+
if mode < 0
|
88
|
+
prev_line = Utils::BitWriter.new
|
89
|
+
write_bit_range(prev_line, white, columns)
|
90
|
+
prev_line = Utils::BitReader.new(prev_line.final.to_s)
|
91
|
+
end
|
92
|
+
|
93
|
+
until bitr.eod?
|
94
|
+
# Emit line synchronization code.
|
95
|
+
bitw.write(*EOL) if use_eol
|
96
|
+
|
97
|
+
if mode == 0
|
98
|
+
encode_one_dimensional_line(bitr, bitw, columns, colors)
|
99
|
+
elsif mode < 0
|
100
|
+
encode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Emit return-to-control code.
|
106
|
+
bitw.write(*RTC) if use_eob
|
107
|
+
|
108
|
+
bitw.final.to_s
|
109
|
+
end
|
24
110
|
|
25
|
-
|
111
|
+
#
|
112
|
+
# Decodes data using CCITT-facsimile compression method.
|
113
|
+
#
|
114
|
+
def decode(stream)
|
115
|
+
mode = @params.key?(:K) ? @params.K.value : 0
|
26
116
|
|
27
|
-
|
117
|
+
unless mode.is_a?(::Integer) && (mode <= 0)
|
118
|
+
raise NotImplementedError.new("CCITT encoding scheme not supported", input_data: stream)
|
28
119
|
end
|
29
120
|
|
30
|
-
|
121
|
+
columns = @params.has_key?(:Columns) ? @params.Columns.value : 1728
|
122
|
+
unless columns.is_a?(::Integer) && (columns >= 0)
|
123
|
+
raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
|
31
124
|
end
|
32
125
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
field :DamagedRowsBeforeError, :Type => :Integer, :Default => 0
|
50
|
-
end
|
126
|
+
colors = (@params.BlackIs1 == true) ? [0, 1] : [1, 0]
|
127
|
+
white, _black = colors
|
128
|
+
params =
|
129
|
+
{
|
130
|
+
is_aligned?: (@params.EncodedByteAlign == true),
|
131
|
+
has_eob?: (@params.EndOfBlock.nil? or @params.EndOfBlock == true),
|
132
|
+
has_eol?: (@params.EndOfLine == true)
|
133
|
+
}
|
134
|
+
|
135
|
+
unless params[:has_eob?]
|
136
|
+
rows = @params.key?(:Rows) ? @params.Rows.value : 0
|
137
|
+
|
138
|
+
unless rows.is_a?(::Integer) && (rows >= 0)
|
139
|
+
raise CCITTFaxFilterError.new("Invalid value for parameter `Rows'", input_data: stream)
|
140
|
+
end
|
141
|
+
end
|
51
142
|
|
52
|
-
|
53
|
-
|
143
|
+
bitr = Utils::BitReader.new(stream)
|
144
|
+
bitw = Utils::BitWriter.new
|
54
145
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
146
|
+
# Group 4 requires an imaginary white line
|
147
|
+
if (columns > 0) && (mode < 0)
|
148
|
+
prev_line = Utils::BitWriter.new
|
149
|
+
write_bit_range(prev_line, white, columns)
|
150
|
+
prev_line = Utils::BitReader.new(prev_line.final.to_s)
|
151
|
+
end
|
61
152
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
unless columns.is_a?(::Integer) and columns >= 0
|
84
|
-
raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
|
85
|
-
end
|
86
|
-
|
87
|
-
if columns > 0
|
88
|
-
# Group 4 requires an imaginary white line
|
89
|
-
if mode < 0
|
90
|
-
prev_line = Utils::BitWriter.new
|
91
|
-
write_bit_range(prev_line, white, columns)
|
92
|
-
prev_line = Utils::BitReader.new(prev_line.final.to_s)
|
93
|
-
end
|
94
|
-
|
95
|
-
until bitr.eod?
|
96
|
-
# Emit line synchronization code.
|
97
|
-
bitw.write(*EOL) if use_eol
|
98
|
-
|
99
|
-
case
|
100
|
-
when mode == 0
|
101
|
-
encode_one_dimensional_line(bitr, bitw, columns, colors)
|
102
|
-
when mode < 0
|
103
|
-
encode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Emit return-to-control code.
|
109
|
-
bitw.write(*RTC) if use_eob
|
110
|
-
|
111
|
-
bitw.final.to_s
|
153
|
+
until bitr.eod? || (rows == 0)
|
154
|
+
# realign the read line on a 8-bit boundary if required
|
155
|
+
align_input(bitr) if params[:is_aligned?]
|
156
|
+
|
157
|
+
# received return-to-control code
|
158
|
+
if params[:has_eob?] && (bitr.peek(RTC[1]) == RTC[0])
|
159
|
+
bitr.pos += RTC[1]
|
160
|
+
break
|
161
|
+
end
|
162
|
+
|
163
|
+
break if columns == 0
|
164
|
+
|
165
|
+
# checking for the presence of EOL
|
166
|
+
if bitr.peek(EOL[1]) != EOL[0]
|
167
|
+
if params[:has_eol?]
|
168
|
+
raise InvalidCCITTFaxDataError.new(
|
169
|
+
"No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
|
170
|
+
input_data: stream,
|
171
|
+
decoded_data: bitw.final.to_s
|
172
|
+
)
|
112
173
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
columns = @params.has_key?(:Columns) ? @params.Columns.value : 1728
|
125
|
-
unless columns.is_a?(::Integer) and columns >= 0
|
126
|
-
raise CCITTFaxFilterError.new("Invalid value for parameter `Columns'", input_data: stream)
|
127
|
-
end
|
128
|
-
|
129
|
-
colors = (@params.BlackIs1 == true) ? [0,1] : [1,0]
|
130
|
-
white, _black = colors
|
131
|
-
params =
|
132
|
-
{
|
133
|
-
is_aligned?: (@params.EncodedByteAlign == true),
|
134
|
-
has_eob?: (@params.EndOfBlock.nil? or @params.EndOfBlock == true),
|
135
|
-
has_eol?: (@params.EndOfLine == true)
|
136
|
-
}
|
137
|
-
|
138
|
-
unless params[:has_eob?]
|
139
|
-
rows = @params.key?(:Rows) ? @params.Rows.value : 0
|
140
|
-
|
141
|
-
unless rows.is_a?(::Integer) and rows >= 0
|
142
|
-
raise CCITTFaxFilterError.new("Invalid value for parameter `Rows'", input_data: stream)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
bitr = Utils::BitReader.new(stream)
|
147
|
-
bitw = Utils::BitWriter.new
|
148
|
-
|
149
|
-
# Group 4 requires an imaginary white line
|
150
|
-
if columns > 0 and mode < 0
|
151
|
-
prev_line = Utils::BitWriter.new
|
152
|
-
write_bit_range(prev_line, white, columns)
|
153
|
-
prev_line = Utils::BitReader.new(prev_line.final.to_s)
|
154
|
-
end
|
155
|
-
|
156
|
-
until bitr.eod? or rows == 0
|
157
|
-
# realign the read line on a 8-bit boundary if required
|
158
|
-
align_input(bitr) if params[:is_aligned?]
|
159
|
-
|
160
|
-
# received return-to-control code
|
161
|
-
if params[:has_eob?] and bitr.peek(RTC[1]) == RTC[0]
|
162
|
-
bitr.pos += RTC[1]
|
163
|
-
break
|
164
|
-
end
|
165
|
-
|
166
|
-
break if columns == 0
|
167
|
-
|
168
|
-
# checking for the presence of EOL
|
169
|
-
if bitr.peek(EOL[1]) != EOL[0]
|
170
|
-
raise InvalidCCITTFaxDataError.new(
|
171
|
-
"No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
|
172
|
-
input_data: stream,
|
173
|
-
decoded_data: bitw.final.to_s
|
174
|
-
) if params[:has_eol?]
|
175
|
-
else
|
176
|
-
bitr.pos += EOL[1]
|
177
|
-
end
|
178
|
-
|
179
|
-
begin
|
180
|
-
case
|
181
|
-
when mode == 0
|
182
|
-
decode_one_dimensional_line(bitr, bitw, columns, colors)
|
183
|
-
when mode < 0
|
184
|
-
decode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
|
185
|
-
end
|
186
|
-
rescue DecodeError => error
|
187
|
-
error.input_data = stream
|
188
|
-
error.decoded_data = bitw.final.to_s
|
189
|
-
|
190
|
-
raise error
|
191
|
-
end
|
192
|
-
|
193
|
-
rows -= 1 unless params[:has_eob?]
|
194
|
-
end
|
195
|
-
|
196
|
-
bitw.final.to_s
|
174
|
+
else
|
175
|
+
bitr.pos += EOL[1]
|
176
|
+
end
|
177
|
+
|
178
|
+
begin
|
179
|
+
if mode == 0
|
180
|
+
decode_one_dimensional_line(bitr, bitw, columns, colors)
|
181
|
+
elsif mode < 0
|
182
|
+
decode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
|
197
183
|
end
|
184
|
+
rescue DecodeError => error
|
185
|
+
error.input_data = stream
|
186
|
+
error.decoded_data = bitw.final.to_s
|
198
187
|
|
199
|
-
|
200
|
-
|
201
|
-
def encode_one_dimensional_line(input, output, columns, colors) #:nodoc:
|
202
|
-
scan_len = 0
|
203
|
-
white, _black = colors
|
204
|
-
current_color = white
|
205
|
-
length = 0
|
206
|
-
|
207
|
-
return if columns == 0
|
208
|
-
|
209
|
-
# Process each bit in line.
|
210
|
-
loop do
|
211
|
-
if input.read(1) == current_color
|
212
|
-
scan_len += 1
|
213
|
-
else
|
214
|
-
if current_color == white
|
215
|
-
put_white_bits(output, scan_len)
|
216
|
-
else
|
217
|
-
put_black_bits(output, scan_len)
|
218
|
-
end
|
219
|
-
|
220
|
-
current_color ^= 1
|
221
|
-
scan_len = 1
|
222
|
-
end
|
223
|
-
|
224
|
-
length += 1
|
225
|
-
break if length == columns
|
226
|
-
end
|
227
|
-
|
228
|
-
if current_color == white
|
229
|
-
put_white_bits(output, scan_len)
|
230
|
-
else
|
231
|
-
put_black_bits(output, scan_len)
|
232
|
-
end
|
233
|
-
|
234
|
-
# Align encoded lign on a 8-bit boundary.
|
235
|
-
align_output(write) if @params.EncodedByteAlign == true
|
236
|
-
end
|
188
|
+
raise error
|
189
|
+
end
|
237
190
|
|
238
|
-
|
239
|
-
|
240
|
-
return if input.pos % 8 == 0
|
241
|
-
input.pos += 8 - (input.pos % 8)
|
242
|
-
end
|
191
|
+
rows -= 1 unless params[:has_eob?]
|
192
|
+
end
|
243
193
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
194
|
+
bitw.final.to_s
|
195
|
+
end
|
196
|
+
|
197
|
+
private
|
198
|
+
|
199
|
+
def encode_one_dimensional_line(input, output, columns, colors) # :nodoc:
|
200
|
+
scan_len = 0
|
201
|
+
white, _black = colors
|
202
|
+
current_color = white
|
203
|
+
length = 0
|
249
204
|
|
250
|
-
|
251
|
-
|
205
|
+
return if columns == 0
|
206
|
+
|
207
|
+
# Process each bit in line.
|
208
|
+
loop do
|
209
|
+
if input.read(1) == current_color
|
210
|
+
scan_len += 1
|
211
|
+
else
|
212
|
+
if current_color == white
|
213
|
+
put_white_bits(output, scan_len)
|
214
|
+
else
|
215
|
+
put_black_bits(output, scan_len)
|
252
216
|
end
|
253
217
|
|
254
|
-
|
255
|
-
|
256
|
-
|
218
|
+
current_color ^= 1
|
219
|
+
scan_len = 1
|
220
|
+
end
|
257
221
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
bit_length = get_white_bits(input)
|
262
|
-
else
|
263
|
-
bit_length = get_black_bits(input)
|
264
|
-
end
|
222
|
+
length += 1
|
223
|
+
break if length == columns
|
224
|
+
end
|
265
225
|
|
266
|
-
|
226
|
+
if current_color == white
|
227
|
+
put_white_bits(output, scan_len)
|
228
|
+
else
|
229
|
+
put_black_bits(output, scan_len)
|
230
|
+
end
|
267
231
|
|
268
|
-
|
232
|
+
# Align encoded lign on a 8-bit boundary.
|
233
|
+
align_output(write) if @params.EncodedByteAlign == true
|
234
|
+
end
|
269
235
|
|
270
|
-
|
236
|
+
# Align input to a byte boundary.
|
237
|
+
def align_input(input)
|
238
|
+
return if input.pos % 8 == 0
|
239
|
+
input.pos += 8 - (input.pos % 8)
|
240
|
+
end
|
271
241
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
242
|
+
# Align output to a byte boundary by adding some zeros.
|
243
|
+
def align_output(output)
|
244
|
+
return if output.pos % 8 == 0
|
245
|
+
output.write(0, 8 - (output.pos % 8))
|
246
|
+
end
|
276
247
|
|
277
|
-
|
278
|
-
|
279
|
-
|
248
|
+
def encode_two_dimensional_line(_input, _output, _columns, _colors, _prev_line) # :nodoc:
|
249
|
+
raise NotImplementedError "CCITT two-dimensional encoding scheme not supported."
|
250
|
+
end
|
280
251
|
|
281
|
-
|
282
|
-
|
283
|
-
|
252
|
+
def decode_one_dimensional_line(input, output, columns, colors) # :nodoc:
|
253
|
+
white, _black = colors
|
254
|
+
current_color = white
|
284
255
|
|
285
|
-
|
286
|
-
|
287
|
-
|
256
|
+
line_length = 0
|
257
|
+
while line_length < columns
|
258
|
+
bit_length = if current_color == white
|
259
|
+
get_white_bits(input)
|
260
|
+
else
|
261
|
+
get_black_bits(input)
|
262
|
+
end
|
288
263
|
|
289
|
-
|
290
|
-
bits = 0
|
291
|
-
check_conf = true
|
292
|
-
|
293
|
-
while check_conf
|
294
|
-
check_conf = false
|
295
|
-
(2..13).each do |length|
|
296
|
-
codeword = bitr.peek(length)
|
297
|
-
config_value = config_words[[codeword, length]]
|
298
|
-
|
299
|
-
if config_value
|
300
|
-
bitr.pos += length
|
301
|
-
bits += config_value
|
302
|
-
check_conf = true if config_value == 2560
|
303
|
-
break
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
(2..13).each do |length|
|
309
|
-
codeword = bitr.peek(length)
|
310
|
-
term_value = term_words[[codeword, length]]
|
311
|
-
|
312
|
-
if term_value
|
313
|
-
bitr.pos += length
|
314
|
-
bits += term_value
|
315
|
-
|
316
|
-
return bits
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
nil
|
321
|
-
end
|
264
|
+
raise InvalidCCITTFaxDataError, "Unfinished line (at bit pos #{input.pos}/#{input.size}})" if bit_length.nil?
|
322
265
|
|
323
|
-
|
324
|
-
table.rassoc [codeword, length]
|
325
|
-
end
|
266
|
+
line_length += bit_length
|
326
267
|
|
327
|
-
|
328
|
-
put_color_bits(bitw, length, WHITE_CONFIGURATION_ENCODE_TABLE, WHITE_TERMINAL_ENCODE_TABLE)
|
329
|
-
end
|
268
|
+
raise InvalidCCITTFaxDataError, "Line is too long (at bit pos #{input.pos}/#{input.size}})" if line_length > columns
|
330
269
|
|
331
|
-
|
332
|
-
|
270
|
+
write_bit_range(output, current_color, bit_length)
|
271
|
+
current_color ^= 1
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def decode_two_dimensional_line(_input, _output, _columns, _colors, _prev_line) # :nodoc:
|
276
|
+
raise NotImplementedError, "CCITT two-dimensional decoding scheme not supported."
|
277
|
+
end
|
278
|
+
|
279
|
+
def get_white_bits(bitr) # :nodoc:
|
280
|
+
get_color_bits(bitr, WHITE_CONFIGURATION_DECODE_TABLE, WHITE_TERMINAL_DECODE_TABLE)
|
281
|
+
end
|
282
|
+
|
283
|
+
def get_black_bits(bitr) # :nodoc:
|
284
|
+
get_color_bits(bitr, BLACK_CONFIGURATION_DECODE_TABLE, BLACK_TERMINAL_DECODE_TABLE)
|
285
|
+
end
|
286
|
+
|
287
|
+
def get_color_bits(bitr, config_words, term_words) # :nodoc:
|
288
|
+
bits = 0
|
289
|
+
check_conf = true
|
290
|
+
|
291
|
+
while check_conf
|
292
|
+
check_conf = false
|
293
|
+
(2..13).each do |length|
|
294
|
+
codeword = bitr.peek(length)
|
295
|
+
config_value = config_words[[codeword, length]]
|
296
|
+
|
297
|
+
if config_value
|
298
|
+
bitr.pos += length
|
299
|
+
bits += config_value
|
300
|
+
check_conf = true if config_value == 2560
|
301
|
+
break
|
333
302
|
end
|
303
|
+
end
|
304
|
+
end
|
334
305
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
length -= 2560
|
339
|
-
end
|
306
|
+
(2..13).each do |length|
|
307
|
+
codeword = bitr.peek(length)
|
308
|
+
term_value = term_words[[codeword, length]]
|
340
309
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
length -= conf_length
|
345
|
-
end
|
310
|
+
if term_value
|
311
|
+
bitr.pos += length
|
312
|
+
bits += term_value
|
346
313
|
|
347
|
-
|
348
|
-
|
314
|
+
return bits
|
315
|
+
end
|
316
|
+
end
|
349
317
|
|
350
|
-
|
351
|
-
|
352
|
-
|
318
|
+
nil
|
319
|
+
end
|
320
|
+
|
321
|
+
def lookup_bits(table, codeword, length)
|
322
|
+
table.rassoc [codeword, length]
|
323
|
+
end
|
324
|
+
|
325
|
+
def put_white_bits(bitw, length) # :nodoc:
|
326
|
+
put_color_bits(bitw, length, WHITE_CONFIGURATION_ENCODE_TABLE, WHITE_TERMINAL_ENCODE_TABLE)
|
327
|
+
end
|
328
|
+
|
329
|
+
def put_black_bits(bitw, length) # :nodoc:
|
330
|
+
put_color_bits(bitw, length, BLACK_CONFIGURATION_ENCODE_TABLE, BLACK_TERMINAL_ENCODE_TABLE)
|
331
|
+
end
|
332
|
+
|
333
|
+
def put_color_bits(bitw, length, config_words, term_words) # :nodoc:
|
334
|
+
while length > 2559
|
335
|
+
bitw.write(*config_words[2560])
|
336
|
+
length -= 2560
|
353
337
|
end
|
354
|
-
CCF = CCITTFax
|
355
338
|
|
339
|
+
if length > 63
|
340
|
+
conf_length = (length >> 6) << 6
|
341
|
+
bitw.write(*config_words[conf_length])
|
342
|
+
length -= conf_length
|
343
|
+
end
|
344
|
+
|
345
|
+
bitw.write(*term_words[length])
|
346
|
+
end
|
347
|
+
|
348
|
+
def write_bit_range(bitw, bit_value, length) # :nodoc:
|
349
|
+
bitw.write((bit_value << length) - bit_value, length)
|
350
|
+
end
|
356
351
|
end
|
352
|
+
CCF = CCITTFax
|
353
|
+
end
|
357
354
|
end
|