pageflow-linkmap-page 1.4.0 → 1.5.0

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