jpeg2moro 0.0.1
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.
- data/History.txt +4 -0
- data/Manifest.txt +13 -0
- data/README.rdoc +64 -0
- data/Rakefile +24 -0
- data/bin/jpeg2moro +102 -0
- data/lib/jpeg2moro.rb +201 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/jpeg2moro_spec.rb +11 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +8 -0
- data/tasks/rspec.rake +16 -0
- metadata +129 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= jpeg2moro
|
2
|
+
|
3
|
+
* http://github.com/2moro/jpeg2moro
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
JPEG2moro is a method of encoding arbitrary data (including an alpha channel) within the JPEG Application Segment APP10.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* converts image files to jpeg2moro format
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
# command line
|
16
|
+
|
17
|
+
# create a jpeg with transparency from a png file (creates image.jpg)
|
18
|
+
> ruby/scripts/jpeg2moro source.png
|
19
|
+
|
20
|
+
# specify alpha channel bit depth (1 bit) and output file output.jpg
|
21
|
+
> ruby/scripts/jpeg2moro source.png -a 1 -o output.jpg
|
22
|
+
|
23
|
+
# programmatically read from file
|
24
|
+
|
25
|
+
jpeg = JPEG2moro.new("source.png")
|
26
|
+
jpeg.save("output.jpg", :alpha_depth => 8)
|
27
|
+
|
28
|
+
# programmatically read from string
|
29
|
+
|
30
|
+
jpeg = JPEG2moro.with_data(File.read("source.png"))
|
31
|
+
jpeg.save("output.jpg", :alpha_depth => 8)
|
32
|
+
|
33
|
+
== REQUIREMENTS:
|
34
|
+
|
35
|
+
* rmagick
|
36
|
+
|
37
|
+
== INSTALL:
|
38
|
+
|
39
|
+
* sudo gem install jpeg2moro
|
40
|
+
|
41
|
+
== LICENSE:
|
42
|
+
|
43
|
+
(The MIT License)
|
44
|
+
|
45
|
+
Copyright (c) 2010 2moro mobile
|
46
|
+
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
48
|
+
a copy of this software and associated documentation files (the
|
49
|
+
'Software'), to deal in the Software without restriction, including
|
50
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
51
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
52
|
+
permit persons to whom the Software is furnished to do so, subject to
|
53
|
+
the following conditions:
|
54
|
+
|
55
|
+
The above copyright notice and this permission notice shall be
|
56
|
+
included in all copies or substantial portions of the Software.
|
57
|
+
|
58
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
59
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
60
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
61
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
62
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
63
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
64
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
#require 'fileutils'
|
5
|
+
#require './lib/jpeg2moro'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'jpeg2moro' do
|
14
|
+
self.developer '2moro mobile', 'support@2moro.com.au'
|
15
|
+
self.rubyforge_name = self.name # TODO this is default value
|
16
|
+
self.extra_deps = [['rmagick','>= 2.13.1']]
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'newgem/tasks'
|
20
|
+
#Dir['tasks/**/*.rake'].each { |t| load t }
|
21
|
+
|
22
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
23
|
+
# remove_task :default
|
24
|
+
# task :default => [:spec, :features]
|
data/bin/jpeg2moro
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
+
|
6
|
+
require 'jpeg2moro'
|
7
|
+
require 'getoptlong'
|
8
|
+
|
9
|
+
ARG_SPEC = [ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
10
|
+
[ '--test', '-n', GetoptLong::NO_ARGUMENT ],
|
11
|
+
[ '--output', '-o', GetoptLong::REQUIRED_ARGUMENT ],
|
12
|
+
[ '--debug', '-d', GetoptLong::NO_ARGUMENT ],
|
13
|
+
[ '--alpha-depth', '-a', GetoptLong::REQUIRED_ARGUMENT ],
|
14
|
+
[ '--quality', '-q', GetoptLong::REQUIRED_ARGUMENT ],
|
15
|
+
[ '--verbose', '-v', GetoptLong::NO_ARGUMENT ]
|
16
|
+
]
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# parse command line arguments
|
21
|
+
def command_line_options
|
22
|
+
opts = GetoptLong.new(*ARG_SPEC)
|
23
|
+
options = {}
|
24
|
+
opts.each do |opt,arg|
|
25
|
+
opt[0,2] = ''
|
26
|
+
opt = opt.gsub(/-/, '_').to_sym
|
27
|
+
case opt
|
28
|
+
when :help
|
29
|
+
puts usage
|
30
|
+
exit 0
|
31
|
+
else
|
32
|
+
options[opt] = arg ? arg : true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
options
|
36
|
+
end
|
37
|
+
|
38
|
+
def usage
|
39
|
+
usage = <<EOM
|
40
|
+
jpeg2moro - converts image files to jpeg2moro format
|
41
|
+
usage: jpeg2moro [OPTIONS] source_file [source_file ...]
|
42
|
+
|
43
|
+
options:
|
44
|
+
--help, -h: this help message
|
45
|
+
--output, -o: specify output filename
|
46
|
+
--debug, -d: turn on debugging output and file dumping
|
47
|
+
--alpha-depth, -a: set depth for alpha channel, default #{JPEG2moro::DEFAULT_ALPHA_DEPTH}
|
48
|
+
--quality, -q: jpeg compression level (0-100), default #{JPEG2moro::DEFAULT_QUALITY}
|
49
|
+
--verbose, -v: verbose mode
|
50
|
+
|
51
|
+
EOM
|
52
|
+
end
|
53
|
+
|
54
|
+
def output_filename(input)
|
55
|
+
file = File.basename(input)
|
56
|
+
file = file.sub(/\.[^.]+$/, '')
|
57
|
+
file + ".jpg"
|
58
|
+
end
|
59
|
+
|
60
|
+
begin
|
61
|
+
opts = command_line_options
|
62
|
+
input_files = ARGV
|
63
|
+
|
64
|
+
#opts[:input] = params.pop if !opts[:input] && $stdin.tty?
|
65
|
+
|
66
|
+
JPEG2moro.debug = opts[:debug]
|
67
|
+
|
68
|
+
if input_files.length == 0
|
69
|
+
puts usage
|
70
|
+
elsif opts[:output] && input_files.length > 1
|
71
|
+
puts "ERROR: output file option can only be used with one input file"
|
72
|
+
puts usage
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
|
76
|
+
output_opts = {}
|
77
|
+
[:alpha_depth, :quality].each do |i|
|
78
|
+
output_opts[i] = opts[i] if opts[i]
|
79
|
+
end
|
80
|
+
|
81
|
+
# convert input files to jpeg2moro format
|
82
|
+
input_files.each do |input_file|
|
83
|
+
unless File.exist?(input_file)
|
84
|
+
puts "error: '#{input_file}' file not found"
|
85
|
+
next
|
86
|
+
end
|
87
|
+
|
88
|
+
output_file = opts[:output] || output_filename(input_file)
|
89
|
+
if output_file == input_file
|
90
|
+
puts "error: input file '#{input_file}' would overwrite itself, skipping"
|
91
|
+
next
|
92
|
+
end
|
93
|
+
|
94
|
+
jpeg = JPEG2moro.new(input_file)
|
95
|
+
jpeg.save(output_file, output_opts)
|
96
|
+
|
97
|
+
if opts[:verbose]
|
98
|
+
puts "%s -> %s" % [File.basename(input_file), File.basename(output_file)]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
data/lib/jpeg2moro.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'zlib'
|
4
|
+
gem 'rmagick'
|
5
|
+
require 'RMagick'
|
6
|
+
include Magick
|
7
|
+
|
8
|
+
class JPEG2moro
|
9
|
+
DEBUG = 1
|
10
|
+
VERSION = "0.0.1"
|
11
|
+
|
12
|
+
DEFAULT_ALPHA_DEPTH = 8
|
13
|
+
DEFAULT_QUALITY = 70
|
14
|
+
|
15
|
+
class << self
|
16
|
+
attr_accessor :debug
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(options = {})
|
20
|
+
if options.kind_of?(Hash)
|
21
|
+
@file = options[:file]
|
22
|
+
@data = options[:data]
|
23
|
+
else
|
24
|
+
@file = options
|
25
|
+
end
|
26
|
+
|
27
|
+
@data = File.read(@file) if @file
|
28
|
+
debug "read %d bytes" % [@data.length]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.with_data(data)
|
32
|
+
return JPEG2moro.new(:data => data)
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
@data
|
37
|
+
end
|
38
|
+
|
39
|
+
# save output_file with the given options
|
40
|
+
def save(output_file, options = {})
|
41
|
+
output = convert(options)
|
42
|
+
File.open(output_file, "w") { |f| f.print output }
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# convert data to jpeg2moro format
|
48
|
+
def convert(options = {})
|
49
|
+
@convert_options = options.clone
|
50
|
+
@convert_options[:alpha_depth] ||= DEFAULT_ALPHA_DEPTH
|
51
|
+
|
52
|
+
# convert image data to jpg format
|
53
|
+
img = Image.from_blob(@data).first
|
54
|
+
jpeg_data = img.to_blob { |i|
|
55
|
+
i.quality = (options[:quality] || DEFAULT_QUALITY).to_i
|
56
|
+
i.format = 'jpg'
|
57
|
+
}
|
58
|
+
# insert alpha channel into jpeg data
|
59
|
+
insert_opacity_header(jpeg_data)
|
60
|
+
|
61
|
+
# return jpeg2moro object (contains alpha channel)
|
62
|
+
return JPEG2moro.new(:data => jpeg_data)
|
63
|
+
end
|
64
|
+
|
65
|
+
def debug(msg)
|
66
|
+
puts msg if self.class.debug
|
67
|
+
end
|
68
|
+
|
69
|
+
def debug_dump(data, filename)
|
70
|
+
if self.class.debug
|
71
|
+
File.open(filename, "w") { |f| f.print data }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def standalone_marker(marker)
|
76
|
+
(marker >= 0xd0 && marker <= 0xd7) || # RST
|
77
|
+
marker == 0xd8 || marker == 0xd9 || # SOI/EOI
|
78
|
+
marker == 0x01 # TEM
|
79
|
+
end
|
80
|
+
|
81
|
+
# find position to insert opacity information
|
82
|
+
# (just before SOS or EOI marker)
|
83
|
+
def insert_position(jpeg_data)
|
84
|
+
# parse jpeg data
|
85
|
+
data = jpeg_data
|
86
|
+
pos = 0
|
87
|
+
while pos < data.length
|
88
|
+
marker1 = data[pos]
|
89
|
+
marker2 = data[pos + 1]
|
90
|
+
|
91
|
+
return -1 if marker1 != 0xff # parse error
|
92
|
+
if marker2 == 0xff
|
93
|
+
# packed marker
|
94
|
+
pos += 1
|
95
|
+
next
|
96
|
+
end
|
97
|
+
|
98
|
+
if marker2 == 0xda || marker2 == 0xd9
|
99
|
+
# SOS (start of scan) or EOI (end of image)
|
100
|
+
# insert before this marker
|
101
|
+
debug "found insert position: %d (marker %x)" % [pos, marker2]
|
102
|
+
return pos
|
103
|
+
end
|
104
|
+
|
105
|
+
pos += 2
|
106
|
+
next if standalone_marker(marker2)
|
107
|
+
|
108
|
+
mlength = data[pos, 2].unpack('C2').reverse.pack('C2').unpack('S').first
|
109
|
+
pos += mlength
|
110
|
+
|
111
|
+
debug "marker: %x, length: %d" % [marker2, mlength]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# create a 'chunk' named name, with the given data.
|
116
|
+
# (4 bytes) Length
|
117
|
+
# (4 bytes) Chunk type (e.g. "ALPH" for alpha channel)
|
118
|
+
# (length bytes) Chunk data
|
119
|
+
def chunk(name, data)
|
120
|
+
raise "chunk name must be four characters long" unless name.length == 4
|
121
|
+
[data.length].pack("N") + name + data # TODO: not sure if this is unsigned
|
122
|
+
end
|
123
|
+
|
124
|
+
# create one or more app10 application segments containing the given data.
|
125
|
+
# if data exceeds the maximum length of the app segment, it is split into multiple
|
126
|
+
# segments. returns array of app10 segments.
|
127
|
+
# (2 bytes) APP10 marker (0xFFE9)
|
128
|
+
# (2 bytes) Length of segment (including 2 byte length parameter)
|
129
|
+
# (length - 2 bytes) Chunk data
|
130
|
+
def app10_segments(data)
|
131
|
+
i = 0
|
132
|
+
len = data.length
|
133
|
+
ret = []
|
134
|
+
while i < len
|
135
|
+
seglen = len - i > 65535 ? 65535 : len - i
|
136
|
+
segdata = data[i, seglen]
|
137
|
+
debug "segment data length: " + segdata.length.to_s
|
138
|
+
|
139
|
+
mlength = segdata.length + 2
|
140
|
+
header = [0xff, 0xe9].pack("C*") # APP10 marker
|
141
|
+
header += [mlength].pack("S").unpack("C*").reverse.pack("C*")
|
142
|
+
header += segdata
|
143
|
+
ret.push header
|
144
|
+
i += seglen
|
145
|
+
end
|
146
|
+
ret
|
147
|
+
end
|
148
|
+
|
149
|
+
# create opacity header
|
150
|
+
def create_opacity_header
|
151
|
+
img = Image.from_blob(@data).first # original image data
|
152
|
+
bit_depth = @convert_options[:alpha_depth]
|
153
|
+
bit_depth = bit_depth.to_i
|
154
|
+
|
155
|
+
unless [1,8,16].include?(bit_depth)
|
156
|
+
raise "unsupported alpha bit depth: " + @convert_options[:alpha_depth].to_s
|
157
|
+
end
|
158
|
+
|
159
|
+
debug "using bit depth: %d" % [bit_depth]
|
160
|
+
|
161
|
+
img.set_channel_depth(AlphaChannel, bit_depth)
|
162
|
+
alpha = img.separate(OpacityChannel)
|
163
|
+
#alpha.set_channel_depth(DefaultChannels, 1)
|
164
|
+
#alpha.display
|
165
|
+
storage = bit_depth == 16 ? ShortPixel : CharPixel
|
166
|
+
data = alpha.export_pixels_to_str(0, 0, alpha.columns, alpha.rows,
|
167
|
+
"A", storage)
|
168
|
+
|
169
|
+
debug_dump(alpha.to_blob, "alpha.png")
|
170
|
+
|
171
|
+
if bit_depth == 1
|
172
|
+
# pack into bit string
|
173
|
+
data = data.unpack('C*').map { |i| i == 0xff ? 1 : 0 }.join
|
174
|
+
data = [data].pack("B*")
|
175
|
+
end
|
176
|
+
|
177
|
+
debug_dump(data, "pixel.dat")
|
178
|
+
|
179
|
+
deflated = Zlib::Deflate.deflate(data, 9)
|
180
|
+
#deflated = deflated[2..-5] # strip header/footer?
|
181
|
+
debug "deflated size: %d bytes" % [deflated.length]
|
182
|
+
|
183
|
+
debug_dump(deflated, "compressed.dat")
|
184
|
+
|
185
|
+
# create alpha chunk, pack into app10 segment(s)
|
186
|
+
alpha_data = [bit_depth].pack("C") + deflated
|
187
|
+
alpha_chunk = chunk("ALPH", alpha_data)
|
188
|
+
segments = app10_segments(alpha_chunk)
|
189
|
+
header = segments.join
|
190
|
+
|
191
|
+
debug_dump(header, "header.dat")
|
192
|
+
|
193
|
+
header
|
194
|
+
end
|
195
|
+
|
196
|
+
def insert_opacity_header(jpeg_data)
|
197
|
+
offset = insert_position(jpeg_data)
|
198
|
+
header = create_opacity_header
|
199
|
+
jpeg_data.insert(offset, header)
|
200
|
+
end
|
201
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/jpeg2moro.rb'}"
|
9
|
+
puts "Loading jpeg2moro gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
3
|
+
require 'rspec'
|
4
|
+
rescue LoadError
|
5
|
+
puts <<-EOS
|
6
|
+
To use rspec for testing you must install rspec gem:
|
7
|
+
gem install rspec
|
8
|
+
EOS
|
9
|
+
exit(0)
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run the specs under spec/models"
|
13
|
+
RSpec::Core::RakeTask.new do |t|
|
14
|
+
# t.rspec_opts = ['--options', "spec/spec.opts"]
|
15
|
+
t.pattern = 'spec/**/*_spec.rb'
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jpeg2moro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- 2moro mobile
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-23 00:00:00 +10:30
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rmagick
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 57
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 13
|
33
|
+
- 1
|
34
|
+
version: 2.13.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rubyforge
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 7
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
49
|
+
- 4
|
50
|
+
version: 2.0.4
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: hoe
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 19
|
62
|
+
segments:
|
63
|
+
- 2
|
64
|
+
- 7
|
65
|
+
- 0
|
66
|
+
version: 2.7.0
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
69
|
+
description: JPEG2moro is a method of encoding arbitrary data (including an alpha channel) within the JPEG Application Segment APP10.
|
70
|
+
email:
|
71
|
+
- support@2moro.com.au
|
72
|
+
executables:
|
73
|
+
- jpeg2moro
|
74
|
+
extensions: []
|
75
|
+
|
76
|
+
extra_rdoc_files:
|
77
|
+
- History.txt
|
78
|
+
- Manifest.txt
|
79
|
+
files:
|
80
|
+
- History.txt
|
81
|
+
- Manifest.txt
|
82
|
+
- README.rdoc
|
83
|
+
- Rakefile
|
84
|
+
- bin/jpeg2moro
|
85
|
+
- lib/jpeg2moro.rb
|
86
|
+
- script/console
|
87
|
+
- script/destroy
|
88
|
+
- script/generate
|
89
|
+
- spec/jpeg2moro_spec.rb
|
90
|
+
- spec/spec.opts
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
- tasks/rspec.rake
|
93
|
+
has_rdoc: true
|
94
|
+
homepage: http://github.com/2moro/jpeg2moro
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options:
|
99
|
+
- --main
|
100
|
+
- README.rdoc
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
hash: 3
|
109
|
+
segments:
|
110
|
+
- 0
|
111
|
+
version: "0"
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
requirements: []
|
122
|
+
|
123
|
+
rubyforge_project: jpeg2moro
|
124
|
+
rubygems_version: 1.3.7
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: JPEG2moro is a method of encoding arbitrary data (including an alpha channel) within the JPEG Application Segment APP10.
|
128
|
+
test_files: []
|
129
|
+
|