oil 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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