oily_png 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +4 -4
  3. data/ext/oily_png/oily_png_ext.c +18 -2
  4. data/ext/oily_png/oily_png_ext.h +22 -2
  5. data/ext/oily_png/png_decoding.c +242 -71
  6. data/ext/oily_png/png_decoding.h +4 -1
  7. data/ext/oily_png/png_encoding.c +24 -23
  8. data/lib/oily_png.rb +1 -1
  9. data/oily_png.gemspec +4 -4
  10. data/spec/decoding_spec.rb +15 -42
  11. data/spec/encoding_spec.rb +3 -3
  12. data/spec/resources/basi0g01.png +0 -0
  13. data/spec/resources/basi0g02.png +0 -0
  14. data/spec/resources/basi0g04.png +0 -0
  15. data/spec/resources/basi0g08.png +0 -0
  16. data/spec/resources/basi0g16.png +0 -0
  17. data/spec/resources/basi2c08.png +0 -0
  18. data/spec/resources/basi2c16.png +0 -0
  19. data/spec/resources/basi3p01.png +0 -0
  20. data/spec/resources/basi3p02.png +0 -0
  21. data/spec/resources/basi3p04.png +0 -0
  22. data/spec/resources/basi3p08.png +0 -0
  23. data/spec/resources/basi4a08.png +0 -0
  24. data/spec/resources/basi4a16.png +0 -0
  25. data/spec/resources/basi6a08.png +0 -0
  26. data/spec/resources/basi6a16.png +0 -0
  27. data/spec/resources/basn0g01.png +0 -0
  28. data/spec/resources/basn0g02.png +0 -0
  29. data/spec/resources/basn0g04.png +0 -0
  30. data/spec/resources/basn0g08.png +0 -0
  31. data/spec/resources/basn0g16.png +0 -0
  32. data/spec/resources/basn2c08.png +0 -0
  33. data/spec/resources/basn2c16.png +0 -0
  34. data/spec/resources/basn3p01.png +0 -0
  35. data/spec/resources/basn3p02.png +0 -0
  36. data/spec/resources/basn3p04.png +0 -0
  37. data/spec/resources/basn3p08.png +0 -0
  38. data/spec/resources/basn4a08.png +0 -0
  39. data/spec/resources/basn4a16.png +0 -0
  40. data/spec/resources/basn6a08.png +0 -0
  41. data/spec/resources/basn6a16.png +0 -0
  42. data/spec/resources/s01i3p01.png +0 -0
  43. data/spec/resources/s01n3p01.png +0 -0
  44. data/spec/resources/s02i3p01.png +0 -0
  45. data/spec/resources/s02n3p01.png +0 -0
  46. data/spec/resources/s03i3p01.png +0 -0
  47. data/spec/resources/s03n3p01.png +0 -0
  48. data/spec/resources/s04i3p01.png +0 -0
  49. data/spec/resources/s04n3p01.png +0 -0
  50. data/spec/resources/s05i3p02.png +0 -0
  51. data/spec/resources/s05n3p02.png +0 -0
  52. data/spec/resources/s06i3p02.png +0 -0
  53. data/spec/resources/s06n3p02.png +0 -0
  54. data/spec/resources/s07i3p02.png +0 -0
  55. data/spec/resources/s07n3p02.png +0 -0
  56. data/spec/resources/s08i3p02.png +0 -0
  57. data/spec/resources/s08n3p02.png +0 -0
  58. data/spec/resources/s09i3p02.png +0 -0
  59. data/spec/resources/s09n3p02.png +0 -0
  60. data/spec/resources/s32i3p04.png +0 -0
  61. data/spec/resources/s32n3p04.png +0 -0
  62. data/spec/resources/s33i3p04.png +0 -0
  63. data/spec/resources/s33n3p04.png +0 -0
  64. data/spec/resources/s34i3p04.png +0 -0
  65. data/spec/resources/s34n3p04.png +0 -0
  66. data/spec/resources/s35i3p04.png +0 -0
  67. data/spec/resources/s35n3p04.png +0 -0
  68. data/spec/resources/s36i3p04.png +0 -0
  69. data/spec/resources/s36n3p04.png +0 -0
  70. data/spec/resources/s37i3p04.png +0 -0
  71. data/spec/resources/s37n3p04.png +0 -0
  72. data/spec/resources/s38i3p04.png +0 -0
  73. data/spec/resources/s38n3p04.png +0 -0
  74. data/spec/resources/s39i3p04.png +0 -0
  75. data/spec/resources/s39n3p04.png +0 -0
  76. data/spec/resources/s40i3p04.png +0 -0
  77. data/spec/resources/s40n3p04.png +0 -0
  78. data/spec/spec_helper.rb +10 -3
  79. metadata +83 -22
data/Gemfile CHANGED
@@ -1,2 +1,10 @@
1
1
  source :rubyforge
2
2
  gemspec
3
+
4
+ # # Use the following gem specification instead of the 'gemspec' statement
5
+ # # to develop with a local chunky_png copy
6
+
7
+ # gem 'chunky_png', :path => File.expand_path('../chunky_png', File.dirname(__FILE__))
8
+ # gem 'oily_png', :path => File.dirname(__FILE__)
9
+ # gem 'rake'
10
+ # gem 'rspec'
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oily_png (0.1.1)
5
- chunky_png (~> 0.10.4)
4
+ oily_png (0.2.0)
5
+ chunky_png (~> 0.11)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
9
9
  specs:
10
- chunky_png (0.10.4)
10
+ chunky_png (0.11.0)
11
11
  diff-lcs (1.1.2)
12
12
  rake (0.8.7)
13
13
  rspec (2.0.0)
@@ -25,7 +25,7 @@ PLATFORMS
25
25
  ruby
26
26
 
27
27
  DEPENDENCIES
28
- chunky_png (~> 0.10.4)
28
+ chunky_png (~> 0.11)
29
29
  oily_png!
30
30
  rake
31
31
  rspec (~> 2.0)
@@ -5,14 +5,14 @@ void Init_oily_png_ext() {
5
5
 
6
6
  // Setup decoding
7
7
  VALUE OilyPNG_PNGDecoding = rb_define_module_under(OilyPNG, "PNGDecoding");
8
- rb_define_method(OilyPNG_PNGDecoding, "decode_png_image_pass", oily_png_decode_png_image_pass, 5);
8
+ rb_define_method(OilyPNG_PNGDecoding, "decode_png_image_pass", oily_png_decode_png_image_pass, 6);
9
9
 
10
10
  // Setup encoding
11
11
  VALUE OilyPNG_PNGEncoding = rb_define_module_under(OilyPNG, "PNGEncoding");
12
12
  rb_define_method(OilyPNG_PNGEncoding, "encode_png_image_pass_to_stream", oily_png_encode_png_image_pass_to_stream, 3);
13
13
  }
14
14
 
15
- int oily_png_pixel_size(int color_mode) {
15
+ char oily_png_samples_per_pixel(char color_mode) {
16
16
  switch (color_mode) {
17
17
  case OILY_PNG_COLOR_GRAYSCALE: return 1;
18
18
  case OILY_PNG_COLOR_TRUECOLOR: return 3;
@@ -22,3 +22,19 @@ int oily_png_pixel_size(int color_mode) {
22
22
  default: rb_raise(rb_eRuntimeError, "Unsupported color mode: %d", color_mode);
23
23
  }
24
24
  }
25
+
26
+ char oily_png_pixel_bitsize(char color_mode, char bit_depth) {
27
+ return oily_png_samples_per_pixel(color_mode) * bit_depth;
28
+ }
29
+
30
+ char oily_png_pixel_bytesize(char color_mode, char bit_depth) {
31
+ return (bit_depth < 8) ? 1 : (oily_png_pixel_bitsize(color_mode, bit_depth) + 7) >> 3;
32
+ }
33
+
34
+ long oily_png_scanline_bytesize(char color_mode, char bit_depth, long width) {
35
+ return (8 + ((oily_png_pixel_bitsize(color_mode, bit_depth) * width) + 7)) >> 3;
36
+ }
37
+
38
+ long oily_png_pass_bytesize(char color_mode, char bit_depth, long width, long height) {
39
+ return (width == 0 || height == 0) ? 0 : (oily_png_scanline_bytesize(color_mode, bit_depth, width)) * height;
40
+ }
@@ -37,8 +37,28 @@
37
37
  void Init_oily_png_ext();
38
38
 
39
39
  /*
40
- Returns the number of bytes per pixel for a given color mode.
40
+ Returns the number of samples per pixel for a given color mode
41
41
  */
42
- int oily_png_pixel_size(int color_mode);
42
+ char oily_png_samples_per_pixel(char color_mode);
43
+
44
+ /*
45
+ Returns the number of bits per pixel for a given color mode and bit depth.
46
+ */
47
+ char oily_png_pixel_bitsize(char color_mode, char bit_depth);
48
+
49
+ /*
50
+ Returns the number of bytes per pixel for a given color mode and bit depth.
51
+ */
52
+ char oily_png_pixel_bytesize(char color_mode, char bit_depth);
53
+
54
+ /*
55
+ Returns the number of bytes per scanline for a given width, color mode and bit depth.
56
+ */
57
+ long oily_png_scanline_bytesize(char color_mode, char bit_depth, long width);
58
+
59
+ /*
60
+ Returns the number of bytes in an image pass with the given properties.
61
+ */
62
+ long oily_png_pass_bytesize(char color_mode, char bit_depth, long width, long height);
43
63
 
44
64
  #endif
@@ -2,16 +2,16 @@
2
2
 
3
3
 
4
4
  // Decodes a SUB filtered scanline at the given position in the byte array
5
- void oily_png_decode_filter_sub(BYTE* bytes, int pos, int line_length, int pixel_size) {
6
- int i;
5
+ void oily_png_decode_filter_sub(BYTE* bytes, long pos, long line_length, char pixel_size) {
6
+ long i;
7
7
  for (i = 1 + pixel_size; i < line_length; i++) {
8
8
  UNFILTER_BYTE(bytes[pos + i], bytes[pos + i - pixel_size]);
9
9
  }
10
10
  }
11
11
 
12
12
  // Decodes an UP filtered scanline at the given position in the byte array
13
- void oily_png_decode_filter_up(BYTE* bytes, int pos, int line_size, int pixel_size) {
14
- int i;
13
+ void oily_png_decode_filter_up(BYTE* bytes, long pos, long line_size, char pixel_size) {
14
+ long i;
15
15
  // The first line is not filtered because there is no privous line
16
16
  if (pos >= line_size) {
17
17
  for (i = 1; i < line_size; i++) {
@@ -21,8 +21,8 @@ void oily_png_decode_filter_up(BYTE* bytes, int pos, int line_size, int pixel_si
21
21
  }
22
22
 
23
23
  // Decodes an AVERAGE filtered scanline at the given position in the byte array
24
- void oily_png_decode_filter_average(BYTE* bytes, int pos, int line_size, int pixel_size) {
25
- int i;
24
+ void oily_png_decode_filter_average(BYTE* bytes, long pos, long line_size, char pixel_size) {
25
+ long i;
26
26
  BYTE a, b;
27
27
  for (i = 1; i < line_size; i++) {
28
28
  a = (i > pixel_size) ? bytes[pos + i - pixel_size] : 0;
@@ -32,103 +32,274 @@ void oily_png_decode_filter_average(BYTE* bytes, int pos, int line_size, int pix
32
32
  }
33
33
 
34
34
  // Decodes a PAETH filtered scanline at the given position in the byte array
35
- void oily_png_decode_filter_paeth(BYTE* bytes, int pos, int line_size, int pixel_size) {
35
+ void oily_png_decode_filter_paeth(BYTE* bytes, long pos, long line_size, char pixel_size) {
36
36
  BYTE a, b, c, pr;
37
- int i, p, pa, pb, pc;
37
+ long i, p, pa, pb, pc;
38
38
  for (i = 1; i < line_size; i++) {
39
39
  a = (i > pixel_size) ? bytes[pos + i - pixel_size] : 0;
40
40
  b = (pos >= line_size) ? bytes[pos + i - line_size] : 0;
41
41
  c = (pos >= line_size && i > pixel_size) ? bytes[pos + i - line_size - pixel_size] : 0;
42
42
  p = a + b - c;
43
- pa = abs(p - a);
44
- pb = abs(p - b);
45
- pc = abs(p - c);
43
+ pa = (p > a) ? p - a : a - p;
44
+ pb = (p > b) ? p - b : b - p;
45
+ pc = (p > c) ? p - c : c - p;
46
46
  pr = (pa <= pb) ? (pa <= pc ? a : c) : (pb <= pc ? b : c);
47
47
  UNFILTER_BYTE(bytes[pos + i], pr);
48
48
  }
49
49
  }
50
50
 
51
- PIXEL oily_png_decode_pixel_grayscale(int color_mode, BYTE* bytes, int byte_index, VALUE decoding_palette) {
52
- return BUILD_PIXEL(bytes[byte_index], bytes[byte_index], bytes[byte_index], 0xff);
51
+ BYTE oily_png_extract_1bit_element(BYTE* bytes, long start, long x) {
52
+ BYTE byte = bytes[start + 1 + (x >> 3)];
53
+ char bitshift = 7 - (x & (BYTE) 0x07);
54
+ return (byte & (0x01 << bitshift)) >> bitshift;
53
55
  }
54
56
 
55
- PIXEL oily_png_decode_pixel_truecolor(int color_mode, BYTE* bytes, int byte_index, VALUE decoding_palette) {
56
- return BUILD_PIXEL(bytes[byte_index], bytes[byte_index + 1], bytes[byte_index + 2], 0xff);
57
+
58
+ BYTE oily_png_extract_2bit_element(BYTE* bytes, long start, long x) {
59
+ BYTE byte = bytes[start + 1 + (x >> 2)];
60
+ char bitshift = (6 - ((x & (BYTE) 0x03) << 1));
61
+ return (byte & (0x03 << bitshift)) >> bitshift;
57
62
  }
58
63
 
59
- PIXEL oily_png_decode_pixel_indexed(int color_mode, BYTE* bytes, int byte_index, VALUE decoding_palette) {
60
- return (PIXEL) NUM2UINT(rb_funcall(decoding_palette, rb_intern("[]"), 1, INT2FIX(bytes[byte_index])));
64
+ BYTE oily_png_extract_4bit_element(BYTE* bytes, long start, long x) {
65
+ return ((x & 0x01) == 0) ? ((bytes[(start) + 1 + ((x) >> 1)] & (BYTE) 0xf0) >> 4) : (bytes[(start) + 1 + ((x) >> 1)] & (BYTE) 0x0f);
61
66
  }
62
67
 
63
- PIXEL oily_png_decode_pixel_grayscale_alpha(int color_mode, BYTE* bytes, int byte_index, VALUE decoding_palette) {
64
- return BUILD_PIXEL(bytes[byte_index], bytes[byte_index], bytes[byte_index], bytes[byte_index + 1]);
68
+ BYTE oily_png_resample_1bit_element(BYTE* bytes, long start, long x) {
69
+ BYTE value = oily_png_extract_1bit_element(bytes, start, x);
70
+ return (value == 0) ? 0x00 : 0xff;
65
71
  }
66
72
 
67
- PIXEL oily_png_decode_pixel_truecolor_alpha(int color_mode, BYTE* bytes, int byte_index, VALUE decoding_palette) {
68
- return BUILD_PIXEL(bytes[byte_index], bytes[byte_index + 1], bytes[byte_index + 2], bytes[byte_index + 3]);
73
+ BYTE oily_png_resample_2bit_element(BYTE* bytes, long start, long x) {
74
+ switch (oily_png_extract_2bit_element(bytes, start, x)) {
75
+ case 0x00: return 0x00;
76
+ case 0x01: return 0x55;
77
+ case 0x02: return 0xaa;
78
+ case 0x03: default: return 0xff;
79
+ }
69
80
  }
70
81
 
71
- VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALUE height, VALUE color_mode, VALUE start_pos) {
72
-
73
- int pixel_size = oily_png_pixel_size(FIX2INT(color_mode));
74
- int line_size = pixel_size * FIX2INT(width) + 1;
75
- int pass_size = line_size * FIX2INT(height);
82
+ BYTE oily_png_resample_4bit_element(BYTE* bytes, long start, long x) {
83
+ switch(oily_png_extract_4bit_element(bytes, start, x)) {
84
+ case 0x00: return 0;
85
+ case 0x01: return 17;
86
+ case 0x02: return 34;
87
+ case 0x03: return 51;
88
+ case 0x04: return 68;
89
+ case 0x05: return 85;
90
+ case 0x06: return 102;
91
+ case 0x07: return 119;
92
+ case 0x08: return 137;
93
+ case 0x09: return 154;
94
+ case 0x0a: return 171;
95
+ case 0x0b: return 188;
96
+ case 0x0c: return 205;
97
+ case 0x0d: return 222;
98
+ case 0x0e: return 239;
99
+ case 0x0f: default: return 255;
100
+ }
101
+ }
102
+
103
+
104
+ PIXEL oily_png_decode_pixel_indexed_8bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
105
+ return (PIXEL) NUM2UINT(rb_funcall(decoding_palette, rb_intern("[]"), 1, INT2FIX(bytes[start + 1 + x])));
106
+ }
107
+
108
+ PIXEL oily_png_decode_pixel_indexed_4bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
109
+ return (PIXEL) NUM2UINT(rb_funcall(decoding_palette, rb_intern("[]"), 1, INT2FIX(oily_png_extract_4bit_element(bytes, start, x))));
110
+ }
111
+
112
+ PIXEL oily_png_decode_pixel_indexed_2bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
113
+ return (PIXEL) NUM2UINT(rb_funcall(decoding_palette, rb_intern("[]"), 1, INT2FIX(oily_png_extract_2bit_element(bytes, start, x))));
114
+ }
115
+
116
+ PIXEL oily_png_decode_pixel_indexed_1bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
117
+ return (PIXEL) NUM2UINT(rb_funcall(decoding_palette, rb_intern("[]"), 1, INT2FIX(oily_png_extract_1bit_element(bytes, start, x))));
118
+ }
119
+
120
+
121
+ PIXEL oily_png_decode_pixel_grayscale_8bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
122
+ return BUILD_PIXEL( bytes[start + 1 + x],
123
+ bytes[start + 1 + x],
124
+ bytes[start + 1 + x],
125
+ 0xff);
126
+ }
127
+
128
+ PIXEL oily_png_decode_pixel_grayscale_1bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
129
+ return BUILD_PIXEL( oily_png_resample_1bit_element(bytes, start, x),
130
+ oily_png_resample_1bit_element(bytes, start, x),
131
+ oily_png_resample_1bit_element(bytes, start, x),
132
+ 0xff);
133
+ }
134
+
135
+ PIXEL oily_png_decode_pixel_grayscale_2bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
136
+ return BUILD_PIXEL( oily_png_resample_2bit_element(bytes, start, x),
137
+ oily_png_resample_2bit_element(bytes, start, x),
138
+ oily_png_resample_2bit_element(bytes, start, x),
139
+ 0xff);
140
+ }
141
+
142
+ PIXEL oily_png_decode_pixel_grayscale_4bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
143
+ return BUILD_PIXEL( oily_png_resample_4bit_element(bytes, start, x),
144
+ oily_png_resample_4bit_element(bytes, start, x),
145
+ oily_png_resample_4bit_element(bytes, start, x),
146
+ 0xff);
147
+ }
148
+
149
+ PIXEL oily_png_decode_pixel_truecolor_8bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
150
+ return BUILD_PIXEL( bytes[start + 1 + (x * 3) + 0],
151
+ bytes[start + 1 + (x * 3) + 1],
152
+ bytes[start + 1 + (x * 3) + 2],
153
+ 0xff);
154
+ }
155
+
156
+ PIXEL oily_png_decode_pixel_grayscale_alpha_8bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
157
+ return BUILD_PIXEL( bytes[start + 1 + (x * 2) + 0],
158
+ bytes[start + 1 + (x * 2) + 0],
159
+ bytes[start + 1 + (x * 2) + 0],
160
+ bytes[start + 1 + (x * 2) + 1]);
161
+ }
162
+
163
+ PIXEL oily_png_decode_pixel_truecolor_alpha_8bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
164
+ return BUILD_PIXEL( bytes[start + 1 + (x * 4) + 0],
165
+ bytes[start + 1 + (x * 4) + 1],
166
+ bytes[start + 1 + (x * 4) + 2],
167
+ bytes[start + 1 + (x * 4) + 3]);
168
+ }
169
+
170
+ PIXEL oily_png_decode_pixel_grayscale_16bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
171
+ return BUILD_PIXEL( bytes[start + 1 + (x * 2)],
172
+ bytes[start + 1 + (x * 2)],
173
+ bytes[start + 1 + (x * 2)],
174
+ 0xff);
175
+ }
176
+
177
+ PIXEL oily_png_decode_pixel_truecolor_16bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
178
+ return BUILD_PIXEL( bytes[start + 1 + (x * 6) + 0],
179
+ bytes[start + 1 + (x * 6) + 2],
180
+ bytes[start + 1 + (x * 6) + 4],
181
+ 0xff);
182
+ }
183
+
184
+ PIXEL oily_png_decode_pixel_grayscale_alpha_16bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
185
+ return BUILD_PIXEL( bytes[start + 1 + (x * 4) + 0],
186
+ bytes[start + 1 + (x * 4) + 0],
187
+ bytes[start + 1 + (x * 4) + 0],
188
+ bytes[start + 1 + (x * 4) + 2]);
189
+ }
190
+
191
+ PIXEL oily_png_decode_pixel_truecolor_alpha_16bit(BYTE* bytes, long start, long x, VALUE decoding_palette) {
192
+ return BUILD_PIXEL( bytes[start + 1 + (x * 8) + 0],
193
+ bytes[start + 1 + (x * 8) + 2],
194
+ bytes[start + 1 + (x * 8) + 4],
195
+ bytes[start + 1 + (x * 8) + 6]);
196
+ }
197
+
198
+
199
+ pixel_decoder_func oily_png_decode_pixel_func(int color_mode, int bit_depth) {
200
+ switch (color_mode) {
201
+ case OILY_PNG_COLOR_GRAYSCALE:
202
+ switch (bit_depth) {
203
+ case 1: return &oily_png_decode_pixel_grayscale_1bit;
204
+ case 2: return &oily_png_decode_pixel_grayscale_2bit;
205
+ case 4: return &oily_png_decode_pixel_grayscale_4bit;
206
+ case 8: return &oily_png_decode_pixel_grayscale_8bit;
207
+ case 16: return &oily_png_decode_pixel_grayscale_16bit;
208
+ default: return NULL;
209
+ }
210
+
211
+ case OILY_PNG_COLOR_TRUECOLOR:
212
+ switch (bit_depth) {
213
+ case 8: return &oily_png_decode_pixel_truecolor_8bit;
214
+ case 16: return &oily_png_decode_pixel_truecolor_16bit;
215
+ default: return NULL;
216
+ }
217
+
218
+ case OILY_PNG_COLOR_INDEXED:
219
+ switch (bit_depth) {
220
+ case 1: return &oily_png_decode_pixel_indexed_1bit;
221
+ case 2: return &oily_png_decode_pixel_indexed_2bit;
222
+ case 4: return &oily_png_decode_pixel_indexed_4bit;
223
+ case 8: return &oily_png_decode_pixel_indexed_8bit;
224
+ default: return NULL;
225
+ }
226
+
227
+ case OILY_PNG_COLOR_GRAYSCALE_ALPHA:
228
+ switch (bit_depth) {
229
+ case 8: return &oily_png_decode_pixel_grayscale_alpha_8bit;
230
+ case 16: return &oily_png_decode_pixel_grayscale_alpha_16bit;
231
+ default: return NULL;
232
+ }
233
+
234
+ case OILY_PNG_COLOR_TRUECOLOR_ALPHA:
235
+ switch (bit_depth) {
236
+ case 8: return &oily_png_decode_pixel_truecolor_alpha_8bit;
237
+ case 16: return &oily_png_decode_pixel_truecolor_alpha_16bit;
238
+ default: return NULL;
239
+ }
240
+
241
+ default: return NULL;
242
+ }
243
+ }
244
+
245
+ VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALUE height, VALUE color_mode, VALUE depth, VALUE start_pos) {
76
246
 
77
247
  VALUE pixels = rb_ary_new();
78
248
 
79
- // Make sure that the stream is large enough to contain out pass.
80
- if (RSTRING_LEN(stream) < pass_size + FIX2INT(start_pos)) {
81
- rb_raise(rb_eRuntimeError, "The length of the stream is too short to contain the image!");
82
- }
249
+ if ((FIX2LONG(height) > 0) && (FIX2LONG(width) > 0)) {
83
250
 
84
- // Copy the bytes for this pass from the stream to a separate location
85
- // so we can work on this byte array directly.
86
- BYTE* pixelstream = (BYTE*) RSTRING_PTR(stream);
87
- BYTE* bytes = ALLOCA_N(BYTE, pass_size);
88
- memcpy(bytes, pixelstream + FIX2INT(start_pos), pass_size);
251
+ char pixel_size = oily_png_pixel_bytesize(FIX2INT(color_mode), FIX2INT(depth));
252
+ long line_size = oily_png_scanline_bytesize(FIX2INT(color_mode), FIX2INT(depth), FIX2LONG(width));
253
+ long pass_size = oily_png_pass_bytesize(FIX2INT(color_mode), FIX2INT(depth), FIX2LONG(width), FIX2LONG(height));
254
+
255
+ // Make sure that the stream is large enough to contain our pass.
256
+ if (RSTRING_LEN(stream) < pass_size + FIX2LONG(start_pos)) {
257
+ rb_raise(rb_eRuntimeError, "The length of the stream is too short to contain the image!");
258
+ }
89
259
 
90
- // Get the decoding palette for indexed images.
91
- VALUE decoding_palette = Qnil;
92
- if (FIX2INT(color_mode) == OILY_PNG_COLOR_INDEXED) {
93
- decoding_palette = rb_funcall(self, rb_intern("decoding_palette"), 0);
94
- }
260
+ // Copy the bytes for this pass from the stream to a separate location
261
+ // so we can work on this byte array directly.
262
+ BYTE* bytes = ALLOCA_N(BYTE, pass_size);
263
+ memcpy(bytes, RSTRING_PTR(stream) + FIX2LONG(start_pos), pass_size);
95
264
 
96
- // Select the pixel decoder function for this color mode.
97
- PIXEL (*pixel_decoder)(int, BYTE*, int, VALUE) = NULL;
98
- switch (FIX2INT(color_mode)) {
99
- case OILY_PNG_COLOR_GRAYSCALE: pixel_decoder = &oily_png_decode_pixel_grayscale; break;
100
- case OILY_PNG_COLOR_TRUECOLOR: pixel_decoder = &oily_png_decode_pixel_truecolor; break;
101
- case OILY_PNG_COLOR_INDEXED: pixel_decoder = &oily_png_decode_pixel_indexed; break;
102
- case OILY_PNG_COLOR_GRAYSCALE_ALPHA: pixel_decoder = &oily_png_decode_pixel_grayscale_alpha; break;
103
- case OILY_PNG_COLOR_TRUECOLOR_ALPHA: pixel_decoder = &oily_png_decode_pixel_truecolor_alpha; break;
104
- default: rb_raise(rb_eRuntimeError, "Color mode not supported: %ld", FIX2INT(color_mode));
105
- }
265
+ // Get the decoding palette for indexed images.
266
+ VALUE decoding_palette = Qnil;
267
+ if (FIX2INT(color_mode) == OILY_PNG_COLOR_INDEXED) {
268
+ decoding_palette = rb_funcall(self, rb_intern("decoding_palette"), 0);
269
+ }
270
+
271
+ // Select the pixel decoder function for this color mode.
272
+ PIXEL (*pixel_decoder)(BYTE*, long, long, VALUE) = NULL;
273
+ pixel_decoder = oily_png_decode_pixel_func(FIX2INT(color_mode), FIX2INT(depth));
106
274
 
107
- int y, x, line_start, byte_index, pixel_index;
108
- PIXEL pixel;
275
+ if (pixel_decoder == NULL) {
276
+ rb_raise(rb_eRuntimeError, "No decoder for color mode %d and bit depth %d", FIX2INT(color_mode), FIX2INT(depth));
277
+ }
278
+
279
+ long y, x, line_start;
280
+ PIXEL pixel;
109
281
 
110
- for (y = 0; y < FIX2INT(height); y++) {
111
- line_start = y * line_size;
282
+ for (y = 0; y < FIX2LONG(height); y++) {
283
+ line_start = y * line_size;
112
284
 
113
- // Apply filering to the line
114
- switch (bytes[line_start]) {
115
- case OILY_PNG_FILTER_NONE: break;
116
- case OILY_PNG_FILTER_SUB: oily_png_decode_filter_sub( bytes, line_start, line_size, pixel_size); break;
117
- case OILY_PNG_FILTER_UP: oily_png_decode_filter_up( bytes, line_start, line_size, pixel_size); break;
118
- case OILY_PNG_FILTER_AVERAGE: oily_png_decode_filter_average( bytes, line_start, line_size, pixel_size); break;
119
- case OILY_PNG_FILTER_PAETH: oily_png_decode_filter_paeth( bytes, line_start, line_size, pixel_size); break;
120
- default: rb_raise(rb_eRuntimeError, "Filter type not supported: %d", bytes[line_start]);
121
- }
285
+ // Apply filering to the line
286
+ switch (bytes[line_start]) {
287
+ case OILY_PNG_FILTER_NONE: break;
288
+ case OILY_PNG_FILTER_SUB: oily_png_decode_filter_sub( bytes, line_start, line_size, pixel_size); break;
289
+ case OILY_PNG_FILTER_UP: oily_png_decode_filter_up( bytes, line_start, line_size, pixel_size); break;
290
+ case OILY_PNG_FILTER_AVERAGE: oily_png_decode_filter_average( bytes, line_start, line_size, pixel_size); break;
291
+ case OILY_PNG_FILTER_PAETH: oily_png_decode_filter_paeth( bytes, line_start, line_size, pixel_size); break;
292
+ default: rb_raise(rb_eRuntimeError, "Filter type not supported: %d", bytes[line_start]);
293
+ }
122
294
 
123
- // Set the filter byte to 0 because the bytearray is now unfiltered.
124
- bytes[line_start] = OILY_PNG_FILTER_NONE;
295
+ // Set the filter byte to 0 because the bytearray is now unfiltered.
296
+ bytes[line_start] = OILY_PNG_FILTER_NONE;
125
297
 
126
- // Now, iterate over all bytes in this line and combine them into pixels
127
- for (x = 0; x < FIX2INT(width); x++) {
128
- pixel_index = FIX2INT(width) * y + x;
129
- byte_index = line_start + 1 + (x * pixel_size);
130
- pixel = pixel_decoder(FIX2INT(color_mode), bytes, byte_index, decoding_palette);
131
- rb_ary_store(pixels, pixel_index, INT2NUM(pixel));
298
+ // Now, iterate over all bytes in this line and convert them into pixels
299
+ for (x = 0; x < FIX2LONG(width); x++) {
300
+ pixel = pixel_decoder(bytes, line_start, x, decoding_palette);
301
+ rb_ary_store(pixels, FIX2LONG(width) * y + x, UINT2NUM(pixel));
302
+ }
132
303
  }
133
304
  }
134
305
 
@@ -4,6 +4,9 @@
4
4
  #define BUILD_PIXEL(r, g, b, a) (((PIXEL) r << 24) + ((PIXEL) g << 16) + ((PIXEL) b << 8) + (PIXEL) a)
5
5
  #define UNFILTER_BYTE(byte, adjustment) byte = (BYTE) (((byte) + (adjustment)) & 0x000000ff)
6
6
 
7
+ typedef PIXEL(*pixel_decoder_func)(BYTE*, long, long, VALUE);
8
+
9
+
7
10
  /*
8
11
  Decodes an image pass from the given byte stream at the given position.
9
12
  A normal PNG will only have one pass that consumes the entire stream, while an
@@ -11,6 +14,6 @@
11
14
 
12
15
  This function shouild replace ChunkyPNG::Canvas::PNGDecoding.decode_png_image_pass
13
16
  */
14
- VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALUE height, VALUE color_mode, VALUE start_pos);
17
+ VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALUE height, VALUE color_mode, VALUE depth, VALUE start_pos);
15
18
 
16
19
  #endif
@@ -2,47 +2,47 @@
2
2
 
3
3
  ///// Pixel encoding functions //////////////////////////////////////////
4
4
 
5
- void oily_png_encode_pixel_grayscale(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
5
+ void oily_png_encode_pixel_grayscale(PIXEL pixel, BYTE* bytes, long pos, VALUE palette) {
6
6
  // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons.
7
7
  // We'll uses the same to reomain compatible with ChunkyPNG.
8
8
  bytes[pos] = B_BYTE(pixel);
9
9
  }
10
10
 
11
- void oily_png_encode_pixel_grayscale_alpha(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
11
+ void oily_png_encode_pixel_grayscale_alpha(PIXEL pixel, BYTE* bytes, long pos, VALUE palette) {
12
12
  // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons.
13
13
  // We'll uses the same to reomain compatible with ChunkyPNG.
14
14
  bytes[pos + 0] = B_BYTE(pixel);
15
15
  bytes[pos + 1] = A_BYTE(pixel);
16
16
  }
17
17
 
18
- void oily_png_encode_pixel_truecolor(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
18
+ void oily_png_encode_pixel_truecolor(PIXEL pixel, BYTE* bytes, long pos, VALUE palette) {
19
19
  bytes[pos + 0] = R_BYTE(pixel);
20
20
  bytes[pos + 1] = G_BYTE(pixel);
21
21
  bytes[pos + 2] = B_BYTE(pixel);
22
22
  }
23
23
 
24
- void oily_png_encode_pixel_truecolor_alpha(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
24
+ void oily_png_encode_pixel_truecolor_alpha(PIXEL pixel, BYTE* bytes, long pos, VALUE palette) {
25
25
  bytes[pos + 0] = R_BYTE(pixel);
26
26
  bytes[pos + 1] = G_BYTE(pixel);
27
27
  bytes[pos + 2] = B_BYTE(pixel);
28
28
  bytes[pos + 3] = A_BYTE(pixel);
29
29
  }
30
30
 
31
- void oily_png_encode_pixel_indexed(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
31
+ void oily_png_encode_pixel_indexed(PIXEL pixel, BYTE* bytes, long pos, VALUE palette) {
32
32
  bytes[pos] = (BYTE) NUM2UINT(rb_funcall(palette, rb_intern("index"), 1, UINT2NUM(pixel)));
33
33
  }
34
34
 
35
35
  ///// Scanline filtering functions //////////////////////////////////////////
36
36
 
37
- void oily_png_encode_filter_sub(BYTE* bytes, int pos, int line_size, int pixel_size) {
38
- int x;
37
+ void oily_png_encode_filter_sub(BYTE* bytes, long pos, long line_size, char pixel_size) {
38
+ long x;
39
39
  for (x = line_size - 1; x > pixel_size; x--) {
40
40
  FILTER_BYTE(bytes[pos + x], bytes[pos + x - pixel_size]);
41
41
  }
42
42
  }
43
43
 
44
- void oily_png_encode_filter_up(BYTE* bytes, int pos, int line_size, int pixel_size) {
45
- int x;
44
+ void oily_png_encode_filter_up(BYTE* bytes, long pos, long line_size, char pixel_size) {
45
+ long x;
46
46
  if (pos >= line_size) {
47
47
  for (x = line_size - 1; x > 0; x--) {
48
48
  FILTER_BYTE(bytes[pos + x], bytes[pos + x - line_size]);
@@ -50,8 +50,8 @@ void oily_png_encode_filter_up(BYTE* bytes, int pos, int line_size, int pixel_si
50
50
  }
51
51
  }
52
52
 
53
- void oily_png_encode_filter_average(BYTE* bytes, int pos, int line_size, int pixel_size) {
54
- int x; BYTE a, b;
53
+ void oily_png_encode_filter_average(BYTE* bytes, long pos, long line_size, char pixel_size) {
54
+ long x; BYTE a, b;
55
55
  for (x = line_size - 1; x > 0; x--) {
56
56
  a = (x > pixel_size) ? bytes[pos + x - pixel_size] : 0;
57
57
  b = (pos >= line_size) ? bytes[pos + x - line_size] : 0;
@@ -59,8 +59,8 @@ void oily_png_encode_filter_average(BYTE* bytes, int pos, int line_size, int pix
59
59
  }
60
60
  }
61
61
 
62
- void oily_png_encode_filter_paeth(BYTE* bytes, int pos, int line_size, int pixel_size) {
63
- int x, p, pa, pb, pc; BYTE a, b, c, pr;
62
+ void oily_png_encode_filter_paeth(BYTE* bytes, long pos, long line_size, char pixel_size) {
63
+ long x; int p, pa, pb, pc; BYTE a, b, c, pr;
64
64
  for (x = line_size - 1; x > 0; x--) {
65
65
  a = (x > pixel_size) ? bytes[pos + x - pixel_size] : 0;
66
66
  b = (pos >= line_size) ? bytes[pos + x - line_size] : 0;
@@ -77,8 +77,9 @@ void oily_png_encode_filter_paeth(BYTE* bytes, int pos, int line_size, int pixel
77
77
  VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE color_mode, VALUE filtering) {
78
78
 
79
79
  // Get the data
80
- int width = FIX2INT(rb_funcall(self, rb_intern("width"), 0));
81
- int height = FIX2INT(rb_funcall(self, rb_intern("height"), 0));
80
+ char depth = 8;
81
+ long width = FIX2LONG(rb_funcall(self, rb_intern("width"), 0));
82
+ long height = FIX2LONG(rb_funcall(self, rb_intern("height"), 0));
82
83
  VALUE pixels = rb_funcall(self, rb_intern("pixels"), 0);
83
84
 
84
85
  if (RARRAY_LEN(pixels) != width * height) {
@@ -91,27 +92,27 @@ VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE c
91
92
  palette = rb_funcall(self, rb_intern("encoding_palette"), 0);
92
93
  }
93
94
 
94
- int pixel_size = oily_png_pixel_size(FIX2INT(color_mode));
95
- int line_size = 1 + pixel_size * width;
96
- int pass_size = line_size * height;
95
+ char pixel_size = oily_png_pixel_bytesize(FIX2INT(color_mode), depth);
96
+ long line_size = oily_png_scanline_bytesize(FIX2INT(color_mode), depth, width);
97
+ long pass_size = oily_png_pass_bytesize(FIX2INT(color_mode), depth, width, height);
97
98
 
98
99
  // Allocate memory for the byte array.
99
100
  BYTE* bytes = ALLOCA_N(BYTE, pass_size);
100
101
 
101
102
  // Select out pixel encoder function based on the color mode.
102
- void (*pixel_encoder)(PIXEL, BYTE*, int, VALUE) = NULL;
103
+ void (*pixel_encoder)(PIXEL, BYTE*, long, VALUE) = NULL;
103
104
  switch (FIX2INT(color_mode)) {
104
105
  case OILY_PNG_COLOR_GRAYSCALE: pixel_encoder = &oily_png_encode_pixel_grayscale; break;
105
106
  case OILY_PNG_COLOR_TRUECOLOR: pixel_encoder = &oily_png_encode_pixel_truecolor; break;
106
107
  case OILY_PNG_COLOR_INDEXED: pixel_encoder = &oily_png_encode_pixel_indexed; break;
107
108
  case OILY_PNG_COLOR_GRAYSCALE_ALPHA: pixel_encoder = &oily_png_encode_pixel_grayscale_alpha; break;
108
109
  case OILY_PNG_COLOR_TRUECOLOR_ALPHA: pixel_encoder = &oily_png_encode_pixel_truecolor_alpha; break;
109
- default: rb_raise(rb_eRuntimeError, "Unsupported color mode: %ld", FIX2INT(color_mode));
110
+ default: rb_raise(rb_eRuntimeError, "Unsupported color mode: %d", FIX2INT(color_mode));
110
111
  }
111
112
 
112
113
  // Loop over all the pixels to encode them into the byte array.
113
114
  PIXEL pixel;
114
- int x, y, pos;
115
+ long x, y, pos;
115
116
  for (y = 0; y < height; y++) {
116
117
  bytes[line_size * y] = (BYTE) FIX2INT(filtering);
117
118
 
@@ -126,13 +127,13 @@ VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE c
126
127
  if (FIX2INT(filtering) != OILY_PNG_FILTER_NONE) {
127
128
 
128
129
  // Assign the chosen filter function to the scanline_filter variable.
129
- void (*scanline_filter)(BYTE*, int, int, int) = NULL;
130
+ void (*scanline_filter)(BYTE*, long, long, char) = NULL;
130
131
  switch (FIX2INT(filtering)) {
131
132
  case OILY_PNG_FILTER_SUB: scanline_filter = &oily_png_encode_filter_sub; break;
132
133
  case OILY_PNG_FILTER_UP: scanline_filter = &oily_png_encode_filter_up; break;
133
134
  case OILY_PNG_FILTER_AVERAGE: scanline_filter = &oily_png_encode_filter_average; break;
134
135
  case OILY_PNG_FILTER_PAETH: scanline_filter = &oily_png_encode_filter_paeth; break;
135
- default: rb_raise(rb_eRuntimeError, "Unsupported filter type: %ld", FIX2INT(filtering));
136
+ default: rb_raise(rb_eRuntimeError, "Unsupported filter type: %d", FIX2INT(filtering));
136
137
  }
137
138
 
138
139
  // Now, apply the scanline_filter function to every line, backwards.
data/lib/oily_png.rb CHANGED
@@ -2,7 +2,7 @@ require 'chunky_png'
2
2
 
3
3
  module OilyPNG
4
4
 
5
- VERSION = "0.1.1"
5
+ VERSION = "0.2.0"
6
6
 
7
7
  def self.included(base)
8
8
  base::Canvas.send(:extend, OilyPNG::PNGDecoding)
data/oily_png.gemspec CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
4
4
 
5
5
  # Do not change the version and date fields by hand. This will be done
6
6
  # automatically by the gem release script.
7
- s.version = "0.1.1"
8
- s.date = "2010-10-18"
7
+ s.version = "0.2.0"
8
+ s.date = "2010-11-01"
9
9
 
10
10
  s.summary = "Native mixin to speed up ChunkyPNG"
11
11
  s.description = <<-EOT
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.extensions = ["ext/oily_png/extconf.rb"]
20
20
  s.require_paths = ["lib", "ext"]
21
21
 
22
- s.add_runtime_dependency('chunky_png', '~> 0.10.4')
22
+ s.add_runtime_dependency('chunky_png', '~> 0.11')
23
23
 
24
24
  s.add_development_dependency('rake')
25
25
  s.add_development_dependency('rspec', '~> 2.0')
@@ -29,6 +29,6 @@ Gem::Specification.new do |s|
29
29
 
30
30
  # Do not change the files and test_files fields by hand. This will be done
31
31
  # automatically by the gem release script.
32
- s.files = %w(.gitignore Gemfile Gemfile.lock LICENSE README.rdoc Rakefile ext/oily_png/extconf.rb ext/oily_png/oily_png_ext.c ext/oily_png/oily_png_ext.h ext/oily_png/png_decoding.c ext/oily_png/png_decoding.h ext/oily_png/png_encoding.c ext/oily_png/png_encoding.h lib/oily_png.rb oily_png.gemspec spec/decoding_spec.rb spec/encoding_spec.rb spec/resources/gray.png spec/resources/interlaced.png spec/resources/nonsquare.png spec/resources/square.png spec/spec_helper.rb tasks/github-gem.rake tasks/testing.rake)
32
+ s.files = %w(.gitignore Gemfile Gemfile.lock LICENSE README.rdoc Rakefile ext/oily_png/extconf.rb ext/oily_png/oily_png_ext.c ext/oily_png/oily_png_ext.h ext/oily_png/png_decoding.c ext/oily_png/png_decoding.h ext/oily_png/png_encoding.c ext/oily_png/png_encoding.h lib/oily_png.rb oily_png.gemspec spec/decoding_spec.rb spec/encoding_spec.rb spec/resources/basi0g01.png spec/resources/basi0g02.png spec/resources/basi0g04.png spec/resources/basi0g08.png spec/resources/basi0g16.png spec/resources/basi2c08.png spec/resources/basi2c16.png spec/resources/basi3p01.png spec/resources/basi3p02.png spec/resources/basi3p04.png spec/resources/basi3p08.png spec/resources/basi4a08.png spec/resources/basi4a16.png spec/resources/basi6a08.png spec/resources/basi6a16.png spec/resources/basn0g01.png spec/resources/basn0g02.png spec/resources/basn0g04.png spec/resources/basn0g08.png spec/resources/basn0g16.png spec/resources/basn2c08.png spec/resources/basn2c16.png spec/resources/basn3p01.png spec/resources/basn3p02.png spec/resources/basn3p04.png spec/resources/basn3p08.png spec/resources/basn4a08.png spec/resources/basn4a16.png spec/resources/basn6a08.png spec/resources/basn6a16.png spec/resources/gray.png spec/resources/interlaced.png spec/resources/nonsquare.png spec/resources/s01i3p01.png spec/resources/s01n3p01.png spec/resources/s02i3p01.png spec/resources/s02n3p01.png spec/resources/s03i3p01.png spec/resources/s03n3p01.png spec/resources/s04i3p01.png spec/resources/s04n3p01.png spec/resources/s05i3p02.png spec/resources/s05n3p02.png spec/resources/s06i3p02.png spec/resources/s06n3p02.png spec/resources/s07i3p02.png spec/resources/s07n3p02.png spec/resources/s08i3p02.png spec/resources/s08n3p02.png spec/resources/s09i3p02.png spec/resources/s09n3p02.png spec/resources/s32i3p04.png spec/resources/s32n3p04.png spec/resources/s33i3p04.png spec/resources/s33n3p04.png spec/resources/s34i3p04.png spec/resources/s34n3p04.png spec/resources/s35i3p04.png spec/resources/s35n3p04.png spec/resources/s36i3p04.png spec/resources/s36n3p04.png spec/resources/s37i3p04.png spec/resources/s37n3p04.png spec/resources/s38i3p04.png spec/resources/s38n3p04.png spec/resources/s39i3p04.png spec/resources/s39n3p04.png spec/resources/s40i3p04.png spec/resources/s40n3p04.png spec/resources/square.png spec/spec_helper.rb tasks/github-gem.rake tasks/testing.rake)
33
33
  s.test_files = %w(spec/decoding_spec.rb spec/encoding_spec.rb)
34
34
  end
@@ -2,20 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe OilyPNG::PNGDecoding do
4
4
 
5
- it "should call Color.bytesize in the pure ruby version" do
6
- ChunkyPNG::Color.should_receive(:bytesize).and_return(3)
5
+ it "should call ChunkyPNG::Color.pixel_bytesize in the pure ruby version" do
6
+ ChunkyPNG::Color.should_receive(:pixel_bytesize).and_return(3)
7
7
  ChunkyPNG::Canvas.from_file(resource_file('square.png'))
8
8
  end
9
9
 
10
- it "should not call Color.bytesize in the native version" do
11
- ChunkyPNG::Color.should_not_receive(:bytesize)
12
- OilyCanvas.from_file(resource_file('square.png'))
13
- end
14
-
15
- it "should decode an interlaced image correctly" do
16
- c1 = OilyCanvas.from_file(resource_file('interlaced.png'))
17
- c2 = ChunkyPNG::Canvas.from_file(resource_file('interlaced.png'))
18
- c2.should == c1
10
+ it "should not call ChunkyPNG::Color.pixel_bytesize in the native version" do
11
+ ChunkyPNG::Color.should_not_receive(:pixel_bytesize)
12
+ OilyPNG::Canvas.from_file(resource_file('square.png'))
19
13
  end
20
14
 
21
15
  context 'decoding different filtering methods' do
@@ -23,56 +17,35 @@ describe OilyPNG::PNGDecoding do
23
17
 
24
18
  it "should decode NONE filtering exactly the same as ChunkyPNG" do
25
19
  filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_NONE)
26
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
20
+ ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data)
27
21
  end
28
22
 
29
23
  it "should decode SUB filtering exactly the same as ChunkyPNG" do
30
24
  filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_SUB)
31
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
25
+ ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data)
32
26
  end
33
27
 
34
28
  it "should decode UP filtering exactly the same as ChunkyPNG" do
35
29
  filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_UP)
36
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
30
+ ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data)
37
31
  end
38
32
 
39
33
  it "should decode AVERAGE filtering exactly the same as ChunkyPNG" do
40
34
  filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_AVERAGE)
41
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
35
+ ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data)
42
36
  end
43
37
 
44
38
  it "should decode PAETH filtering exactly the same as ChunkyPNG" do
45
39
  filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_PAETH)
46
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
40
+ ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data)
47
41
  end
48
42
  end
49
43
 
50
- context 'decoding different color modes' do
51
- before(:all) { @reference = ChunkyPNG::Canvas.from_file(resource_file('gray.png'))}
52
-
53
- it "should decode RGBA images the same as ChunkyPNG" do
54
- filtered_data = @reference.to_blob(:color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA)
55
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
56
- end
57
-
58
- it "should decode RGB images exactly the same as ChunkyPNG" do
59
- filtered_data = @reference.to_blob(:color_mode => ChunkyPNG::COLOR_TRUECOLOR)
60
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
61
- end
62
-
63
- it "should decode indexed images exactly the same as ChunkyPNG" do
64
- filtered_data = @reference.to_blob(:color_mode => ChunkyPNG::COLOR_INDEXED)
65
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
66
- end
67
-
68
- it "should decode grayscale images exactly the same as ChunkyPNG" do
69
- filtered_data = @reference.to_blob(:color_mode => ChunkyPNG::COLOR_GRAYSCALE)
70
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
71
- end
72
-
73
- it "should decode grayscale images with transparency the same as ChunkyPNG" do
74
- filtered_data = @reference.to_blob(:color_mode => ChunkyPNG::COLOR_GRAYSCALE_ALPHA)
75
- ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyCanvas.from_blob(filtered_data)
44
+ context 'decoding compatibility with ChunkyPNG' do
45
+ resource_files.each do |file|
46
+ it "should #{File.basename(file)} the same as ChunkyPNG" do
47
+ OilyPNG::Canvas.from_file(file).pixels.should == ChunkyPNG::Canvas.from_file(file).pixels
48
+ end
76
49
  end
77
50
  end
78
51
  end
@@ -5,7 +5,7 @@ describe OilyPNG::PNGEncoding do
5
5
  context 'encoding different color modes' do
6
6
  before do
7
7
  @canvas = ChunkyPNG::Canvas.from_file(resource_file('gray.png'))
8
- @oily_canvas = OilyCanvas.from_canvas(@canvas)
8
+ @oily_canvas = OilyPNG::Canvas.from_canvas(@canvas)
9
9
  end
10
10
 
11
11
  it "should encode an image using grayscale correctly" do
@@ -47,7 +47,7 @@ describe OilyPNG::PNGEncoding do
47
47
  context 'encoding different filters' do
48
48
  before do
49
49
  @canvas = ChunkyPNG::Canvas.from_file(resource_file('nonsquare.png'))
50
- @oily_canvas = OilyCanvas.from_canvas(@canvas)
50
+ @oily_canvas = OilyPNG::Canvas.from_canvas(@canvas)
51
51
  end
52
52
 
53
53
  it "should encode correctly with no filtering" do
@@ -83,7 +83,7 @@ describe OilyPNG::PNGEncoding do
83
83
 
84
84
  it "should encode an interlaced image correctly" do
85
85
  canvas = ChunkyPNG::Canvas.from_file(resource_file('interlaced.png'))
86
- data = OilyCanvas.from_canvas(canvas).to_blob(:interlace => true)
86
+ data = OilyPNG::Canvas.from_canvas(canvas).to_blob(:interlace => true)
87
87
  ds = ChunkyPNG::Datastream.from_blob(data)
88
88
  ds.header_chunk.interlace.should == ChunkyPNG::INTERLACING_ADAM7
89
89
  ChunkyPNG::Canvas.from_datastream(ds).should == canvas
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
data/spec/spec_helper.rb CHANGED
@@ -7,9 +7,12 @@ require 'rspec'
7
7
  require 'chunky_png'
8
8
  require 'oily_png/oily_png_ext'
9
9
 
10
- class OilyCanvas < ChunkyPNG::Canvas
11
- extend OilyPNG::PNGDecoding
12
- include OilyPNG::PNGEncoding
10
+
11
+ module OilyPNG
12
+ class Canvas < ChunkyPNG::Canvas
13
+ extend OilyPNG::PNGDecoding
14
+ include OilyPNG::PNGEncoding
15
+ end
13
16
  end
14
17
 
15
18
  module ResourceHelper
@@ -20,6 +23,10 @@ end
20
23
 
21
24
  module CanvasHelper
22
25
 
26
+ def resource_files(pattern = "*.png")
27
+ Dir[File.join(File.dirname(__FILE__), 'resources', pattern)]
28
+ end
29
+
23
30
  def resource_file(name)
24
31
  File.join(File.dirname(__FILE__), 'resources', name)
25
32
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oily_png
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Willem van Bergen
@@ -15,54 +14,50 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-10-18 00:00:00 +02:00
17
+ date: 2010-11-01 00:00:00 +01:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
21
+ name: chunky_png
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
23
  none: false
24
24
  requirements:
25
25
  - - ~>
26
26
  - !ruby/object:Gem::Version
27
- hash: 63
28
27
  segments:
29
28
  - 0
30
- - 10
31
- - 4
32
- version: 0.10.4
33
- requirement: *id001
29
+ - 11
30
+ version: "0.11"
34
31
  type: :runtime
35
- name: chunky_png
36
32
  prerelease: false
33
+ version_requirements: *id001
37
34
  - !ruby/object:Gem::Dependency
38
- version_requirements: &id002 !ruby/object:Gem::Requirement
35
+ name: rake
36
+ requirement: &id002 !ruby/object:Gem::Requirement
39
37
  none: false
40
38
  requirements:
41
39
  - - ">="
42
40
  - !ruby/object:Gem::Version
43
- hash: 3
44
41
  segments:
45
42
  - 0
46
43
  version: "0"
47
- requirement: *id002
48
44
  type: :development
49
- name: rake
50
45
  prerelease: false
46
+ version_requirements: *id002
51
47
  - !ruby/object:Gem::Dependency
52
- version_requirements: &id003 !ruby/object:Gem::Requirement
48
+ name: rspec
49
+ requirement: &id003 !ruby/object:Gem::Requirement
53
50
  none: false
54
51
  requirements:
55
52
  - - ~>
56
53
  - !ruby/object:Gem::Version
57
- hash: 3
58
54
  segments:
59
55
  - 2
60
56
  - 0
61
57
  version: "2.0"
62
- requirement: *id003
63
58
  type: :development
64
- name: rspec
65
59
  prerelease: false
60
+ version_requirements: *id003
66
61
  description: " This Ruby C extenstion defines a module that can be included into ChunkyPNG to improve its speed.\n"
67
62
  email:
68
63
  - willem@railsdoctors.com
@@ -90,9 +85,75 @@ files:
90
85
  - oily_png.gemspec
91
86
  - spec/decoding_spec.rb
92
87
  - spec/encoding_spec.rb
88
+ - spec/resources/basi0g01.png
89
+ - spec/resources/basi0g02.png
90
+ - spec/resources/basi0g04.png
91
+ - spec/resources/basi0g08.png
92
+ - spec/resources/basi0g16.png
93
+ - spec/resources/basi2c08.png
94
+ - spec/resources/basi2c16.png
95
+ - spec/resources/basi3p01.png
96
+ - spec/resources/basi3p02.png
97
+ - spec/resources/basi3p04.png
98
+ - spec/resources/basi3p08.png
99
+ - spec/resources/basi4a08.png
100
+ - spec/resources/basi4a16.png
101
+ - spec/resources/basi6a08.png
102
+ - spec/resources/basi6a16.png
103
+ - spec/resources/basn0g01.png
104
+ - spec/resources/basn0g02.png
105
+ - spec/resources/basn0g04.png
106
+ - spec/resources/basn0g08.png
107
+ - spec/resources/basn0g16.png
108
+ - spec/resources/basn2c08.png
109
+ - spec/resources/basn2c16.png
110
+ - spec/resources/basn3p01.png
111
+ - spec/resources/basn3p02.png
112
+ - spec/resources/basn3p04.png
113
+ - spec/resources/basn3p08.png
114
+ - spec/resources/basn4a08.png
115
+ - spec/resources/basn4a16.png
116
+ - spec/resources/basn6a08.png
117
+ - spec/resources/basn6a16.png
93
118
  - spec/resources/gray.png
94
119
  - spec/resources/interlaced.png
95
120
  - spec/resources/nonsquare.png
121
+ - spec/resources/s01i3p01.png
122
+ - spec/resources/s01n3p01.png
123
+ - spec/resources/s02i3p01.png
124
+ - spec/resources/s02n3p01.png
125
+ - spec/resources/s03i3p01.png
126
+ - spec/resources/s03n3p01.png
127
+ - spec/resources/s04i3p01.png
128
+ - spec/resources/s04n3p01.png
129
+ - spec/resources/s05i3p02.png
130
+ - spec/resources/s05n3p02.png
131
+ - spec/resources/s06i3p02.png
132
+ - spec/resources/s06n3p02.png
133
+ - spec/resources/s07i3p02.png
134
+ - spec/resources/s07n3p02.png
135
+ - spec/resources/s08i3p02.png
136
+ - spec/resources/s08n3p02.png
137
+ - spec/resources/s09i3p02.png
138
+ - spec/resources/s09n3p02.png
139
+ - spec/resources/s32i3p04.png
140
+ - spec/resources/s32n3p04.png
141
+ - spec/resources/s33i3p04.png
142
+ - spec/resources/s33n3p04.png
143
+ - spec/resources/s34i3p04.png
144
+ - spec/resources/s34n3p04.png
145
+ - spec/resources/s35i3p04.png
146
+ - spec/resources/s35n3p04.png
147
+ - spec/resources/s36i3p04.png
148
+ - spec/resources/s36n3p04.png
149
+ - spec/resources/s37i3p04.png
150
+ - spec/resources/s37n3p04.png
151
+ - spec/resources/s38i3p04.png
152
+ - spec/resources/s38n3p04.png
153
+ - spec/resources/s39i3p04.png
154
+ - spec/resources/s39n3p04.png
155
+ - spec/resources/s40i3p04.png
156
+ - spec/resources/s40n3p04.png
96
157
  - spec/resources/square.png
97
158
  - spec/spec_helper.rb
98
159
  - tasks/github-gem.rake
@@ -117,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
178
  requirements:
118
179
  - - ">="
119
180
  - !ruby/object:Gem::Version
120
- hash: 3
181
+ hash: -58392216600872723
121
182
  segments:
122
183
  - 0
123
184
  version: "0"
@@ -126,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
187
  requirements:
127
188
  - - ">="
128
189
  - !ruby/object:Gem::Version
129
- hash: 3
190
+ hash: -58392216600872723
130
191
  segments:
131
192
  - 0
132
193
  version: "0"