hydra-derivatives 0.0.7 → 0.0.8

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 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