pageflow-linkmap-page 1.4.0 → 1.5.0

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
  SHA256:
3
- metadata.gz: d0c072e362e5fd91d17154f9ed25852b6c53061ea9f50f6ba374fb3fba5fa3d4
4
- data.tar.gz: 0145c75e7ed5b66698fc7c0325fc5d5cf19906f20965078c843aceca614235cf
3
+ metadata.gz: 292a7ccb48c2c4a81d69edfee98d6567861b6df965ab6ff59d29384da534bcc8
4
+ data.tar.gz: 168b15ee2a7da3d2803e2d3ffac8625e3f2d154036e94b725efb261452f086b8
5
5
  SHA512:
6
- metadata.gz: 9013b4a2609db40b0cc6bfe3be0f20807dd829beed8658db5d27a2ccd89867b94df7ef3fae78da2b7a4b34e1d75b483ed59c495e42d247ccc528d433369251b4
7
- data.tar.gz: 7589468debf2e4619411ab137b0cbddbbf81a8be5090d0caabcc1eb6b16e288a27c0ecbba3a09522a45b4abf8b9fed8ee183534592fe4788d65ce75ea17bcadb
6
+ metadata.gz: e5d6b1ddc936609028ccb8ef0a5c6c3ff0cd08ad122bfc8b9b0d9fb2e503d46c6d41df21c52b2eea16bb6cbad64b285f76ab8bdd0cbac43a5a42edce51cddc9c
7
+ data.tar.gz: 1699af6c8ab0e2719df1006f5f16e8947ae52860f7a0a7e863fa2e3c4cfa933b9045f28241cc35dfa3642284422ef57729857bbc56cef52a6afae69a0c27550f
data/CHANGELOG.md CHANGED
@@ -1,15 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
- ### Version 1.4.0
3
+ ### Version 1.5.0
4
4
 
5
- 2018-12-10
5
+ 2019-01-23
6
6
 
7
- [Compare changes](https://github.com/codevise/pageflow-linkmap-page/compare/1-3-stable...v1.4.0)
7
+ [Compare changes](https://github.com/codevise/pageflow-linkmap-page/compare/1-4-stable...v1.5.0)
8
8
 
9
- - Add theme variables for circle and connector line colors
10
- ([#46](https://github.com/codevise/pageflow-linkmap-page/pull/46),
11
- [#45](https://github.com/codevise/pageflow-linkmap-page/pull/45))
9
+ - Add Rake-Task to migrate existing linkmap pages to 2.0-version
10
+ ([#47](https://github.com/codevise/pageflow-linkmap-page/pull/47))
12
11
 
13
12
  See
14
- [1-3-stable branch](https://github.com/codevise/pageflow-linkmap-page/blob/1-3-stable/CHANGELOG.md)
13
+ [1-4-stable branch](https://github.com/codevise/pageflow-linkmap-page/blob/1-4-stable/CHANGELOG.md)
15
14
  for previous changes.
@@ -0,0 +1,15 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ class ProcessSourceImageFileJob
4
+ @queue = :resizing
5
+
6
+ extend StateMachineJob
7
+
8
+ def self.perform_with_result(file, _options)
9
+ file.attachment = file.source_image_file.attachment
10
+ file.save!
11
+ :ok
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,85 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ class ColorMapFile < ProcessedImageFile
4
+ belongs_to :source_image_file, class_name: 'Pageflow::ImageFile'
5
+
6
+ # Prevent anti aliasing. Otherwise, when processing color map
7
+ # images, borders between areas are blurred.
8
+ SOURCE_FILE_OPTIONS = '-filter point'.freeze
9
+
10
+ PALETTE_PATH = Pageflow::LinkmapPage::Engine.root
11
+ .join('lib', 'pageflow', 'linkmap_page', 'images', 'palette.png').freeze
12
+
13
+ CONVERT_OPTIONS = [
14
+ '-quality 70',
15
+ '-interlace Plane',
16
+ '-dither None',
17
+ '-colors 64',
18
+ "-remap #{PALETTE_PATH}",
19
+ ].join(' ').freeze
20
+
21
+ has_attached_file(:attachment,
22
+ Pageflow.config.paperclip_s3_default_options
23
+ .merge(styles: {
24
+ remapped: {
25
+ processors: [:thumbnail],
26
+ format: 'png',
27
+ geometry: GEOMETRY,
28
+ source_file_options: SOURCE_FILE_OPTIONS,
29
+ convert_options: CONVERT_OPTIONS
30
+ },
31
+ sprite: {
32
+ processors: [
33
+ :thumbnail,
34
+ :pageflow_linkmap_page_image_dimensions,
35
+ :pageflow_linkmap_page_image_colors
36
+ ],
37
+ format: 'png',
38
+ geometry: '1024x1024>',
39
+ source_file_options: SOURCE_FILE_OPTIONS,
40
+ convert_options: CONVERT_OPTIONS,
41
+ progress_callback: :update_processing_progress
42
+ }
43
+ }))
44
+
45
+ do_not_validate_attachment_file_type :attachment
46
+
47
+ serialize :attachment_colors
48
+
49
+ def sprite_url
50
+ attachment.url(:sprite)
51
+ end
52
+
53
+ def width
54
+ attachment_width
55
+ end
56
+
57
+ def height
58
+ attachment_height
59
+ end
60
+
61
+ def url
62
+ attachment.url(:remapped)
63
+ end
64
+
65
+ def processed_attachment
66
+ attachment.styles[:remapped]
67
+ end
68
+
69
+ def present_colors
70
+ attachment_colors ? attachment_colors.keys : []
71
+ end
72
+
73
+ def bounding_box_for_color(color)
74
+ attachment_colors[color]
75
+ end
76
+
77
+ private
78
+
79
+ def update_processing_progress(percent)
80
+ update_column(:processing_progress, percent)
81
+ touch
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,51 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ class MaskedImageFile < ProcessedImageFile
4
+ belongs_to :color_map_file, class_name: 'Pageflow::LinkmapPage::ColorMapFile'
5
+
6
+ STYLES = lambda do |attachment|
7
+ masked_image_file = attachment.instance
8
+
9
+ masked_image_file.present_styles.each_with_object({}) do |color, result|
10
+ result[color.to_sym] = {
11
+ processors: [
12
+ :thumbnail,
13
+ :pageflow_linkmap_page_color_mask,
14
+ :pageflow_linkmap_page_invoke_callback
15
+ ],
16
+ color_map_attachment: masked_image_file.color_map_file.processed_attachment,
17
+ format: 'png',
18
+ geometry: GEOMETRY,
19
+ callback: :update_processing_progress
20
+ }
21
+ end
22
+ end
23
+
24
+ has_attached_file(:attachment,
25
+ Pageflow.config.paperclip_s3_default_options
26
+ .merge(styles: STYLES))
27
+
28
+ do_not_validate_attachment_file_type :attachment
29
+
30
+ def url_for_color(color)
31
+ attachment.url(color.to_sym)
32
+ end
33
+
34
+ def for_color(color)
35
+ attachment.styles[color.to_sym]
36
+ end
37
+
38
+ def present_styles
39
+ color_map_file.present_colors
40
+ end
41
+
42
+ private
43
+
44
+ def update_processing_progress(style)
45
+ update_column(:processing_progress,
46
+ (present_styles.index(style.to_s) + 1) * 100 / present_styles.size)
47
+ touch
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,60 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ class ProcessedImageFile < ActiveRecord::Base
4
+ self.abstract_class = true
5
+
6
+ include Pageflow::UploadedFile
7
+
8
+ belongs_to :source_image_file, class_name: 'Pageflow::ImageFile'
9
+
10
+ GEOMETRY = '1920x1080^'.freeze
11
+
12
+ state_machine initial: 'not_processed' do
13
+ extend StateMachineJob::Macro
14
+
15
+ state 'not_processed'
16
+ state 'processing'
17
+ state 'processed'
18
+
19
+ event :process do
20
+ transition 'not_processed' => 'processing'
21
+ transition 'processing_failed' => 'processing'
22
+ end
23
+
24
+ job ProcessSourceImageFileJob do
25
+ on_enter 'processing'
26
+ result ok: 'processed'
27
+ result error: 'processing_failed'
28
+ end
29
+ end
30
+
31
+ def url
32
+ ''
33
+ end
34
+
35
+ def original_url
36
+ ''
37
+ end
38
+
39
+ def retry!
40
+ process!
41
+ end
42
+
43
+ def publish!
44
+ process!
45
+ end
46
+
47
+ def retryable?
48
+ processing_failed?
49
+ end
50
+
51
+ def ready?
52
+ processed?
53
+ end
54
+
55
+ def basename
56
+ 'unused'
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,21 @@
1
+ class CreateMaskedImageFiles < ActiveRecord::Migration
2
+ def change
3
+ create_table :pageflow_linkmap_page_masked_image_files do |t|
4
+ t.belongs_to :entry, index: true
5
+ t.string :state
6
+ t.string :rights
7
+ t.integer :parent_file_id
8
+ t.string :parent_file_model_type
9
+
10
+ t.belongs_to :source_image_file
11
+ t.belongs_to :color_map_file
12
+ t.string :attachment_file_name
13
+ t.integer :processing_progress, default: 0, null: false
14
+
15
+ t.timestamps
16
+
17
+ t.index([:parent_file_id, :parent_file_model_type],
18
+ name: 'index_masked_image_files_on_parent_id_and_parent_model_type')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ class CreateColorMapFiles < ActiveRecord::Migration
2
+ def change
3
+ create_table :pageflow_linkmap_page_color_map_files do |t|
4
+ t.belongs_to :entry, index: true
5
+ t.string :state
6
+ t.string :rights
7
+ t.integer :parent_file_id
8
+ t.string :parent_file_model_type
9
+
10
+ t.string :attachment_file_name
11
+ t.text :attachment_colors
12
+ t.integer :attachment_width
13
+ t.integer :attachment_height
14
+ t.integer :processing_progress, default: 0, null: false
15
+
16
+ t.belongs_to :source_image_file
17
+
18
+ t.timestamps
19
+
20
+ t.index([:parent_file_id, :parent_file_model_type],
21
+ name: 'index_color_map_files_on_parent_id_and_parent_model_type')
22
+ end
23
+ end
24
+ end
@@ -8,6 +8,22 @@ module Pageflow
8
8
  config.autoload_paths << File.join(config.root, 'lib')
9
9
  config.i18n.load_path += Dir[config.root.join('config', 'locales', '**', '*.yml').to_s]
10
10
 
11
+ initializer 'pageflow_linkmap_page.paperclip' do
12
+ Paperclip.configure do |config|
13
+ config.register_processor(:pageflow_linkmap_page_image_colors,
14
+ Pageflow::LinkmapPage::PaperclipProcessors::Colors)
15
+
16
+ config.register_processor(:pageflow_linkmap_page_color_mask,
17
+ Pageflow::LinkmapPage::PaperclipProcessors::ColorMask)
18
+
19
+ config.register_processor(:pageflow_linkmap_page_invoke_callback,
20
+ Pageflow::LinkmapPage::PaperclipProcessors::InvokeCallback)
21
+
22
+ config.register_processor(:pageflow_linkmap_page_image_dimensions,
23
+ Pageflow::LinkmapPage::PaperclipProcessors::ImageDimensions)
24
+ end
25
+ end
26
+
11
27
  config.generators do |g|
12
28
  g.test_framework :rspec,:fixture => false
13
29
  g.fixture_replacement :factory_girl, :dir => 'spec/factories'
@@ -0,0 +1,53 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ module PaperclipProcessors
4
+ class ColorMask < Paperclip::Processor
5
+ CONVERT_COMMAND = [
6
+ # Create mask by making all non-matching colors in color map
7
+ # image transparent
8
+ ':color_map',
9
+ '+transparent :color',
10
+ # Make all areas transparent in source that are transparent in mask
11
+ ':source',
12
+ '-compose src-in -composite',
13
+ # Write result to output file
14
+ ':dest'
15
+ ].join(' ').freeze
16
+
17
+ def make
18
+ with_destination_tempfile do |dest|
19
+ with_color_map do |color_map_path|
20
+ convert(CONVERT_COMMAND,
21
+ color: "##{options[:style]}",
22
+ color_map: color_map_path,
23
+ source: File.expand_path(file.path),
24
+ dest: File.expand_path(dest.path))
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def with_destination_tempfile
32
+ current_format = File.extname(file.path)
33
+ basename = File.basename(file.path, current_format)
34
+
35
+ dest = Tempfile.new([basename, '.png'])
36
+ dest.binmode
37
+
38
+ yield dest
39
+
40
+ dest
41
+ end
42
+
43
+ def with_color_map(&block)
44
+ Pageflow::LinkmapPage::PaperclipTempfile.for(color_map_attachment, &block)
45
+ end
46
+
47
+ def color_map_attachment
48
+ options.fetch(:color_map_attachment)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,213 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ module PaperclipProcessors
4
+ class Colors < Paperclip::Processor
5
+ def make
6
+ with_progress(steps: 2) do |progress|
7
+ colors = unique_colors(file) - ['000000']
8
+ boxes = color_bounding_boxes_ignoring_single_pixels(file, colors, progress)
9
+
10
+ attachment.instance_write('colors', boxes)
11
+ make_color_sprite(file, boxes.keys, progress)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def unique_colors(file)
18
+ ConvertOutput.parse_unique_colors(convert(':source -unique-colors txt:-',
19
+ source: file.path))
20
+ end
21
+
22
+ def color_bounding_boxes_ignoring_single_pixels(file, colors, overall_progress)
23
+ overall_progress.divide(steps: colors.size) do |progress|
24
+ boxes = colors.each_with_object({}) do |color, result|
25
+ result[color] = color_bounding_box_ignoring_single_pixels(file, color)
26
+ progress.step
27
+ end
28
+
29
+ remove_boxes_for_ignored_colors(boxes)
30
+ end
31
+ end
32
+
33
+ def remove_boxes_for_ignored_colors(boxes)
34
+ boxes.delete_if do |_, box|
35
+ box[:width].zero? && box[:height].zero?
36
+ end
37
+ end
38
+
39
+ COLOR_MASK_ARGS = [
40
+ # Make transparent areas black
41
+ '-background black -flatten',
42
+ # Make all non matching colors black
43
+ '-fill black +opaque :color',
44
+ # Replace color with white - required for morphology
45
+ '-fill white -opaque :color',
46
+ # Remove shapes that are smaller than 3x3 pixels
47
+ '-morphology Open Square:1',
48
+ # Make black areas transparent
49
+ '-transparent black',
50
+ # Restore original color
51
+ '-fill :color -opaque white',
52
+ ].join(' ').freeze
53
+
54
+ TRIM_CONVERT_ARGS = [
55
+ # Make all non-matching colors in color map image
56
+ # transparent
57
+ ':source',
58
+ COLOR_MASK_ARGS,
59
+ # Create a transparent border
60
+ '-bordercolor none',
61
+ '-border 1x1',
62
+ # Trim transparent region.
63
+ '-trim',
64
+ ].join(' ').freeze
65
+
66
+ TRIM_INFO_CONVERT_ARGS = [
67
+ TRIM_CONVERT_ARGS,
68
+ # Write info to stdout
69
+ 'info:-'
70
+ ].join(' ').freeze
71
+
72
+ def color_bounding_box_ignoring_single_pixels(file, color)
73
+ box = ConvertOutput.parse_trim(convert(TRIM_INFO_CONVERT_ARGS,
74
+ color: "##{color}",
75
+ source: file.path))
76
+ ignore_added_border_in_coordinated(box)
77
+ end
78
+
79
+ def ignore_added_border_in_coordinated(box)
80
+ {
81
+ left: box[:left] - 1,
82
+ top: box[:top] - 1,
83
+ width: box[:width],
84
+ height: box[:height]
85
+ }
86
+ end
87
+
88
+ def make_color_sprite(file, colors, overall_progress)
89
+ with_destination_tempfile do |sprite_tempfile|
90
+ with_tempfiles(colors) do |color_tempfiles|
91
+ overall_progress.divide(steps: colors.size + 1) do |progress|
92
+ color_tempfiles.each do |color, color_tempfile|
93
+ make_color_filtered_image(file, color, color_tempfile)
94
+ progress.step
95
+ end
96
+
97
+ make_sprite(color_tempfiles, sprite_tempfile)
98
+ progress.step
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ COLOR_FILTER_CONVERT_ARGS = [
105
+ TRIM_CONVERT_ARGS,
106
+ # Crop image to trimmed area
107
+ '+repage',
108
+ ':dest'
109
+ ].join(' ').freeze
110
+
111
+ def make_color_filtered_image(file, color, destination_tempfile)
112
+ convert(COLOR_FILTER_CONVERT_ARGS,
113
+ color: "##{color}",
114
+ source: File.expand_path(file.path),
115
+ dest: File.expand_path(destination_tempfile.path))
116
+ end
117
+
118
+ def make_sprite(files, destination_tempfile)
119
+ inputs = files.each_with_object({}) do |(key, tempfile), result|
120
+ result["input_#{key}"] = File.expand_path(tempfile.path)
121
+ end
122
+
123
+ placeholders = inputs.keys.sort.map { |key| ":#{key}" }
124
+
125
+ Paperclip.run('montage',
126
+ [
127
+ *placeholders,
128
+ '-background transparent',
129
+ "-tile #{inputs.size}x",
130
+ '-mode Concatenate',
131
+ ':output'
132
+ ].join(' '),
133
+ inputs.merge(output: File.expand_path(destination_tempfile.path)))
134
+ end
135
+
136
+ def with_destination_tempfile
137
+ dest = create_tempfile
138
+ yield dest
139
+ dest
140
+ end
141
+
142
+ def with_tempfiles(keys)
143
+ files = keys.each_with_object({}) do |key, result|
144
+ result[key] = create_tempfile(key)
145
+ end
146
+
147
+ yield files
148
+ ensure
149
+ files.each_value do |file|
150
+ file.close
151
+ file.unlink
152
+ end
153
+ end
154
+
155
+ def create_tempfile(suffix = nil)
156
+ current_format = File.extname(file.path)
157
+ basename = File.basename(file.path, current_format)
158
+
159
+ dest = Tempfile.new([[basename, suffix].compact.join('-'), '.png'])
160
+ dest.binmode
161
+
162
+ dest
163
+ end
164
+
165
+ def with_progress(steps:)
166
+ progress = Pageflow::LinkmapPage::Progress.new(steps: steps) do |percent|
167
+ if options[:progress_callback]
168
+ attachment.instance.send(options[:progress_callback], percent)
169
+ end
170
+ end
171
+
172
+ yield progress
173
+ end
174
+
175
+ module ConvertOutput
176
+ HEX_COLOR_REGEXP = /#[0-9a-f]{6,8}/i
177
+ TRANSPARENT = '#00000000'.freeze
178
+
179
+ module_function
180
+
181
+ def parse_unique_colors(output)
182
+ output
183
+ .split("\n")
184
+ .reject { |line| line.starts_with?('#') }
185
+ .map { |line| line[HEX_COLOR_REGEXP] }
186
+ .reject { |color| color == TRANSPARENT }
187
+ .map { |color| color.tr('#', '') }
188
+ .map(&:downcase)
189
+ .sort
190
+ end
191
+
192
+ def parse_trim(output)
193
+ trimmed_size, size_and_offset = output.split(' ')[2, 3]
194
+ width, height = trimmed_size.split('x')
195
+
196
+ if size_and_offset.ends_with?('-1-1')
197
+ return {left: 0, top: 0, width: 0, height: 0}
198
+ end
199
+
200
+ _size, left, top = size_and_offset.split('+')
201
+
202
+ {
203
+ left: left.to_i,
204
+ top: top.to_i,
205
+ width: width.to_i,
206
+ height: height.to_i
207
+ }
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,21 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ module PaperclipProcessors
4
+ class ImageDimensions < Paperclip::Processor
5
+ def make
6
+ store_dimensions(file)
7
+ file
8
+ end
9
+
10
+ private
11
+
12
+ def store_dimensions(file)
13
+ geometry = Paperclip::Geometry.from_file(file)
14
+
15
+ attachment.instance_write('width', geometry.width)
16
+ attachment.instance_write('height', geometry.height)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ module PaperclipProcessors
4
+ class InvokeCallback < Paperclip::Processor
5
+ def make
6
+ attachment.instance.send(options[:callback], options[:style])
7
+ file
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ module PaperclipTempfile
4
+ module_function
5
+
6
+ def for(attachment)
7
+ tempfile = Paperclip.io_adapters.for(attachment)
8
+
9
+ begin
10
+ yield(tempfile.path)
11
+ ensure
12
+ tempfile.close
13
+ tempfile.unlink
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,43 @@
1
+ module Pageflow
2
+ module LinkmapPage
3
+ class Progress
4
+ def initialize(steps:, &block)
5
+ @total_steps = steps
6
+ @block = block
7
+ @counter = 0
8
+ end
9
+
10
+ def step
11
+ return if counter >= total_steps
12
+ @counter += 1
13
+ report(current_percent)
14
+ end
15
+
16
+ def divide(steps:)
17
+ return if counter >= total_steps
18
+
19
+ sub_progress = Progress.new(steps: steps) do |percent|
20
+ if percent == 100
21
+ step
22
+ else
23
+ report(current_percent + percent / total_steps)
24
+ end
25
+ end
26
+
27
+ yield sub_progress
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :block, :total_steps, :counter
33
+
34
+ def current_percent
35
+ 100.0 / total_steps * counter
36
+ end
37
+
38
+ def report(percent)
39
+ @block.call(percent)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
2
  module LinkmapPage
3
- VERSION = '1.4.0'.freeze
3
+ VERSION = '1.5.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,149 @@
1
+ namespace :pageflow_linkmap_page do
2
+ desc 'Migrate to server generated files'
3
+ task migrate_to_masked_image_files: :environment do
4
+ Pageflow::LinkmapPage::MaskedImageFilesMigrator.run
5
+ end
6
+ end
7
+
8
+ module Pageflow
9
+ module LinkmapPage
10
+ module MaskedImageFilesMigrator
11
+ extend self
12
+
13
+ def run
14
+ Resque.inline = true
15
+ total = pages_with_mask_image.count
16
+
17
+ pages_with_mask_image.find_each.with_index do |page, index|
18
+ puts "== Migrating page #{page.id} (#{index}/#{total})"
19
+ color_map_file = create_files(page)
20
+
21
+ if color_map_file
22
+ puts '-- Migrating mask perma ids...'
23
+ migrate_mask_perma_ids(page, color_map_file)
24
+ end
25
+
26
+ page.save!
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def create_files(page)
33
+ color_map_image_file =
34
+ ImageFile.find_by_id(page.configuration['linkmap_color_map_image_id'])
35
+
36
+ if color_map_image_file
37
+ revision = page.chapter.storyline.revision
38
+
39
+ puts "-- Color map file for image file #{color_map_image_file.id}"
40
+
41
+ color_map_file = color_map_file_for(color_map_image_file, revision)
42
+ page.configuration['linkmap_color_map_file_id'] = color_map_file.id
43
+
44
+ hover_image_file = ImageFile.find_by_id(page.configuration['hover_image_id'])
45
+
46
+ if hover_image_file
47
+ puts "-- Masked image file for hover image file #{hover_image_file.id}"
48
+
49
+ masked_image_file = masked_image_file_for(hover_image_file, color_map_file, revision)
50
+ page.configuration['linkmap_masked_hover_image_id'] = masked_image_file.id
51
+ end
52
+
53
+ visited_image_file = ImageFile.find_by_id(page.configuration['visited_image_id'])
54
+
55
+ if visited_image_file
56
+ puts "-- Masked image file for visited image file #{visited_image_file.id}"
57
+
58
+ masked_image_file = masked_image_file_for(visited_image_file, color_map_file, revision)
59
+ page.configuration['linkmap_masked_visited_image_id'] = masked_image_file.id
60
+ end
61
+
62
+ color_map_file
63
+ end
64
+ end
65
+
66
+ def color_map_file_for(image_file, revision)
67
+ color_map_file = ColorMapFile.find_or_create_by(source_image_file_id: image_file.id) do |c|
68
+ c.entry_id = revision.entry_id
69
+ end
70
+
71
+ unless color_map_file.processed?
72
+ puts ' Processing...'
73
+
74
+ color_map_file.process!
75
+ color_map_file.reload
76
+ end
77
+
78
+ revision.file_usages.find_or_create_by(file: color_map_file)
79
+ color_map_file
80
+ end
81
+
82
+ def masked_image_file_for(image_file, color_map_file, revision)
83
+ masked_image_file = MaskedImageFile.find_or_create_by(source_image_file: image_file,
84
+ color_map_file: color_map_file) do |m|
85
+ m.entry_id = revision.entry_id
86
+ end
87
+
88
+ unless masked_image_file.processed?
89
+ puts ' Processing...'
90
+
91
+ masked_image_file.process!
92
+ masked_image_file.reload
93
+ end
94
+
95
+ revision.file_usages.find_or_create_by(file: masked_image_file)
96
+ masked_image_file
97
+ end
98
+
99
+ def migrate_mask_perma_ids(page, color_map_file)
100
+ areas = page.configuration['linkmap_areas'] || []
101
+
102
+ page.configuration['linkmap_areas'] = areas.map do |area_attributes|
103
+ mask_perma_id = area_attributes['mask_perma_id']
104
+
105
+ if mask_perma_id && !area_attributes['color_map_component_id']
106
+ sprite_id = page.configuration.fetch('linkmap_masks').fetch('id')
107
+ colors =
108
+ page
109
+ .configuration
110
+ .fetch('linkmap_masks')
111
+ .fetch('c')
112
+ .fetch('c')
113
+ .map { |component| component['c'] }
114
+
115
+ area_attributes.merge(color_map_component_id: convert_mask_perma_id(mask_perma_id,
116
+ colors,
117
+ color_map_file,
118
+ sprite_id))
119
+ else
120
+ area_attributes
121
+ end
122
+ end
123
+ end
124
+
125
+ def convert_mask_perma_id(perma_id, colors, color_map_file, sprite_id)
126
+ target_sprite_id, color_index = perma_id.split(':')
127
+
128
+ if target_sprite_id.to_i == sprite_id
129
+ "#{color_map_file.id}:#{nearest_color(color_map_file, *colors[color_index.to_i])}"
130
+ end
131
+ end
132
+
133
+ def nearest_color(color_map_file, r, g, b)
134
+ color_map_file.present_colors.min_by do |color|
135
+ (color[0..1].to_i(16) - r).abs +
136
+ (color[2..3].to_i(16) - g).abs +
137
+ (color[4..5].to_i(16) - b).abs
138
+ end
139
+ end
140
+
141
+ def pages_with_mask_image
142
+ Page
143
+ .where(template: 'linkmap_page')
144
+ .where('configuration LIKE "%linkmap_color_map_image_id%"')
145
+ .includes(chapter: {storyline: :revision})
146
+ end
147
+ end
148
+ end
149
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pageflow-linkmap-page
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Codevise Solutions Ltd.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-10 00:00:00.000000000 Z
11
+ date: 2019-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pageflow
@@ -253,7 +253,11 @@ files:
253
253
  - app/assets/stylesheets/pageflow/linkmap_page/themes/default/scroll_indicators.scss
254
254
  - app/controllers/pageflow/linkmap_page/mask_sprites_controller.rb
255
255
  - app/helpers/pageflow/linkmap_page/areas_helper.rb
256
+ - app/jobs/pageflow/linkmap_page/process_source_image_file_job.rb
257
+ - app/models/pageflow/linkmap_page/color_map_file.rb
256
258
  - app/models/pageflow/linkmap_page/mask_sprite.rb
259
+ - app/models/pageflow/linkmap_page/masked_image_file.rb
260
+ - app/models/pageflow/linkmap_page/processed_image_file.rb
257
261
  - app/views/pageflow/linkmap_page/areas/_div.html.erb
258
262
  - app/views/pageflow/linkmap_page/page.html.erb
259
263
  - bin/rspec
@@ -263,12 +267,22 @@ files:
263
267
  - config/routes.rb
264
268
  - config/spring.rb
265
269
  - db/migrate/20170330201200_create_mask_sprites.rb
270
+ - db/migrate/20171106151700_create_masked_image_files.rb
271
+ - db/migrate/20180111145100_create_color_map_files.rb
266
272
  - lib/generators/pageflow_linkmap_page/install/install_generator.rb
267
273
  - lib/pageflow-linkmap-page.rb
268
274
  - lib/pageflow/linkmap_page/engine.rb
275
+ - lib/pageflow/linkmap_page/images/palette.png
269
276
  - lib/pageflow/linkmap_page/page_type.rb
277
+ - lib/pageflow/linkmap_page/paperclip_processors/color_mask.rb
278
+ - lib/pageflow/linkmap_page/paperclip_processors/colors.rb
279
+ - lib/pageflow/linkmap_page/paperclip_processors/image_dimensions.rb
280
+ - lib/pageflow/linkmap_page/paperclip_processors/invoke_callback.rb
281
+ - lib/pageflow/linkmap_page/paperclip_tempfile.rb
270
282
  - lib/pageflow/linkmap_page/plugin.rb
283
+ - lib/pageflow/linkmap_page/progress.rb
271
284
  - lib/pageflow/linkmap_page/version.rb
285
+ - lib/tasks/pageflow_linkmap_page_tasks.rake
272
286
  - pageflow-linkmap-page.gemspec
273
287
  - spec/controllers/pageflow/linkmap_page/mask_sprites_controller_spec.rb
274
288
  - spec/helpers/pageflow/linkmap_page/areas_helper_spec.rb
@@ -295,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
295
309
  version: '0'
296
310
  requirements: []
297
311
  rubyforge_project:
298
- rubygems_version: 2.7.5
312
+ rubygems_version: 2.7.8
299
313
  signing_key:
300
314
  specification_version: 4
301
315
  summary: Pageflow page type for a page that contains customizable link areas