mupdf 0.3.0 → 1.0.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 +4 -4
- data/Gemfile +1 -0
- data/README.md +44 -2
- data/lib/mupdf/box.rb +72 -0
- data/lib/mupdf/document.rb +49 -0
- data/lib/mupdf/page.rb +123 -0
- data/lib/mupdf/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75c0956dd50c089d4cea76952bdc5c4244a946c674d4e648edc71d749bd1faca
|
4
|
+
data.tar.gz: c5fe14cf7c06739d4e03480c894ab938c4e0fa68b897bdcf4b49e0f078f33bf5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 842db6317559209c6f2a6b0205adc8e2792c395be8fc61c0b5b23a6d750d86daf8a9642b656661efea26981cbbe6e8b64c83cd9448b470941bedc7c8011df04c
|
7
|
+
data.tar.gz: e3e79b6054b2f4f32947d62b64ca421d71efe1c949d544e99e0464503a22dde8472d4cb5da7e8cf9770d464dd7bd0f8e5b2a95d8351ab7c9347edd88405b32b9
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -12,11 +12,29 @@
|
|
12
12
|
gem install mupdf
|
13
13
|
```
|
14
14
|
|
15
|
+
_This project requires `mutool` be installed on your system. To verify ensure the following works:_
|
16
|
+
|
17
|
+
```bash
|
18
|
+
mutool
|
19
|
+
```
|
20
|
+
|
21
|
+
To install `mutool` on MacOS use:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
brew install mupdf
|
25
|
+
```
|
26
|
+
|
27
|
+
To install `mutool` on Ubuntu use:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
apt-get install mupdf
|
31
|
+
```
|
32
|
+
|
15
33
|
## Usage
|
16
34
|
|
17
35
|
### Document
|
18
36
|
|
19
|
-
A `MuPDF::Document` wraps
|
37
|
+
A `MuPDF::Document` wraps a PDF file:
|
20
38
|
|
21
39
|
```ruby
|
22
40
|
document = MuPDF::Document.new('./file.pdf')
|
@@ -24,9 +42,33 @@ document = MuPDF::Document.new('./file.pdf')
|
|
24
42
|
|
25
43
|
#### Info
|
26
44
|
|
27
|
-
The `info` command displays information about
|
45
|
+
The `info` command displays information about the document such as the number of pages:
|
28
46
|
|
29
47
|
```ruby
|
30
48
|
info = document.info
|
31
49
|
info.pages # e.g. 2
|
32
50
|
```
|
51
|
+
|
52
|
+
#### Pages
|
53
|
+
|
54
|
+
The `pages` command finds sizing information about the pages within a document:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
pages = document.pages
|
58
|
+
pages.count # e.g. 2
|
59
|
+
pages.each do |page|
|
60
|
+
page.number # e.g. 1, 2, ...
|
61
|
+
page.width # 612
|
62
|
+
page.height # 792
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
#### Draw
|
67
|
+
|
68
|
+
The `draw` command is useful for converting a document between formats:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
document.pages.each do |page|
|
72
|
+
document.draw(page: page.number, format: "png", path: "./file-#{page.number}.png")
|
73
|
+
end
|
74
|
+
```
|
data/lib/mupdf/box.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MuPDF
|
4
|
+
# A bounding box for a PDF (e.g. media / crop / bleed / trim).
|
5
|
+
class Box
|
6
|
+
REGEX = /l="(?<l>\d+)" b="(?<b>\d+)" r="(?<r>\d+)" t="(?<t>\d+)"/
|
7
|
+
|
8
|
+
# @!attribute l
|
9
|
+
# @return [String] The left coordinate.
|
10
|
+
attr_reader :l
|
11
|
+
|
12
|
+
# @!attribute b
|
13
|
+
# @return [String] The bottom coordinate.
|
14
|
+
attr_reader :b
|
15
|
+
|
16
|
+
# @!attribute r
|
17
|
+
# @return [String] The right coordinate.
|
18
|
+
attr_reader :r
|
19
|
+
|
20
|
+
# @!attribute t
|
21
|
+
# @return [String] The top coordinate.
|
22
|
+
attr_reader :t
|
23
|
+
|
24
|
+
# @!attribute kind
|
25
|
+
# @return [Symbol] The kind of box.
|
26
|
+
attr_reader :kind
|
27
|
+
|
28
|
+
# @param text [String]
|
29
|
+
# @param kind [Symbol]
|
30
|
+
#
|
31
|
+
# @return [MuPDF::Box]
|
32
|
+
def self.parse(text, kind:)
|
33
|
+
match = text.match(REGEX)
|
34
|
+
|
35
|
+
new(
|
36
|
+
l: Integer(match[:l]),
|
37
|
+
b: Integer(match[:b]),
|
38
|
+
r: Integer(match[:r]),
|
39
|
+
t: Integer(match[:t]),
|
40
|
+
kind:
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param l [Integer]
|
45
|
+
# @param b [Integer]
|
46
|
+
# @param r [Integer]
|
47
|
+
# @param t [Integer]
|
48
|
+
# @param kind [Symbol] optional
|
49
|
+
def initialize(l:, b:, r:, t:, kind: nil)
|
50
|
+
@l = l
|
51
|
+
@b = b
|
52
|
+
@r = r
|
53
|
+
@t = t
|
54
|
+
@kind = kind
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [String]
|
58
|
+
def inspect
|
59
|
+
"#<#{self.class.name} l=#{l} b=#{b} r=#{r} t=#{t} kind=#{kind}>"
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Integer]
|
63
|
+
def width
|
64
|
+
@r - @l
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Integer]
|
68
|
+
def height
|
69
|
+
@t - @b
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/mupdf/document.rb
CHANGED
@@ -8,6 +8,14 @@ module MuPDF
|
|
8
8
|
@pathname = pathname
|
9
9
|
end
|
10
10
|
|
11
|
+
# @return [String]
|
12
|
+
def inspect
|
13
|
+
"#<#{self.class.name} pathname=#{@pathname}>"
|
14
|
+
end
|
15
|
+
|
16
|
+
# @usage
|
17
|
+
# document.info #=> #<MuPDF::Info ...>
|
18
|
+
#
|
11
19
|
# @raise [MuPDF::CommandError]
|
12
20
|
#
|
13
21
|
# @return [MuPDF::Info]
|
@@ -17,5 +25,46 @@ module MuPDF
|
|
17
25
|
MuPDF::Info.parse(result)
|
18
26
|
end
|
19
27
|
end
|
28
|
+
|
29
|
+
# @usage
|
30
|
+
# pages = document.pages #=> [#<MuPDF::Page ...>, ...]
|
31
|
+
# pages.each do |page|
|
32
|
+
# puts page.number # e.g. 1, 2, 3, ...
|
33
|
+
# puts page.width # e.g. 612
|
34
|
+
# puts page.height # e.g. 792
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# @raise [MuPDF::CommandError]
|
38
|
+
#
|
39
|
+
# @return [Array<MuPDF::Page>]
|
40
|
+
def pages
|
41
|
+
@pages ||= begin
|
42
|
+
result = MuPDF.mutool('pages', String(@pathname))
|
43
|
+
MuPDF::Page.parse(result)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @usage
|
48
|
+
# Tempfile.open(['mupdf', '.png']) do |tempfile|
|
49
|
+
# document.draw(path: tempfile.path, page: 2, format: 'png')
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# @param path [String] the path where the conversion is saved
|
53
|
+
# @param format [String] "png", "svg", "txt", etc
|
54
|
+
# @param page [Integer] the page
|
55
|
+
# @param resultion [Integer] optional (default: 72)
|
56
|
+
# @param width [Integer] optional
|
57
|
+
# @param height [Integer] optional
|
58
|
+
#
|
59
|
+
# @raise [MuPDF::CommandError]
|
60
|
+
def draw(path:, page:, format: 'png', width: nil, height: nil, resolution: nil)
|
61
|
+
args = ['draw', '-o', path, '-F', format, String(@pathname), String(page)]
|
62
|
+
|
63
|
+
args << '-w' << width if width
|
64
|
+
args << '-h' << height if height
|
65
|
+
args << '-r' << resolution if resolution
|
66
|
+
|
67
|
+
MuPDF.mutool(*args)
|
68
|
+
end
|
20
69
|
end
|
21
70
|
end
|
data/lib/mupdf/page.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MuPDF
|
4
|
+
# A wrapper for a PDF page within a PDF document.
|
5
|
+
class Page
|
6
|
+
REGEX = %r{<page pagenum="(?<pagenum>\d+)">(?<content>.*?)</page>}m
|
7
|
+
MEDIA_BOX_REGEX = %r{<MediaBox (?<content>.*?) />}
|
8
|
+
CROP_BOX_REGEX = %r{<CropBox (?<content>.*?) />}
|
9
|
+
ART_BOX_REGEX = %r{<ArtBox (?<content>.*?) />}
|
10
|
+
BLEED_BOX_REGEX = %r{<BleedBox (?<content>.*?) />}
|
11
|
+
TRIM_BOX_REGEX = %r{<TrimBox (?<content>.*?) />}
|
12
|
+
|
13
|
+
# @param text [String]
|
14
|
+
#
|
15
|
+
# @return [Array<MuPDF::Page>]
|
16
|
+
def self.parse(text)
|
17
|
+
text.scan(REGEX).map do |number, content|
|
18
|
+
new(
|
19
|
+
media_box: parse_media_box(content),
|
20
|
+
crop_box: parse_crop_box(content),
|
21
|
+
art_box: parse_art_box(content),
|
22
|
+
bleed_box: parse_bleed_box(content),
|
23
|
+
trim_box: parse_trim_box(content),
|
24
|
+
number: Integer(number)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param text [String]
|
30
|
+
#
|
31
|
+
# @return [MuPDF::Box]
|
32
|
+
def self.parse_media_box(text)
|
33
|
+
match = MEDIA_BOX_REGEX.match(text)
|
34
|
+
MuPDF::Box.parse(match[:content], kind: :media)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param text [String]
|
38
|
+
#
|
39
|
+
# @return [MuPDF::Box]
|
40
|
+
def self.parse_crop_box(text)
|
41
|
+
match = CROP_BOX_REGEX.match(text)
|
42
|
+
MuPDF::Box.parse(match[:content], kind: :crop)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param text [String]
|
46
|
+
#
|
47
|
+
# @return [MuPDF::Box]
|
48
|
+
def self.parse_art_box(text)
|
49
|
+
match = ART_BOX_REGEX.match(text)
|
50
|
+
MuPDF::Box.parse(match[:content], kind: :art)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param text [String]
|
54
|
+
#
|
55
|
+
# @return [MuPDF::Box]
|
56
|
+
def self.parse_bleed_box(text)
|
57
|
+
match = BLEED_BOX_REGEX.match(text)
|
58
|
+
MuPDF::Box.parse(match[:content], kind: :bleed)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param text [String]
|
62
|
+
#
|
63
|
+
# @return [MuPDF::Box]
|
64
|
+
def self.parse_trim_box(text)
|
65
|
+
match = TRIM_BOX_REGEX.match(text)
|
66
|
+
MuPDF::Box.parse(match[:content], kind: :trim)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @!attribute media_box
|
70
|
+
# @return [MuPDFBox]
|
71
|
+
attr_accessor :media_box
|
72
|
+
|
73
|
+
# @!attribute crop_box
|
74
|
+
# @return [MuPDFBox]
|
75
|
+
attr_accessor :crop_box
|
76
|
+
|
77
|
+
# @!attribute art_box
|
78
|
+
# @return [MuPDFBox]
|
79
|
+
attr_accessor :art_box
|
80
|
+
|
81
|
+
# @!attribute bleed_box
|
82
|
+
# @return [MuPDFBox]
|
83
|
+
attr_accessor :bleed_box
|
84
|
+
|
85
|
+
# @!attribute trim_box
|
86
|
+
# @return [MuPDFBox]
|
87
|
+
attr_accessor :trim_box
|
88
|
+
|
89
|
+
# @!attribute pagenum
|
90
|
+
# @return [Integer]
|
91
|
+
attr_accessor :pagenum
|
92
|
+
|
93
|
+
# @param media_box [MuPDF::Box]
|
94
|
+
# @param crop_box [MuPDF::Box]
|
95
|
+
# @param art_box [MuPDF::Box]
|
96
|
+
# @param bleed_box [MuPDF::Box]
|
97
|
+
# @param trim_box [MuPDF::Box]
|
98
|
+
# @param number [Integer]
|
99
|
+
def initialize(media_box:, crop_box:, art_box:, bleed_box:, trim_box:, number:)
|
100
|
+
@media_box = media_box
|
101
|
+
@crop_box = crop_box
|
102
|
+
@art_box = art_box
|
103
|
+
@bleed_box = bleed_box
|
104
|
+
@trim_box = trim_box
|
105
|
+
@number = number
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [String]
|
109
|
+
def inspect
|
110
|
+
"#<#{self.class.name} number=#{@number}>"
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [Integer]
|
114
|
+
def width
|
115
|
+
@media_box.width
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [Integer]
|
119
|
+
def height
|
120
|
+
@media_box.height
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/lib/mupdf/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mupdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-01-
|
11
|
+
date: 2025-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: open3
|
@@ -50,9 +50,11 @@ files:
|
|
50
50
|
- bin/console
|
51
51
|
- bin/setup
|
52
52
|
- lib/mupdf.rb
|
53
|
+
- lib/mupdf/box.rb
|
53
54
|
- lib/mupdf/command_error.rb
|
54
55
|
- lib/mupdf/document.rb
|
55
56
|
- lib/mupdf/info.rb
|
57
|
+
- lib/mupdf/page.rb
|
56
58
|
- lib/mupdf/version.rb
|
57
59
|
homepage: https://github.com/ksylvest/mupdf
|
58
60
|
licenses:
|
@@ -60,8 +62,8 @@ licenses:
|
|
60
62
|
metadata:
|
61
63
|
rubygems_mfa_required: 'true'
|
62
64
|
homepage_uri: https://github.com/ksylvest/mupdf
|
63
|
-
source_code_uri: https://github.com/ksylvest/mupdf/tree/
|
64
|
-
changelog_uri: https://github.com/ksylvest/mupdf/releases/tag/
|
65
|
+
source_code_uri: https://github.com/ksylvest/mupdf/tree/v1.0.0
|
66
|
+
changelog_uri: https://github.com/ksylvest/mupdf/releases/tag/v1.0.0
|
65
67
|
documentation_uri: https://mupdf.ksylvest.com/
|
66
68
|
post_install_message:
|
67
69
|
rdoc_options: []
|