ruby-clip 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 38d04be6e9a54a1bd07fef270d5040d36bae39572be238876fa64baa089dae4a
4
+ data.tar.gz: b4a4f2532d37c2ee5db743af02d7429a2005e0bb74ed1c234d6578a84d92e4b6
5
+ SHA512:
6
+ metadata.gz: 7f922425c94fafe8ccf6178376ca33364ab0f99a86a096e8c83d37f399b372cc0825c0c084c6c2ee63bbab3039b93ea3f91db8a4b733518fe80a52d1c7825b5a
7
+ data.tar.gz: 9b9a06d319e20734c9412521b3b26148376c93147c1907c52a82d3784ed116adfaae09ab9092cc5e5ca43b6a2e0095b2dc968c66b7acf069b0bac5f1b84a5abd
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-12-10
4
+
5
+ - Initial release, Canvas Preview export only
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Julien 'Lta' BALLET
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # Ruby::Clip
2
+
3
+ A miminal parser for Clip Studio Paint file. Currently this lib can only export
4
+ the Canvas previews out of the file.
5
+
6
+ ## Installation
7
+
8
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
9
+
10
+ Install the gem and add to the application's Gemfile by executing:
11
+
12
+ ```bash
13
+ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
14
+ ```
15
+
16
+ If bundler is not being used to manage dependencies, install the gem by executing:
17
+
18
+ ```bash
19
+ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ``` ruby
25
+ require 'clip'
26
+
27
+ file = Clip::File.open('/path/to/file.clip')
28
+ preview = file.previews.first
29
+
30
+ # Get info about the canvas preview
31
+ preview.width # => 800
32
+ preview.height # => 60000
33
+
34
+ # Access the preview image content
35
+ preview.image # => "PNG..."
36
+
37
+ # Save the preview to a file
38
+ preview.image_save('/tmp/my_clip_preview.png')
39
+
40
+ # Save the preview to a temporary file
41
+ tempfile = preview.image_tempfile # => #<File:/tmp/ruby-clip--20241211-276516-hunc5h.png>
42
+ tempfile.close
43
+
44
+ # Close the file, coz' you're so well-behaved
45
+ file.close
46
+ ```
47
+
48
+ ## Development
49
+
50
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
+
52
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at
57
+ https://github.com/flagcatstudio/ruby-clip.
58
+
59
+ ## License
60
+
61
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clip
4
+ class CanvasPreview
5
+ attr_reader :file, :row
6
+
7
+ def initialize(file, row)
8
+ @file = file
9
+ @row = row
10
+ end
11
+
12
+ def inspect
13
+ "#{self.class.name}: #{@row}"
14
+ end
15
+
16
+ def main_id
17
+ row[:MainId]
18
+ end
19
+
20
+ def canvas_id
21
+ row[:CanvasId]
22
+ end
23
+
24
+ def width
25
+ row[:ImageWidth]
26
+ end
27
+
28
+ def height
29
+ row[:ImageHeigth]
30
+ end
31
+
32
+ def image_type
33
+ # NOTE: So far I've only encountered ImageType == 1, which I assume means
34
+ # png. but we can't know for sure :shrug:
35
+ row[:ImageType]
36
+ end
37
+
38
+ def image
39
+ row[:ImageData]
40
+ end
41
+
42
+ def image_tempfile
43
+ file = Tempfile.new(['ruby-clip--', '.png'])
44
+ file.write image
45
+ file.seek 0
46
+ file
47
+ end
48
+
49
+ def image_save(path)
50
+ File.open(path, 'wb') do |file|
51
+ file.write image
52
+ end
53
+ end
54
+ end
55
+ end
data/lib/clip/file.rb ADDED
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sqlite3'
4
+
5
+ require_relative './canvas_preview'
6
+
7
+ module Clip
8
+ class File
9
+ MAGIC = 'CSFCHUNK'
10
+ SQLITE_MAGIC = 'SQLite format 3'
11
+ FOOTER_MARKER = 'CHNKFoot'
12
+
13
+ attr_reader :path
14
+
15
+ def self.open(*, **)
16
+ new(*, **)
17
+ end
18
+
19
+ def initialize(path)
20
+ @path = path
21
+
22
+ raise InvalidClipFile, 'Not a CSP .clip' unless magic_present?
23
+ raise InvalidClipFile, 'No database found in .clip' unless sqlite_present?
24
+ end
25
+
26
+ def file
27
+ @file ||= ::File.open(path, 'rb')
28
+ end
29
+
30
+ def raw_content
31
+ @raw_content ||= file.read
32
+ end
33
+
34
+ def magic_present?
35
+ file.pread(MAGIC.length, 0) == MAGIC
36
+ end
37
+
38
+ def sqlite_present?
39
+ !sqlite_index.nil?
40
+ end
41
+
42
+ def sqlite_content
43
+ @sqlite_content ||=
44
+ begin
45
+ len = footer_index - sqlite_index
46
+ raw_content.byteslice(sqlite_index, len)
47
+ end
48
+ end
49
+
50
+ def sqlite_file
51
+ @sqlite_file ||=
52
+ begin
53
+ file = Tempfile.new("ruby-clip-#{basename}--")
54
+ file.write(sqlite_content)
55
+ file.seek(0)
56
+ file
57
+ end
58
+ end
59
+
60
+ def sqlite
61
+ @sqlite ||= SQLite3::Database.open(sqlite_file.path)
62
+ end
63
+
64
+ def close
65
+ if defined? :@sqlite && @sqlite
66
+ @sqlite.close
67
+ @sqlite = nil
68
+ end
69
+
70
+ if defined? :@sqlite_file && @sqlite_file
71
+ @sqlite_file.close
72
+ @sqlite_file.unlink
73
+ @sqlite_file = nil
74
+ end
75
+ end
76
+
77
+ def canvas_previews
78
+ rows = sqlite_execute_as_hash <<-SQL
79
+ SELECT * FROM CanvasPreview;
80
+ SQL
81
+ rows.map { |row| CanvasPreview.new(self, row) }
82
+ end
83
+
84
+
85
+ protected
86
+
87
+ def basename
88
+ ::File.basename(path)
89
+ end
90
+
91
+ def sqlite_index
92
+ raw_content.index SQLITE_MAGIC
93
+ end
94
+
95
+ def footer_index
96
+ raw_content.rindex FOOTER_MARKER || raw_content.length
97
+ end
98
+
99
+ def sqlite_execute_as_hash(query)
100
+ rows = sqlite.execute2(query)
101
+ headers = rows.shift.map(&:to_sym)
102
+
103
+ rows.map do |row|
104
+ h = {}
105
+ headers.each_with_index { |header, index| h[header] = row[index] }
106
+ h
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Clip
4
+ VERSION = "0.1.0"
5
+ end
data/lib/clip.rb ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "clip/version"
4
+
5
+ require_relative "clip/file"
6
+
7
+ module Clip
8
+ class Error < StandardError; end
9
+ # Your code goes here...
10
+
11
+ class InvalidClipFile < Error; end
12
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-clip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Julien 'Lta' BALLET
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-12-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sqlite3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ description:
28
+ email:
29
+ - lta@flagcat.studio
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".rspec"
35
+ - CHANGELOG.md
36
+ - LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - lib/clip.rb
40
+ - lib/clip/canvas_preview.rb
41
+ - lib/clip/file.rb
42
+ - lib/clip/version.rb
43
+ homepage: https://github.com/FlagCatStudio/ruby-clip
44
+ licenses:
45
+ - MIT
46
+ metadata:
47
+ homepage_uri: https://github.com/FlagCatStudio/ruby-clip
48
+ source_code_uri: https://github.com/FlagCatStudio/ruby-clip
49
+ changelog_uri: https://github.com/FlagCatStudio/ruby-clip/blob/main/CHANGELOG.md
50
+ Copyrights: Flagcat SAS
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 3.0.0
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubygems_version: 3.5.22
67
+ signing_key:
68
+ specification_version: 4
69
+ summary: A minimal parser for Clip Studio Paint files
70
+ test_files: []