jpegsan 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7e4ba515dd409c7360348c352569dc827d5a3280859ae6da174c257e56fa63fc
4
+ data.tar.gz: d7f9a09a421bab51fcc8701f0c1cd5280dd8564855160efd92638612ddf1f7af
5
+ SHA512:
6
+ metadata.gz: a50a9e68195f37dc5879055a09c8fc0e0ca1e0e79cdb45da4e91f67d25b1cd57e307c269c56124e530ee0ab9f595ac50c78c1057fe9c6f70c23f5b22d7c47c73
7
+ data.tar.gz: c18d7a05518699bc30a60ea88dff385f1f5116e18043b688e816be0112b708bbf5ad04c22f256a8dc9159b9f97118f799368701dc75f2dc5bb0d34519073cf18
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.0
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in jpegsan.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,41 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jpegsan (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.1.2)
10
+ diff-lcs (1.3)
11
+ method_source (0.9.0)
12
+ pry (0.11.3)
13
+ coderay (~> 1.1.0)
14
+ method_source (~> 0.9.0)
15
+ rake (10.5.0)
16
+ rspec (3.8.0)
17
+ rspec-core (~> 3.8.0)
18
+ rspec-expectations (~> 3.8.0)
19
+ rspec-mocks (~> 3.8.0)
20
+ rspec-core (3.8.0)
21
+ rspec-support (~> 3.8.0)
22
+ rspec-expectations (3.8.1)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.8.0)
25
+ rspec-mocks (3.8.0)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.8.0)
28
+ rspec-support (3.8.0)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 1.16)
35
+ jpegsan!
36
+ pry
37
+ rake (~> 10.0)
38
+ rspec (~> 3.0)
39
+
40
+ BUNDLED WITH
41
+ 1.16.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Shimpei Makimoto
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ Jpegsan
2
+ ---
3
+
4
+ Just another JPEG file reader/writer for data destruction freaks.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'jpegsan'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install jpegsan
21
+
22
+ ## Usage
23
+
24
+ TODO: Write usage instructions here
25
+
26
+ ## Development
27
+
28
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
29
+
30
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
31
+
32
+ ## Contributing
33
+
34
+ Bug reports and pull requests are welcome on GitHub at https://github.com/makimoto/jpegsan.
35
+
36
+ ## License
37
+
38
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jpegsan"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/jpegsan.gemspec ADDED
@@ -0,0 +1,27 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "jpegsan/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jpegsan"
8
+ spec.version = Jpegsan::VERSION
9
+ spec.authors = ["Shimpei Makimoto"]
10
+ spec.email = ["s@makimoto.org"]
11
+
12
+ spec.summary = %q{Just another JPEG file reader/writer for data destruction freaks.}
13
+ spec.homepage = "https://github.com/makimoto/glitchsan"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.16"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "pry"
27
+ end
@@ -0,0 +1,168 @@
1
+ class Jpegsan::Jpeg
2
+ attr_accessor :data
3
+
4
+ JpegMarker = Struct.new(:code_suffix, :symbol, :description, :data_sequence) do
5
+ def code
6
+ "\xff#{code_suffix}".b
7
+ end
8
+
9
+ def to_bytes
10
+ "#{code}#{data_sequence}".b
11
+ end
12
+
13
+ def sequence_in_hex
14
+ if data_sequence.nil?
15
+ return nil
16
+ end
17
+ data_sequence.unpack('H*').first.chars.each_slice(2).map(&:join).join(' ')
18
+ end
19
+ end
20
+
21
+ # Table B.1 in https://www.w3.org/Graphics/JPEG/itu-t81.pdf
22
+ JPEG_MARKERS =
23
+ [
24
+ JpegMarker.new(?\xc0, 'SOF0', 'non-differential, Huffman coding - Baseline DCT'),
25
+ JpegMarker.new(?\xc1, 'SOF1', 'non-differential, Huffman coding - Extended sequential DCT'),
26
+ JpegMarker.new(?\xc2, 'SOF2', 'non-differential, Huffman coding - Progressive DCT'),
27
+ JpegMarker.new(?\xc3, 'SOF3', 'non-differential, Huffman coding - Lossless (sequential)'),
28
+ JpegMarker.new(?\xc5, 'SOF5', 'differential, Huffman coding - Differential sequential DCT'),
29
+ JpegMarker.new(?\xc6, 'SOF6', 'differential, Huffman coding - Differential progressive DCT'),
30
+ JpegMarker.new(?\xc7, 'SOF7', 'differential, Huffman coding - Differential lossless (sequential)'),
31
+ JpegMarker.new(?\xc8, 'JPG', 'non-differential, arithmetic coding - Reversed for JPEG extensions'),
32
+ JpegMarker.new(?\xc9, 'SOF9', 'non-differential, arithmetic coding - Extended sequential DCT'),
33
+ JpegMarker.new(?\xca, 'SOF10', 'non-differential, arithmetic coding - Progressive DCT'),
34
+ JpegMarker.new(?\xcb, 'SOF11', 'non-differential, arithmetic coding - Lossless (sequential)'),
35
+ JpegMarker.new(?\xcd, 'SOF13', 'differential, arithmetic coding - Differential sequential DCT'),
36
+ JpegMarker.new(?\xce, 'SOF14', 'differential, arithmetic coding - Differential progressive DCT'),
37
+ JpegMarker.new(?\xcf, 'SOF15', 'differential, arithmetic coding - Differential lossless (sequential)'),
38
+ JpegMarker.new(?\xc4, 'DHT', 'Huffman table specification - Define Huffman table(s)'),
39
+ JpegMarker.new(?\xcc, 'DAC', 'Arithmetic coding conditioning specification - Define arithmetic coding conditioning(s)'),
40
+ JpegMarker.new(?\xd0, 'RST0', 'Restart interval termination - Restart with modulo count 0'),
41
+ JpegMarker.new(?\xd1, 'RST1', 'Restart interval termination - Restart with modulo count 1'),
42
+ JpegMarker.new(?\xd2, 'RST2', 'Restart interval termination - Restart with modulo count 2'),
43
+ JpegMarker.new(?\xd3, 'RST3', 'Restart interval termination - Restart with modulo count 3'),
44
+ JpegMarker.new(?\xd4, 'RST4', 'Restart interval termination - Restart with modulo count 4'),
45
+ JpegMarker.new(?\xd5, 'RST5', 'Restart interval termination - Restart with modulo count 5'),
46
+ JpegMarker.new(?\xd6, 'RST6', 'Restart interval termination - Restart with modulo count 6'),
47
+ JpegMarker.new(?\xd7, 'RST7', 'Restart interval termination - Restart with modulo count 7'),
48
+ JpegMarker.new(?\xd8, 'SOI', 'Start of image'),
49
+ JpegMarker.new(?\xd9, 'EOI', 'End of image'),
50
+ JpegMarker.new(?\xda, 'SOS', 'Start of scan'),
51
+ JpegMarker.new(?\xdb, 'DQT', 'Define quantization table(s)'),
52
+ JpegMarker.new(?\xdc, 'DNL', 'Define number of lines'),
53
+ JpegMarker.new(?\xdd, 'DRI', 'Define restart interval'),
54
+ JpegMarker.new(?\xde, 'DHP', 'Define hierarchical progression'),
55
+ JpegMarker.new(?\xdf, 'EXP', 'Expand reference component(s)'),
56
+ JpegMarker.new(?\xe0, 'APP0', 'Reserved for application segments'),
57
+ JpegMarker.new(?\xe1, 'APP1', 'Reserved for application segments'),
58
+ JpegMarker.new(?\xe2, 'APP2', 'Reserved for application segments'),
59
+ JpegMarker.new(?\xe3, 'APP3', 'Reserved for application segments'),
60
+ JpegMarker.new(?\xe4, 'APP4', 'Reserved for application segments'),
61
+ JpegMarker.new(?\xe5, 'APP5', 'Reserved for application segments'),
62
+ JpegMarker.new(?\xe6, 'APP6', 'Reserved for application segments'),
63
+ JpegMarker.new(?\xe7, 'APP7', 'Reserved for application segments'),
64
+ JpegMarker.new(?\xe8, 'APP8', 'Reserved for application segments'),
65
+ JpegMarker.new(?\xe9, 'APP9', 'Reserved for application segments'),
66
+ JpegMarker.new(?\xea, 'APP10', 'Reserved for application segments'),
67
+ JpegMarker.new(?\xeb, 'APP11', 'Reserved for application segments'),
68
+ JpegMarker.new(?\xec, 'APP12', 'Reserved for application segments'),
69
+ JpegMarker.new(?\xed, 'APP13', 'Reserved for application segments'),
70
+ JpegMarker.new(?\xee, 'APP14', 'Reserved for application segments'),
71
+ JpegMarker.new(?\xef, 'APP15', 'Reserved for application segments'),
72
+ JpegMarker.new(?\xf0, 'JPG0', 'Reserved for JPEG extensions'),
73
+ JpegMarker.new(?\xf1, 'JPG1', 'Reserved for JPEG extensions'),
74
+ JpegMarker.new(?\xf2, 'JPG2', 'Reserved for JPEG extensions'),
75
+ JpegMarker.new(?\xf3, 'JPG3', 'Reserved for JPEG extensions'),
76
+ JpegMarker.new(?\xf4, 'JPG4', 'Reserved for JPEG extensions'),
77
+ JpegMarker.new(?\xf5, 'JPG5', 'Reserved for JPEG extensions'),
78
+ JpegMarker.new(?\xf6, 'JPG6', 'Reserved for JPEG extensions'),
79
+ JpegMarker.new(?\xf7, 'JPG7', 'Reserved for JPEG extensions'),
80
+ JpegMarker.new(?\xf8, 'JPG8', 'Reserved for JPEG extensions'),
81
+ JpegMarker.new(?\xf9, 'JPG9', 'Reserved for JPEG extensions'),
82
+ JpegMarker.new(?\xfa, 'JPG10', 'Reserved for JPEG extensions'),
83
+ JpegMarker.new(?\xfb, 'JPG11', 'Reserved for JPEG extensions'),
84
+ JpegMarker.new(?\xfc, 'JPG12', 'Reserved for JPEG extensions'),
85
+ JpegMarker.new(?\xfd, 'JPG13', 'Reserved for JPEG extensions'),
86
+ JpegMarker.new(?\xfe, 'COM', 'Comment'),
87
+ JpegMarker.new(?\x01, 'TEM', 'For temporary private use in arithmetic coding'),
88
+ # Markers for "Reserved" are from X'FF02' thru X'FFBF' actually, but we have only X'FF02' for this.
89
+ JpegMarker.new(?\x02, 'RES', 'Reserved'),
90
+ ]
91
+
92
+ MARKER_BY_SUFFIX = JPEG_MARKERS.map {|a| [a.code_suffix, a]}.to_h
93
+
94
+ def initialize(file)
95
+ @data = []
96
+
97
+ items = []
98
+ marker = false
99
+ current_marker = nil
100
+
101
+ file.read.chars.each do |e|
102
+ if marker
103
+ marker = false
104
+ # "X'FF00' is NOT a marker but X'FF' value"
105
+ if e == ?\x00
106
+ items << ?\xff
107
+ items << ?\x00
108
+ next
109
+ end
110
+
111
+ # "X'FFFF' is treated as is
112
+ if e == ?\xff
113
+ items << ?\xff
114
+ items << ?\xff
115
+ next
116
+ end
117
+
118
+ if !items.empty?
119
+ current_marker.data_sequence = items.join.b
120
+ items.clear
121
+ end
122
+
123
+ current_marker = MARKER_BY_SUFFIX[e].dup
124
+ if current_marker.nil?
125
+ current_marker = JpegMarker.new(e, 'UNK', 'Unknown marker')
126
+ end
127
+
128
+ @data << current_marker
129
+ next
130
+ end
131
+
132
+ if e == ?\xff
133
+ marker = true
134
+ next
135
+ end
136
+ items << e
137
+ end
138
+
139
+ if !items.empty?
140
+ @data << items.join
141
+ end
142
+ end
143
+
144
+ def save(dest = 'out.jpg')
145
+ @last_filename = dest
146
+ open(dest, 'w').write(@data.map(&:to_bytes).join)
147
+ end
148
+
149
+ def open_file
150
+ if @last_filename.nil?
151
+ STDERR.puts('WARN: No file to open')
152
+ return
153
+ end
154
+
155
+ system('open', @last_filename)
156
+ end
157
+
158
+ def show_list
159
+ @data.each do |e|
160
+ STDERR.puts "= MARKER #{e.code_suffix.b.inspect}: #{e&.symbol} (#{e&.description}) ="
161
+ if e.sequence_in_hex
162
+ STDERR.puts e.sequence_in_hex
163
+ end
164
+ end
165
+
166
+ nil
167
+ end
168
+ end
@@ -0,0 +1,3 @@
1
+ module Jpegsan
2
+ VERSION = "0.1.0"
3
+ end
data/lib/jpegsan.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'jpegsan/jpeg'
2
+ module Jpegsan
3
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jpegsan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shimpei Makimoto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-08-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - s@makimoto.org
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - bin/console
85
+ - bin/setup
86
+ - jpegsan.gemspec
87
+ - lib/jpegsan.rb
88
+ - lib/jpegsan/jpeg.rb
89
+ - lib/jpegsan/version.rb
90
+ homepage: https://github.com/makimoto/glitchsan
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.7.6
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Just another JPEG file reader/writer for data destruction freaks.
114
+ test_files: []