oil 0.1.3 → 0.2.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.
@@ -1,46 +1,119 @@
1
+ /**
2
+ * Copyright (c) 2014-2016 Timothy Elliott
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ * THE SOFTWARE.
20
+ */
21
+
1
22
  #ifndef RESAMPLE_H
2
23
  #define RESAMPLE_H
3
24
 
4
- #define OIL_FILLER 1
25
+ #include <stdint.h>
26
+ #include <stddef.h>
27
+
28
+ enum oil_colorspace {
29
+ OIL_CS_G = 0x0001,
30
+ OIL_CS_GA = 0x0002,
31
+ OIL_CS_RGB = 0x0003,
32
+ OIL_CS_RGBX = 0x0004,
33
+ OIL_CS_RGBA = 0x0104,
34
+ OIL_CS_CMYK = 0x0204,
35
+ };
36
+ #define CS_TO_CMP(x) (x&0xFF)
37
+
38
+ struct sl_rbuf {
39
+ uint32_t height; // number of scanlines that the ring buffer can hold
40
+ size_t length; // width in bytes of each scanline in the buffer
41
+ uint32_t count; // total no. of scanlines that have been fed in
42
+ uint16_t *buf; // buffer for the ring buffer
43
+ uint16_t **virt; // space to provide scanline pointers for scaling
44
+ };
5
45
 
6
46
  /**
7
- * Scale scanline in to the scanline out.
47
+ * Struct to hold state for y-scaling.
8
48
  */
9
- void xscale(unsigned char *in, long in_width, unsigned char *out,
10
- long out_width, int cmp, int opts);
49
+ struct yscaler {
50
+ struct sl_rbuf rb; // ring buffer holding scanlines.
51
+ uint32_t in_height; // input image height.
52
+ uint32_t out_height; // output image height.
53
+ uint32_t width;
54
+ enum oil_colorspace cs;
55
+ uint32_t target; // where the ring buffer should be on next scaling.
56
+ float ty; // sub-pixel offset for next scaling.
57
+ };
11
58
 
12
59
  /**
13
- * Indicate how many taps will be required to scale an image. The number of taps
14
- * required indicates how tall a strip needs to be.
60
+ * Initialize a yscaler struct. Calculates how large the scanline ring buffer
61
+ * will need to be and allocates it.
15
62
  */
16
- long calc_taps(long dim_in, long dim_out);
63
+ int yscaler_init(struct yscaler *ys, uint32_t in_height, uint32_t out_height,
64
+ uint32_t width, enum oil_colorspace cs);
17
65
 
18
66
  /**
19
- * Given input & output dimensions and an output position, return the
20
- * corresponding input position and put the sub-pixel remainder in rest.
67
+ * Free a yscaler struct, including the ring buffer.
21
68
  */
22
- long split_map(unsigned long dim_in, unsigned long dim_out, unsigned long pos,
23
- float *rest);
69
+ void yscaler_free(struct yscaler *ys);
24
70
 
25
71
  /**
26
- * Scale a strip. The height parameter indicates the height of the strip, not
27
- * the height of the image.
28
- *
29
- * The strip_height parameter indicates how many scanlines we are passing in. It
30
- * must be a multiple of 4.
31
- *
32
- * The in parameter points to an array of scanlines, each with width samples in
33
- * sample_fmt format. There must be at least strip_height scanlines in the
34
- * array.
35
- *
36
- * The ty parameter indicates how far our mapped sampling position is from the
37
- * center of the strip.
72
+ * Get a pointer to the next scanline to be filled in the ring buffer. Returns
73
+ * null if no more scanlines are needed to perform scaling.
74
+ */
75
+ uint16_t *yscaler_next(struct yscaler *ys);
76
+
77
+ /**
78
+ * Scale the buffered contents of the yscaler to produce the next scaled output
79
+ * scanline.
38
80
  *
39
- * Note that all scanlines in the strip must be populated, even when this
40
- * requires scanlines that are less than 0 or larger than the height of the
41
- * source image.
81
+ * Scaled scanline will be written to the out parameter.
82
+ * The width parameter is the nuber of samples in each scanline.
83
+ * The cmp parameter is the number of components per sample (3 for RGB).
84
+ * The pos parameter is the position of the output scanline.
85
+ */
86
+ int yscaler_scale(struct yscaler *ys, uint8_t *out, uint32_t pos);
87
+
88
+ /**
89
+ * Struct to hold state for x-scaling.
90
+ */
91
+ struct xscaler {
92
+ uint16_t *psl_buf;
93
+ uint16_t *psl_pos0;
94
+ size_t psl_offset;
95
+ uint32_t width_in;
96
+ uint32_t width_out;
97
+ enum oil_colorspace cs;
98
+ };
99
+
100
+ struct preprocess_xscaler {
101
+ struct xscaler xs;
102
+ uint32_t width_in;
103
+ enum oil_colorspace cs_in;
104
+ uint32_t scale_factor;
105
+ };
106
+
107
+ int preprocess_xscaler_init(struct preprocess_xscaler *pxs, uint32_t width_in,
108
+ uint32_t width_out, enum oil_colorspace cs_in);
109
+ void preprocess_xscaler_scale(struct preprocess_xscaler *pxs, uint8_t *in,
110
+ uint16_t *out);
111
+ void preprocess_xscaler_free(struct preprocess_xscaler *pxs);
112
+
113
+ /**
114
+ * Utility helpers.
42
115
  */
43
- void strip_scale(void **in, long strip_height, long width, void *out, float ty,
44
- int cmp, int opts);
116
+ void fix_ratio(uint32_t src_width, uint32_t src_height, uint32_t *out_width,
117
+ uint32_t *out_height);
45
118
 
46
119
  #endif
data/lib/oil.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Oil
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
 
4
4
  def self.sniff_signature(io)
5
5
  a = io.getc
@@ -27,30 +27,6 @@ module Oil
27
27
 
28
28
  private
29
29
 
30
- def self.fix_ratio(sw, sh, boxw, boxh)
31
- x = boxw / sw.to_f
32
- y = boxh / sh.to_f
33
-
34
- destw = boxw
35
- desth = boxh
36
-
37
- if x < y
38
- desth = (sh * x).round
39
- else
40
- destw = (sw * y).round
41
- end
42
-
43
- if desth < 1
44
- desth = 1
45
- end
46
-
47
- if destw < 1
48
- destw = 1
49
- end
50
-
51
- return destw, desth
52
- end
53
-
54
30
  def self.new_jpeg_reader(io, box_width, box_height)
55
31
  o = JPEGReader.new(io, [:COM, :APP1, :APP2])
56
32
 
@@ -60,20 +36,7 @@ module Oil
60
36
  end
61
37
 
62
38
  # JPEG Pre-scaling is equivalent to a box filter at an integer scale factor.
63
- # We don't use this to scale down past 4x the target image size in order to
64
- # get proper bicubic scaling in the final image.
65
- inv_scale = o.image_width / box_width
66
- inv_scale /= 4
67
-
68
- if inv_scale >= 8
69
- o.scale_denom = 8
70
- elsif inv_scale >= 4
71
- o.scale_denom = 4
72
- elsif inv_scale >= 2
73
- o.scale_denom = 2
74
- end
75
-
76
- destw, desth = self.fix_ratio(o.output_width, o.output_height, box_width, box_height)
39
+ destw, desth = Oil.fix_ratio(o.output_width, o.output_height, box_width, box_height)
77
40
  o.scale_width = destw
78
41
  o.scale_height = desth
79
42
 
@@ -42,7 +42,6 @@ class TestPNG < MiniTest::Test
42
42
  def test_bogus_end_chunk
43
43
  str = PNG_DATA.dup
44
44
  str[-6] = "\x10"
45
- io = StringIO.new(str)
46
45
  o = Oil::PNGReader.new(png_io)
47
46
  assert_equal 1, o.width
48
47
  assert_equal 1, o.height
@@ -134,7 +133,7 @@ class TestPNG < MiniTest::Test
134
133
  def test_each_shrinks_buffer
135
134
  Oil::PNGReader.new(png_io).each { |d| d.slice!(0, 4) }
136
135
  end
137
-
136
+
138
137
  def test_each_enlarges_buffer
139
138
  Oil::PNGReader.new(png_io).each { |d| d << "foobar" }
140
139
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timothy Elliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-10 00:00:00.000000000 Z
11
+ date: 2018-03-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Resize JPEG and PNG images, aiming for fast performance and low memory
14
14
  use.
@@ -28,8 +28,6 @@ files:
28
28
  - ext/oil/png.c
29
29
  - ext/oil/resample.c
30
30
  - ext/oil/resample.h
31
- - ext/oil/yscaler.c
32
- - ext/oil/yscaler.h
33
31
  - lib/oil.rb
34
32
  - test/helper.rb
35
33
  - test/test_jpeg.rb
@@ -54,7 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
52
  version: '0'
55
53
  requirements: []
56
54
  rubyforge_project:
57
- rubygems_version: 2.4.5
55
+ rubygems_version: 2.7.6
58
56
  signing_key:
59
57
  specification_version: 4
60
58
  summary: Resize JPEG and PNG images.
@@ -1,167 +0,0 @@
1
- #include "yscaler.h"
2
- #include "resample.h"
3
- #include <stdlib.h>
4
- #include <stdint.h>
5
-
6
- /**
7
- * Initializes a strip of height scanlines.
8
- *
9
- * Scanlines are allocated with a size of len bytes.
10
- */
11
- static void strip_init(struct strip *st, uint32_t height, size_t buflen)
12
- {
13
- uint32_t i;
14
-
15
- st->height = height;
16
- st->rr = 0;
17
- st->sl = malloc(height * sizeof(uint8_t *));
18
- st->virt = malloc(height * sizeof(uint8_t *));
19
- for (i=0; i<height; i++) {
20
- st->sl[i] = malloc(buflen);
21
- st->virt[i] = st->sl[0];
22
- }
23
- }
24
-
25
- /**
26
- * Frees memory allocated at initialization.
27
- */
28
- static void strip_free(struct strip *st)
29
- {
30
- uint32_t i;
31
-
32
- for (i=0; i<st->height; i++) {
33
- free(st->sl[i]);
34
- }
35
- free(st->sl);
36
- free(st->virt);
37
- }
38
-
39
- /**
40
- * Shifts the virtual scanline pointers downwards by one.
41
- *
42
- * The bottmomost virtual scanline pointer is left untouched since we may have
43
- * reached the end of the source image and we may want to leave it pointing at
44
- * the bottom.
45
- *
46
- * If we have not reached the bottom of the source image this call should be
47
- * followed up by strip_bottom_shift() to complete the strip shift.
48
- */
49
- static void strip_top_shift(struct strip *st)
50
- {
51
- uint32_t i;
52
- for (i=1; i<st->height; i++) {
53
- st->virt[i - 1] = st->virt[i];
54
- }
55
- }
56
-
57
- /**
58
- * Points the bottommost virtual scanline to the next allocated scanline,
59
- * discarding the topmost scanline.
60
- *
61
- * The caller is expected to fill the bottom virtual scanline with image data
62
- * after this call.
63
- */
64
- static void strip_bottom_shift(struct strip *st)
65
- {
66
- st->rr = (st->rr + 1) % st->height;
67
- st->virt[st->height - 1] = st->sl[st->rr];
68
- }
69
-
70
- /**
71
- * Returns a pointer to the bottommost virtual scanline.
72
- */
73
- static void *strip_bottom(struct strip *st)
74
- {
75
- return st->virt[st->height - 1];
76
- }
77
-
78
- static void yscaler_map_pos(struct yscaler *ys)
79
- {
80
- uint32_t target;
81
- target = split_map(ys->in_height, ys->out_height, ys->out_pos, &ys->ty);
82
- ys->in_target = target + ys->strip.height / 2 + 1;
83
- }
84
-
85
- void yscaler_init(struct yscaler *ys, uint32_t in_height, uint32_t out_height,
86
- uint32_t buflen)
87
- {
88
- uint32_t taps;
89
-
90
- ys->in_height = in_height;
91
- ys->out_height = out_height;
92
- ys->in_pos = 0;
93
- ys->out_pos = 0;
94
-
95
- taps = calc_taps(in_height, out_height);
96
- strip_init(&ys->strip, taps, buflen);
97
- yscaler_map_pos(ys);
98
- }
99
-
100
- void yscaler_free(struct yscaler *ys)
101
- {
102
- strip_free(&ys->strip);
103
- }
104
-
105
- unsigned char *yscaler_next(struct yscaler *ys)
106
- {
107
- struct strip *st;
108
-
109
- st = &ys->strip;
110
-
111
- /* We need the first scanline for top padding. */
112
- if (ys->in_pos == 0) {
113
- ys->in_pos++;
114
- return strip_bottom(st);
115
- }
116
-
117
- while (ys->in_pos < ys->in_target) {
118
- ys->in_pos++;
119
- strip_top_shift(&ys->strip);
120
- if (ys->in_pos <= ys->in_height) {
121
- strip_bottom_shift(st);
122
- return strip_bottom(st);
123
- }
124
- }
125
-
126
- return 0;
127
- }
128
-
129
- void yscaler_scale(struct yscaler *ys, uint8_t *out, uint32_t width,
130
- uint8_t cmp, uint8_t opts)
131
- {
132
- struct strip *st;
133
-
134
- st = &ys->strip;
135
- strip_scale((void **)st->virt, st->height, width, (void *)out, ys->ty,
136
- cmp, opts);
137
- ys->out_pos++;
138
- yscaler_map_pos(ys);
139
- }
140
-
141
- void yscaler_prealloc_scale(uint32_t in_height, uint32_t out_height,
142
- uint8_t **in, uint8_t *out, uint32_t pos, uint32_t width, uint8_t cmp,
143
- uint8_t opts)
144
- {
145
- uint32_t i, taps;
146
- int32_t smp_i, strip_pos;
147
- uint8_t **virt;
148
- float ty;
149
-
150
- taps = calc_taps(in_height, out_height);
151
- virt = malloc(taps * sizeof(uint8_t *));
152
- smp_i = split_map(in_height, out_height, pos, &ty);
153
- strip_pos = smp_i + 1 - taps / 2;
154
-
155
- for (i=0; i<taps; i++) {
156
- if (strip_pos < 0) {
157
- virt[i] = in[0];
158
- } else if ((uint32_t)strip_pos > in_height - 1) {
159
- virt[i] = in[in_height - 1];
160
- } else {
161
- virt[i] = in[strip_pos];
162
- }
163
- strip_pos++;
164
- }
165
-
166
- strip_scale((void **)virt, taps, width, (void *)out, ty, cmp, opts);
167
- }
@@ -1,33 +0,0 @@
1
- #ifndef YSCALER_H
2
- #define YSCALER_H
3
-
4
- #include <stdint.h>
5
-
6
- struct strip {
7
- uint32_t height;
8
- uint8_t **sl;
9
- uint8_t **virt;
10
- uint32_t rr;
11
- };
12
-
13
- struct yscaler {
14
- uint32_t in_height;
15
- uint32_t out_height;
16
- struct strip strip;
17
- uint32_t in_pos;
18
- uint32_t out_pos;
19
- uint32_t in_target;
20
- float ty;
21
- };
22
-
23
- void yscaler_init(struct yscaler *ys, uint32_t in_height, uint32_t out_height,
24
- uint32_t buflen);
25
- void yscaler_free(struct yscaler *ys);
26
- unsigned char *yscaler_next(struct yscaler *ys);
27
- void yscaler_scale(struct yscaler *ys, uint8_t *out, uint32_t width,
28
- uint8_t cmp, uint8_t opts);
29
- void yscaler_prealloc_scale(uint32_t in_height, uint32_t out_height,
30
- uint8_t **in, uint8_t *out, uint32_t pos, uint32_t width, uint8_t cmp,
31
- uint8_t opts);
32
-
33
- #endif