hydra-derivatives 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0212a791210218d33a99934df59e57d60ad44258
4
- data.tar.gz: 5cbe5a947d8709a75a958380ac7495c6fd84eb5f
3
+ metadata.gz: 1bc8abf9416fda90a423323e7717b6ff5b889f70
4
+ data.tar.gz: db345a163681b8b2d981f5f4aad33e868951d03c
5
5
  SHA512:
6
- metadata.gz: 9b340d1a70f8be41222ea8be383cf9f25085c30b7df20b6898176f229f2096bee2cfd55803e4d80a2eeb6b4e43b0b05cc49a3691bb6b163a314276345f703c83
7
- data.tar.gz: de99c7a8c27dcc00bde2b165536e87d2b960d1936dfafb35e13460dfd50a46cdcf2374d1a18c9b31aab10159b2c7ba1951df619f453063de594aaf2d781be043
6
+ metadata.gz: 57b97d9fbd4b63233ae73d58da47546f2c466a78de5bea3ef687f818cf3d493d17ed4c128f8a0c312f3a872d17bf0771a754479fbac1ddcdb359f5f02ef6f81f
7
+ data.tar.gz: 30f51ea9f6b6fc4be16631b89d46c090a7ee26e96b46a2d0f70c3e76f71eedcf890d0940db488413082e6446d5b059bd71a54e6fefc3cf8b37274f13cc49fbd0
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ Gemfile.lock
2
2
  tmp/
3
3
  jetty/
4
4
  pkg/
5
+ .bundle/
data/History.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 0.0.8 (2013-04-09)
2
+ - Add support for JPEG2000 Derivatives
3
+ - Correcting Railtie initializer
4
+ - Added ImageMagick dependency
5
+ - Updated FITS URL
6
+ - Adding input and output options to ffmpeg and video processor
7
+ - Revert "Switch to streamio_ffmpeg for easier handling of ffmpeg arguments"
8
+ - Switch to streamio_ffmpeg for easier handling of ffmpeg arguments
9
+ - Adding Railtie for initialization
10
+
11
+ ## 0.0.7 (2013-10-11)
12
+ - Restore `Hydra::Derivatives::ExtractMetadata#to_tempfile`
13
+
14
+ ## 0.0.6 (2013-10-10)
15
+ - Added version badge
16
+ - Adding Hydra::FileCharacterization
17
+ - Updating CONTRIBUTING.md as per Hydra v6.0.0
18
+ - Adding microsoft openxmlformats as output formats
19
+ - Adding rewind to allow image data to be extracted properly
20
+ - Replacing rmagick with mini_magick
21
+ - Refactoring extraction to implicitly close
22
+ - Changes audio encoding to libfdk_aac for video derivatives
23
+
1
24
  ## 0.0.5 (2013-07-25)
2
25
  - Allow images to change format without being resize [Justin Coyne]
3
26
 
data/README.md CHANGED
@@ -1,6 +1,4 @@
1
- hydra-derivatives
2
- =================
3
- [![Gem Version](https://badge.fury.io/rb/hydra-derivatives.png)](http://badge.fury.io/rb/hydra-derivatives)
1
+ # hydra-derivatives [![Version](https://badge.fury.io/rb/hydra-derivatives.png)](http://badge.fury.io/rb/hydra-derivatives) [![Build Status](https://travis-ci.org/projecthydra/hydra-derivatives.png?branch=master)](https://travis-ci.org/projecthydra/hydra-derivatives) [![Dependency Status](https://gemnasium.com/projecthydra/hydra-derivatives.png)](https://gemnasium.com/projecthydra/hydra-derivatives)
4
2
 
5
3
  Derivative generation for hydra
6
4
 
@@ -23,6 +21,8 @@ If you have an ActiveFedora class like this:
23
21
  obj.transform_datastream :content, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'} }, processor: :video
24
22
  when 'image/png', 'image/jpg'
25
23
  obj.transform_datastream :content, { :medium => "300x300>", :thumb => "100x100>" }
24
+ when 'image/tiff'
25
+ obj.transform_datastream :content, { :service => { resize: "3600x3600>" } }, processor: 'jpeg2k_image'
26
26
  end
27
27
  end
28
28
  end
@@ -48,8 +48,10 @@ Or a class like this:
48
48
  transform_datastream :content, { :mp3 => {format: 'mp3'}, :ogg => {format: 'ogg'} }, processor: :audio
49
49
  when 'video/avi'
50
50
  transform_datastream :content, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'} }, processor: :video
51
- when 'image/png', 'image/jpg', 'image/tiff'
51
+ when 'image/png', 'image/jpg'
52
52
  transform_datastream :content, { :medium => "300x300>", :thumb => {size: "100x100>", datastream: 'thumbnail'} }
53
+ when 'image/tiff'
54
+ transform_datastream :content, { :service => { recipe: :default } }, processor: 'jpeg2k_image'
53
55
  end
54
56
  end
55
57
  end
@@ -60,7 +62,7 @@ And you add some content to it:
60
62
  ```ruby
61
63
  obj = GenericFile.new
62
64
  obj.content.content = File.open(...)
63
- obj.mime_type = 'image/tiff'
65
+ obj.mime_type = 'image/jpg'
64
66
  obj.save
65
67
  ```
66
68
 
@@ -74,11 +76,15 @@ Just add `gem 'hydra-derivatives'` to your Gemfile.
74
76
 
75
77
  ## Dependencies
76
78
 
77
- * [Fits](https://code.google.com/p/fits/)
79
+ * [FITS](http://fitstool.org/)
78
80
  * [FFMpeg](http://www.ffmpeg.org/)
79
81
  * [LibreOffice](https://www.libreoffice.org/)
82
+ * [ImageMagick](http://www.imagemagick.org/)
83
+ * Kakadu's [kdu_compress](http://www.kakadusoftware.com/)
84
+
85
+ To enable LibreOffice, FFMpeg, ImageMagick, FITS support, and kdu_compress support, make sure they are on your path. Most people will put that in their .bash_profile or somewhere similar.
80
86
 
81
- To enable LibreOffice, FFMpeg and Fits.sh support, you make sure they are on your path. Most people will put that in their .bash_profile or somewhere similar. For example:
87
+ For example:
82
88
 
83
89
  ```bash
84
90
  # in .bash_profile
@@ -90,5 +96,23 @@ Alternatively, you can configure their paths:
90
96
  Hydra::Derivatives.ffmpeg_path = '/opt/local/ffmpeg/bin/ffmpeg'
91
97
  Hydra::Derivatives.fits_path = '/opt/local/fits/bin/fits.sh'
92
98
  Hydra::Derivatives.libreoffice_path = '/opt/local/libreoffice_path/bin/soffice'
93
-
99
+ Hydra::Derivatives.kdu_compress_path = '/usr/local/bin/kdu_compress'
94
100
  ```
101
+
102
+ ## JPEG2k Directives
103
+
104
+ Unlike the other processors, the `Jpeg2kImage` processor does not generally accept arguments that directly (or nearly so) translate to the arguments you would give to the corresponding command line utility.
105
+
106
+ Instead, each directive may contain these arguments:
107
+
108
+ * `:datastream` (String) : The name for the new datastream
109
+ * `:to_srgb` (Boolean) : If `true` and the image is a color image it will map the source image color profile to sRGB. Default: `true`
110
+ * `:resize` (String) : Geometry; the same syntax as the `Hydra::Derivatives::Image` processor
111
+ * `:recipe` :
112
+ - If a Symbol the recipe will be read from the `Hydra::Derivatives.kdu_compress_recipes` hash. You can override this, or a couple of samples are supplied. The symbol in the config file should be the name in the model + `_{quality}`, e.g. `recipe: :default` will look `:default_color` or `:default_grey` in the hash.
113
+ - If a String the recipe in the string will be used. You may include anything the command line utility will accept except `-i` or `-o`. See `$ kdu_compress -usage` in your shell.
114
+ - If no `:recipe` is provided the processor will examine the image and make a best guess, but you can set a few basic options (the remainder of this list). Note that these are ignored if you provided a recipe via either of the first two methods described.
115
+ * `:levels` (Integer) : The number of decomposition levels. The default is the number of times the long dimension can be divided by two, down to 96, e.g. a 7200 pixel image would have 6 levels (3600, 1800, 900, 450, 225, 112)
116
+ * `:layers` (Integer) : The number of quality layers. Default: 8
117
+ * `:compression` (Integer) : The left number of the compression ratio `n:1`, e.g. 12 will apply 12:1 compression. Default: 10.
118
+ * `:tile_size` (Integer) : Pixel dimension of the tiles. Default: 1024
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.0.8
@@ -0,0 +1,7 @@
1
+ Terms of use (from http://www.color.org/srgbprofiles.xalter#v2)
2
+
3
+ To anyone who acknowledges that the files "sRGB_IEC61966-2-1_no_black_scaling.icc" and "sRGB_IEC61966-2-1_black scaled.icc"
4
+ are provided "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTY, permission to use, copy and distribute these file for any purpose
5
+ is hereby granted without fee, provided that the files are not changed including the ICC copyright notice tag, and that the
6
+ name of ICC shall not be used in advertising or publicity pertaining to distribution of the software without specific,
7
+ written prior permission. ICC makes no representations about the suitability of this software for any purpose.
@@ -1,4 +1,6 @@
1
1
  require 'active_fedora'
2
+ require 'hydra/derivatives/railtie' if defined?(Rails)
3
+
2
4
  module Hydra
3
5
  module Derivatives
4
6
  extend ActiveSupport::Concern
@@ -13,6 +15,7 @@ module Hydra
13
15
  autoload :Document
14
16
  autoload :ExtractMetadata
15
17
  autoload :ShellBasedProcessor
18
+ autoload :Jpeg2kImage
16
19
 
17
20
  def self.config
18
21
  @config ||= reset_config!
@@ -22,7 +25,9 @@ module Hydra
22
25
  @config = Config.new
23
26
  end
24
27
 
25
- [:ffmpeg_path, :libreoffice_path, :temp_file_base, :fits_path, :enable_ffmpeg].each do |method|
28
+
29
+ [:ffmpeg_path, :libreoffice_path, :temp_file_base, :fits_path, :kdu_compress_path,
30
+ :kdu_compress_recipes, :enable_ffmpeg].each do |method|
26
31
  module_eval <<-RUBY
27
32
  def self.#{method.to_s}
28
33
  config.#{method.to_s}
@@ -1,7 +1,8 @@
1
1
  module Hydra
2
2
  module Derivatives
3
3
  class Config
4
- attr_writer :ffmpeg_path, :libreoffice_path, :temp_file_base, :fits_path, :enable_ffmpeg
4
+ attr_writer :ffmpeg_path, :libreoffice_path, :temp_file_base, :fits_path,
5
+ :enable_ffmpeg, :kdu_compress_path, :kdu_compress_recipes
5
6
  def ffmpeg_path
6
7
  @ffmpeg_path ||= 'ffmpeg'
7
8
  end
@@ -22,6 +23,43 @@ module Hydra
22
23
  @enable_ffmpeg ||= true
23
24
  end
24
25
 
26
+ def kdu_compress_path
27
+ @kdu_compress_path ||= 'kdu_compress'
28
+ end
29
+
30
+ def kdu_compress_recipes
31
+ @kdu_compress_recipes ||= {
32
+ default_color: %Q{-rate 2.4,1.48331273,.91673033,.56657224,.35016049,.21641118,.13374944,.08266171
33
+ -jp2_space sRGB
34
+ -double_buffering 10
35
+ -num_threads 4
36
+ -no_weights
37
+ Clevels=6
38
+ Clayers=8
39
+ Cblk=\{64,64\}
40
+ Cuse_sop=yes
41
+ Cuse_eph=yes
42
+ Corder=RPCL
43
+ ORGgen_plt=yes
44
+ ORGtparts=R
45
+ Stiles=\{1024,1024\} }.gsub(/\s+/, " ").strip,
46
+ default_grey: %Q{-rate 2.4,1.48331273,.91673033,.56657224,.35016049,.21641118,.13374944,.08266171
47
+ -jp2_space sLUM
48
+ -double_buffering 10
49
+ -num_threads 4
50
+ -no_weights
51
+ Clevels=6
52
+ Clayers=8
53
+ Cblk=\{64,64\}
54
+ Cuse_sop=yes
55
+ Cuse_eph=yes
56
+ Corder=RPCL
57
+ ORGgen_plt=yes
58
+ ORGtparts=R
59
+ Stiles=\{1024,1024\} }.gsub(/\s+/, " ").strip
60
+ }
61
+ end
62
+
25
63
  end
26
64
  end
27
65
  end
@@ -37,4 +37,4 @@ module Hydra
37
37
 
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -8,6 +8,9 @@ module Hydra
8
8
  module Ffmpeg
9
9
  extend ActiveSupport::Concern
10
10
 
11
+ INPUT_OPTIONS=:input_options
12
+ OUTPUT_OPTIONS=:output_options
13
+
11
14
  included do
12
15
  include ShellBasedProcessor
13
16
  end
@@ -16,7 +19,11 @@ module Hydra
16
19
  module ClassMethods
17
20
 
18
21
  def encode(path, options, output_file)
19
- execute "#{Hydra::Derivatives.ffmpeg_path} -y -i \"#{path}\" #{options} #{output_file}"
22
+ inopts = options[INPUT_OPTIONS] if options
23
+ inopts ||= "-y"
24
+ outopts = options[OUTPUT_OPTIONS] if options
25
+ outopts ||= options
26
+ execute "#{Hydra::Derivatives.ffmpeg_path} #{inopts} -i \"#{path}\" #{outopts} #{output_file}"
20
27
  end
21
28
  end
22
29
 
@@ -0,0 +1,20 @@
1
+ defaults: &defaults
2
+ jp2_recipes:
3
+ # note that these aren't real recipes, just enough to test configuration options
4
+ myrecipe_color: >
5
+ -rate 2.4
6
+ -jp2_space sRGB
7
+ Stiles=\{1024,1024\}
8
+ myrecipe_grey: >
9
+ -rate 2.4
10
+ -jp2_space sLUM
11
+ Stiles=\{1024,1024\}
12
+
13
+ development:
14
+ <<: *defaults
15
+
16
+ test:
17
+ <<: *defaults
18
+
19
+ production:
20
+ <<: *defaults
@@ -0,0 +1,147 @@
1
+ require 'mini_magick'
2
+ require 'nokogiri'
3
+
4
+
5
+ module Hydra
6
+ module Derivatives
7
+ class Jpeg2kImage < Processor
8
+ include ShellBasedProcessor
9
+
10
+ def process
11
+ quality, colorspace = extract_quality_and_colorspace
12
+ directives.each do |name, args|
13
+ file_path = nil
14
+ long_dim = nil
15
+ to_srgb = args.fetch(:to_srgb, true)
16
+ if args[:resize] || to_srgb
17
+ image = preprocess(resize: args[:resize], to_srgb: to_srgb, src_quality: quality)
18
+ long_dim = self.class.long_dim(image)
19
+ file_path = self.class.tmp_file('.tif')
20
+ image.write file_path
21
+ else
22
+ long_dim = self.class.long_dim(MiniMagick::Image.read(source_datastream.content))
23
+ end
24
+ recipe = self.class.kdu_compress_recipe(args, quality, long_dim)
25
+ output_datastream_name = args[:datastream] || output_datastream_id(name)
26
+ encode_datastream(output_datastream_name, recipe, file_path: file_path)
27
+ File.unlink(file_path) unless file_path.nil?
28
+ end
29
+ end
30
+
31
+ def encode_datastream(dest_dsid, recipe, opts={})
32
+ output_file = self.class.tmp_file('.jp2')
33
+ if opts[:file_path]
34
+ self.class.encode(opts[:file_path], recipe, output_file)
35
+ else
36
+ source_datastream.to_tempfile do |f|
37
+ self.class.encode(f.path, recipe, output_file)
38
+ end
39
+ end
40
+ out_file = File.open(output_file, "rb")
41
+ object.add_file_datastream(out_file.read, dsid: dest_dsid, mimeType: 'image/jp2')
42
+ File.unlink(output_file)
43
+ end
44
+
45
+ protected
46
+ def preprocess(opts={})
47
+ # resize: <geometry>, to_srgb: <bool>,src_quality: 'color'|'grey'
48
+ image = MiniMagick::Image.read(source_datastream.content)
49
+ image.combine_options do |c|
50
+ c.resize(opts[:resize]) if opts[:resize]
51
+ c.profile self.class.srgb_profile_path if opts[:src_quality] == 'color' && opts[:to_srgb]
52
+ end
53
+ image
54
+ end
55
+
56
+ def extract_quality_and_colorspace
57
+ xml = source_datastream.extract_metadata
58
+ doc = Nokogiri::XML(xml).remove_namespaces!
59
+ bps = doc.xpath('//bitsPerSample').first.content
60
+ quality = bps == '8 8 8' ? 'color' : 'grey'
61
+ colorspace = doc.xpath('.//colorSpace').first.content
62
+ [quality, colorspace]
63
+ end
64
+
65
+ def self.encode(path, recipe, output_file)
66
+ kdu_compress = Hydra::Derivatives.kdu_compress_path
67
+ execute "#{kdu_compress} -i #{path} -o #{output_file} #{recipe}"
68
+ end
69
+
70
+ def self.srgb_profile_path
71
+ File.join [
72
+ File.expand_path('../../../', __FILE__),
73
+ 'color_profiles',
74
+ 'sRGB_IEC61966-2-1_no_black_scaling.icc'
75
+ ]
76
+ end
77
+
78
+ def self.tmp_file(ext)
79
+ Dir::Tmpname.create(['sufia', ext], Hydra::Derivatives.temp_file_base){}
80
+ end
81
+
82
+ def self.long_dim(image)
83
+ [image[:width], image[:height]].max
84
+ end
85
+
86
+ def self.kdu_compress_recipe(args, quality, long_dim)
87
+ if args[:recipe].is_a? Symbol
88
+ recipe = [args[:recipe].to_s, quality].join('_')
89
+ if Hydra::Derivatives.kdu_compress_recipes.has_key? recipe
90
+ return Hydra::Derivatives.kdu_compress_recipes[recipe]
91
+ else
92
+ logger.warn "No JP2 recipe for :#{args[:recipe].to_s} ('#{recipe}') found in configuration. Using best guess."
93
+ return Hydra::Derivatives::Jpeg2kImage.calculate_recipe(args,quality,long_dim)
94
+ end
95
+ elsif args[:recipe].is_a? String
96
+ return args[:recipe]
97
+ else
98
+ return Hydra::Derivatives::Jpeg2kImage.calculate_recipe(args, quality, long_dim)
99
+ end
100
+ end
101
+
102
+ def self.calculate_recipe(args, quality, long_dim)
103
+ levels_arg = args.fetch(:levels, Hydra::Derivatives::Jpeg2kImage.level_count_for_size(long_dim))
104
+ rates_arg = Hydra::Derivatives::Jpeg2kImage.layer_rates(args.fetch(:layers, 8), args.fetch(:compression, 10))
105
+ tile_size = args.fetch(:tile_size, 1024)
106
+ tiles_arg = "\{#{tile_size},#{tile_size}\}"
107
+ jp2_space_arg = quality == 'grey' ? 'sLUM' : 'sRGB'
108
+
109
+ %Q{-rate #{rates_arg}
110
+ -jp2_space #{jp2_space_arg}
111
+ -double_buffering 10
112
+ -num_threads 4
113
+ -no_weights
114
+ Clevels=#{levels_arg}
115
+ Stiles=#{tiles_arg}
116
+ Cblk=\{64,64\}
117
+ Cuse_sop=yes
118
+ Cuse_eph=yes
119
+ Corder=RPCL
120
+ ORGgen_plt=yes
121
+ ORGtparts=R }.gsub(/\s+/, " ").strip
122
+ end
123
+
124
+ def self.level_count_for_size(long_dim)
125
+ levels = 0
126
+ level_size = long_dim
127
+ while level_size >= 96
128
+ level_size = level_size/2
129
+ levels+=1
130
+ end
131
+ levels-1
132
+ end
133
+
134
+ def self.layer_rates(layer_count,compression_numerator)
135
+ #e.g. if compression_numerator = 10 then compression is 10:1
136
+ rates = []
137
+ cmp = 24.0/compression_numerator
138
+ layer_count.times do
139
+ rates << cmp
140
+ cmp = (cmp/1.618).round(8)
141
+ end
142
+ rates.map(&:to_s ).join(',')
143
+ end
144
+
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,7 @@
1
+ module Hydra::Derivative
2
+ class Railtie < Rails::Railtie
3
+ initializer 'hydra-derivative' do
4
+ require 'hydra-file_characterization'
5
+ end
6
+ end
7
+ end
@@ -6,7 +6,17 @@ module Hydra
6
6
  protected
7
7
 
8
8
  def options_for(format)
9
- "-s #{size_attributes} #{video_attributes} #{codecs(format)} #{audio_attributes}"
9
+ input_options=""
10
+ output_options = "-s #{size_attributes} #{codecs(format)}"
11
+
12
+ if (format == "jpg")
13
+ input_options +=" -itsoffset -2"
14
+ output_options+= " -vframes 1 -an -f rawvideo"
15
+ else
16
+ output_options +=" #{video_attributes} #{audio_attributes}"
17
+ end
18
+
19
+ { Ffmpeg::OUTPUT_OPTIONS => output_options, Ffmpeg::INPUT_OPTIONS => input_options}
10
20
  end
11
21
 
12
22
  def video_bitrate
@@ -30,14 +40,18 @@ module Hydra
30
40
  when 'mp4'
31
41
  "-vcodec libx264 -acodec libfdk_aac"
32
42
  when 'webm'
33
- "-acodec libvorbis"
43
+ "-vcodec libvpx -acodec libvorbis"
44
+ when "mkv"
45
+ "-vcodec ffv1"
46
+ when "jpg"
47
+ "-vcodec mjpeg"
34
48
  else
35
49
  raise ArgumentError, "Unknown format `#{format}'"
36
50
  end
37
51
  end
38
52
 
39
53
  def new_mime_type(format)
40
- "video/#{format}"
54
+ format == "jpg" ? "image/jpeg" : "video/#{format}"
41
55
  end
42
56
  end
43
57
  end
Binary file
@@ -0,0 +1,20 @@
1
+ defaults: &defaults
2
+ jp2_recipes:
3
+ # note that these aren't real recipes, just enough to test configuration options
4
+ myrecipe_color: >
5
+ -rate 2.4
6
+ -jp2_space sRGB
7
+ Stiles=\{1024,1024\}
8
+ myrecipe_grey: >
9
+ -rate 2.4
10
+ -jp2_space sLUM
11
+ Stiles=\{1024,1024\}
12
+
13
+ development:
14
+ <<: *defaults
15
+
16
+ test:
17
+ <<: *defaults
18
+
19
+ production:
20
+ <<: *defaults
Binary file
@@ -9,17 +9,26 @@ describe "the configuration" do
9
9
  subject.libreoffice_path.should == 'soffice'
10
10
  subject.temp_file_base.should == '/tmp'
11
11
  subject.fits_path.should == 'fits.sh'
12
+ subject.kdu_compress_path.should == 'kdu_compress'
12
13
  end
13
14
 
14
15
  it "should let you change the configuration" do
15
16
  subject.ffmpeg_path = '/usr/local/ffmpeg-1.0/bin/ffmpeg'
16
17
  subject.ffmpeg_path.should == '/usr/local/ffmpeg-1.0/bin/ffmpeg'
18
+
19
+ subject.kdu_compress_path = '/opt/local/bin/kdu_compress'
20
+ subject.kdu_compress_path.should == '/opt/local/bin/kdu_compress'
21
+
17
22
  end
18
23
 
19
24
  it "should let you reset the configuration" do
20
25
  subject.ffmpeg_path = '/usr/local/ffmpeg-1.0/bin/ffmpeg'
21
26
  subject.reset_config!
22
27
  subject.ffmpeg_path.should == 'ffmpeg'
28
+
29
+ subject.kdu_compress_path = '/usr/local/bin/kdu_compress'
30
+ subject.reset_config!
31
+ subject.kdu_compress_path.should == 'kdu_compress'
23
32
  end
24
33
 
25
34
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+
4
+ describe Hydra::Derivatives::Jpeg2kImage do
5
+ let(:object) { ActiveFedora::Base.new }
6
+
7
+ describe "#calculate_recipe" do
8
+ it "calculates the number of levels from a size" do
9
+ dim = 7200
10
+ Hydra::Derivatives::Jpeg2kImage.level_count_for_size(dim).should == 6
11
+ end
12
+
13
+ it "calculates the compression rates for each quality layer" do
14
+ compression_num = 10
15
+ layers = 8
16
+ calc = Hydra::Derivatives::Jpeg2kImage.layer_rates(layers, compression_num)
17
+ calc.should == "2.4,1.48331273,0.91675694,0.56659885,0.3501847,0.21643059,0.13376427,0.0826726"
18
+ end
19
+
20
+ end
21
+
22
+ describe "#kdu_compress_recipe" do
23
+ before(:all) do
24
+ @sample_cfg = YAML.load_file(File.expand_path('../../fixtures/jpeg2k_config.yml', __FILE__))['test']
25
+ Hydra::Derivatives.kdu_compress_recipes = @sample_cfg['jp2_recipes']
26
+ end
27
+
28
+ it "can get the recipe from a config file" do
29
+ args = { recipe: :myrecipe }
30
+ r = Hydra::Derivatives::Jpeg2kImage.kdu_compress_recipe(args, 'grey', 7200)
31
+ r.should == @sample_cfg['jp2_recipes']['myrecipe_grey']
32
+ end
33
+
34
+ it "can take a recipe as a string" do
35
+ args = { recipe: '-my -excellent -recipe' }
36
+ r = Hydra::Derivatives::Jpeg2kImage.kdu_compress_recipe(args, 'grey', 7200)
37
+ r.should == args[:recipe]
38
+ end
39
+
40
+ it "will fall back to a #calculate_recipe if a symbol is passed but no recipe is found" do
41
+ args = { recipe: :x }
42
+ r = Hydra::Derivatives::Jpeg2kImage.kdu_compress_recipe(args, 'grey', 7200)
43
+ r.should == Hydra::Derivatives::Jpeg2kImage.calculate_recipe(args, 'grey', 7200)
44
+ end
45
+
46
+ it "will fall back to a #calculate_recipe if there is no attempt to provide one" do
47
+ args = {}
48
+ r = Hydra::Derivatives::Jpeg2kImage.kdu_compress_recipe(args, 'grey', 7200)
49
+ r.should == Hydra::Derivatives::Jpeg2kImage.calculate_recipe(args, 'grey', 7200)
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -11,7 +11,7 @@ describe "Transcoder" do
11
11
  m.field "mime_type", :string
12
12
  end
13
13
 
14
- delegate :mime_type, :to => :characterization, :unique => true
14
+ has_attributes :mime_type, datastream: :characterization, multiple: false
15
15
  has_file_datastream 'content', type: ContentDatastream
16
16
 
17
17
  makes_derivatives do |obj|
@@ -21,7 +21,8 @@ describe "Transcoder" do
21
21
  when 'audio/wav'
22
22
  obj.transform_datastream :content, { :mp3 => {format: 'mp3'}, :ogg => {format: 'ogg'} }, processor: :audio
23
23
  when 'video/avi'
24
- obj.transform_datastream :content, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'} }, processor: :video
24
+ obj.transform_datastream :content, { :mp4 => {format: 'mp4'}, :webm => {format: 'webm'},
25
+ :thumbnail=> {:format => 'jpg' , datastream: 'thumbnail'} }, processor: :video
25
26
  when 'image/png', 'image/jpg'
26
27
  obj.transform_datastream :content, { :medium => "300x300>", :thumb => "100x100>", :access => {format: 'jpg', datastream: 'access'} }
27
28
  when 'application/vnd.ms-powerpoint'
@@ -32,6 +33,14 @@ describe "Transcoder" do
32
33
  obj.transform_datastream :content, { :access => { :format=>'pdf' }, :preservation=> {:format => 'docx' } }, processor: 'document'
33
34
  when 'application/vnd.ms-excel'
34
35
  obj.transform_datastream :content, { :access => { :format=>'pdf' }, :preservation=> {:format => 'xslx' } }, processor: 'document'
36
+ when 'image/tiff'
37
+ obj.transform_datastream :content, {
38
+ resized: { recipe: :default, resize: "600x600>", datastream: 'resized' },
39
+ config_lookup: { recipe: :default, datastream: 'config_lookup' },
40
+ string_recipe: { recipe: '-quiet', datastream: 'string_recipe' },
41
+ diy: { }
42
+ }, processor: 'jpeg2k_image'
43
+
35
44
  end
36
45
 
37
46
  end
@@ -117,6 +126,8 @@ describe "Transcoder" do
117
126
  file.datastreams['content_mp4'].mimeType.should == 'video/mp4'
118
127
  file.datastreams['content_webm'].should have_content
119
128
  file.datastreams['content_webm'].mimeType.should == 'video/webm'
129
+ file.datastreams['thumbnail'].should have_content
130
+ file.datastreams['thumbnail'].mimeType.should == 'image/jpeg'
120
131
  end
121
132
  end
122
133
 
@@ -187,4 +198,21 @@ describe "Transcoder" do
187
198
  end
188
199
  end
189
200
 
201
+ describe "with an attached tiff", unless: ENV['TRAVIS'] == 'true' do
202
+
203
+ let(:attachment) { File.open(File.expand_path('../../fixtures/test.tif', __FILE__))}
204
+ let(:file) { GenericFile.new(mime_type: 'image/tiff').tap { |t| t.content.content = attachment; t.save } }
205
+ it "should transcode" do
206
+ file.create_derivatives
207
+ file.datastreams['content_diy'].should have_content
208
+ file.datastreams['content_diy'].mimeType.should == 'image/jp2'
209
+ file.datastreams['config_lookup'].should have_content
210
+ file.datastreams['config_lookup'].mimeType.should == 'image/jp2'
211
+ file.datastreams['resized'].should have_content
212
+ file.datastreams['resized'].mimeType.should == 'image/jp2'
213
+ file.datastreams['string_recipe'].should have_content
214
+ file.datastreams['string_recipe'].mimeType.should == 'image/jp2'
215
+ end
216
+ end
217
+
190
218
  end
@@ -6,7 +6,7 @@ describe Hydra::Derivatives::Video do
6
6
  let(:directives) {{ :thumb => {format: "webm", datastream: 'thumbnail'} }}
7
7
  subject { Hydra::Derivatives::Video.new(double(:obj), 'content', directives)}
8
8
  it "should create a datastream with the specified name" do
9
- subject.should_receive(:encode_datastream).with("thumbnail", "webm", 'video/webm', "-s 320x240 -g 30 -b:v 345k -acodec libvorbis -ac 2 -ab 96k -ar 44100")
9
+ subject.should_receive(:encode_datastream).with("thumbnail", "webm", 'video/webm', {Hydra::Derivatives::Ffmpeg::OUTPUT_OPTIONS =>"-s 320x240 -vcodec libvpx -acodec libvorbis -g 30 -b:v 345k -ac 2 -ab 96k -ar 44100", Hydra::Derivatives::Ffmpeg::INPUT_OPTIONS=>""})
10
10
  subject.process
11
11
 
12
12
  end
@@ -16,7 +16,17 @@ describe Hydra::Derivatives::Video do
16
16
  let(:directives) {{ :thumb => {format: "webm"} }}
17
17
  subject { Hydra::Derivatives::Video.new(double(:obj), 'content', directives)}
18
18
  it "should create a datastream and infer the name" do
19
- subject.should_receive(:encode_datastream).with("content_thumb", "webm", 'video/webm', "-s 320x240 -g 30 -b:v 345k -acodec libvorbis -ac 2 -ab 96k -ar 44100")
19
+ subject.should_receive(:encode_datastream).with("content_thumb", "webm", 'video/webm', {Hydra::Derivatives::Ffmpeg::OUTPUT_OPTIONS =>"-s 320x240 -vcodec libvpx -acodec libvorbis -g 30 -b:v 345k -ac 2 -ab 96k -ar 44100", Hydra::Derivatives::Ffmpeg::INPUT_OPTIONS=>""})
20
+ subject.process
21
+
22
+ end
23
+ end
24
+
25
+ describe "and jpg is requested" do
26
+ let(:directives) {{ :thumb => {:format => 'jpg' , datastream: 'thumbnail'} }}
27
+ subject { Hydra::Derivatives::Video.new(double(:obj), 'content', directives)}
28
+ it "should create a datastream and infer the name" do
29
+ subject.should_receive(:encode_datastream).with("thumbnail", "jpg", "image/jpeg", {:output_options=>"-s 320x240 -vcodec mjpeg -vframes 1 -an -f rawvideo", :input_options=>" -itsoffset -2"})
20
30
  subject.process
21
31
 
22
32
  end
metadata CHANGED
@@ -1,131 +1,131 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydra-derivatives
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-11 00:00:00.000000000 Z
11
+ date: 2014-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: jettywrapper
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: active-fedora
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: hydra-file_characterization
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: mini_magick
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: activesupport
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: 3.2.13
118
- - - <
118
+ - - "<"
119
119
  - !ruby/object:Gem::Version
120
120
  version: '5.0'
121
121
  type: :runtime
122
122
  prerelease: false
123
123
  version_requirements: !ruby/object:Gem::Requirement
124
124
  requirements:
125
- - - '>='
125
+ - - ">="
126
126
  - !ruby/object:Gem::Version
127
127
  version: 3.2.13
128
- - - <
128
+ - - "<"
129
129
  - !ruby/object:Gem::Version
130
130
  version: '5.0'
131
131
  description: Derivative generation plugin for hydra
@@ -135,9 +135,9 @@ executables: []
135
135
  extensions: []
136
136
  extra_rdoc_files: []
137
137
  files:
138
- - .gitignore
139
- - .rspec
140
- - .travis.yml
138
+ - ".gitignore"
139
+ - ".rspec"
140
+ - ".travis.yml"
141
141
  - CONTRIBUTING.md
142
142
  - Gemfile
143
143
  - History.md
@@ -148,6 +148,8 @@ files:
148
148
  - VERSION
149
149
  - config/jetty.yml
150
150
  - hydra-derivatives.gemspec
151
+ - lib/color_profiles/license.txt
152
+ - lib/color_profiles/sRGB_IEC61966-2-1_no_black_scaling.icc
151
153
  - lib/hydra/derivatives.rb
152
154
  - lib/hydra/derivatives/audio.rb
153
155
  - lib/hydra/derivatives/config.rb
@@ -155,15 +157,21 @@ files:
155
157
  - lib/hydra/derivatives/extract_metadata.rb
156
158
  - lib/hydra/derivatives/ffmpeg.rb
157
159
  - lib/hydra/derivatives/image.rb
160
+ - lib/hydra/derivatives/jpeg2k_config.yml
161
+ - lib/hydra/derivatives/jpeg2k_image.rb
158
162
  - lib/hydra/derivatives/processor.rb
163
+ - lib/hydra/derivatives/railtie.rb
159
164
  - lib/hydra/derivatives/shell_based_processor.rb
160
165
  - lib/hydra/derivatives/video.rb
161
166
  - spec/fixtures/FlashPix.ppt
167
+ - spec/fixtures/adobe1998.tif
162
168
  - spec/fixtures/countdown.avi
169
+ - spec/fixtures/jpeg2k_config.yml
163
170
  - spec/fixtures/piano_note.wav
164
171
  - spec/fixtures/sample.rtf
165
172
  - spec/fixtures/test.doc
166
173
  - spec/fixtures/test.pdf
174
+ - spec/fixtures/test.tif
167
175
  - spec/fixtures/test.xls
168
176
  - spec/fixtures/world.png
169
177
  - spec/lib/hydra/derivatives/extract_metadata_spec.rb
@@ -171,6 +179,7 @@ files:
171
179
  - spec/units/config_spec.rb
172
180
  - spec/units/extract_spec.rb
173
181
  - spec/units/image_spec.rb
182
+ - spec/units/jpeg2k_spec.rb
174
183
  - spec/units/transcoding_spec.rb
175
184
  - spec/units/video_spec.rb
176
185
  homepage: https://github.com/projecthydra/hydra-derivatives
@@ -183,27 +192,30 @@ require_paths:
183
192
  - lib
184
193
  required_ruby_version: !ruby/object:Gem::Requirement
185
194
  requirements:
186
- - - '>='
195
+ - - ">="
187
196
  - !ruby/object:Gem::Version
188
197
  version: '0'
189
198
  required_rubygems_version: !ruby/object:Gem::Requirement
190
199
  requirements:
191
- - - '>='
200
+ - - ">="
192
201
  - !ruby/object:Gem::Version
193
202
  version: '0'
194
203
  requirements: []
195
204
  rubyforge_project:
196
- rubygems_version: 2.0.3
205
+ rubygems_version: 2.2.2
197
206
  signing_key:
198
207
  specification_version: 4
199
208
  summary: Derivative generation plugin for hydra
200
209
  test_files:
201
210
  - spec/fixtures/FlashPix.ppt
211
+ - spec/fixtures/adobe1998.tif
202
212
  - spec/fixtures/countdown.avi
213
+ - spec/fixtures/jpeg2k_config.yml
203
214
  - spec/fixtures/piano_note.wav
204
215
  - spec/fixtures/sample.rtf
205
216
  - spec/fixtures/test.doc
206
217
  - spec/fixtures/test.pdf
218
+ - spec/fixtures/test.tif
207
219
  - spec/fixtures/test.xls
208
220
  - spec/fixtures/world.png
209
221
  - spec/lib/hydra/derivatives/extract_metadata_spec.rb
@@ -211,5 +223,6 @@ test_files:
211
223
  - spec/units/config_spec.rb
212
224
  - spec/units/extract_spec.rb
213
225
  - spec/units/image_spec.rb
226
+ - spec/units/jpeg2k_spec.rb
214
227
  - spec/units/transcoding_spec.rb
215
228
  - spec/units/video_spec.rb