oily_png 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- oily_png (0.0.6)
4
+ oily_png (0.0.7)
5
5
  chunky_png (~> 0.10.2)
6
6
 
7
7
  GEM
data/README.rdoc CHANGED
@@ -3,7 +3,9 @@
3
3
  OilyPNG is a Ruby C extension to speed up the pure Ruby ChunkyPNG library. It is a standalone
4
4
  module, so it does not require LibPNG, ImageMagick or any other library. Currently it has an
5
5
  alternative implementation of decoding and encoding PNGs, making these operations much
6
- faster for PNG images that apply filtering.
6
+ faster, especially for PNG images that apply filtering.
7
+
8
+ Performance comparison: http://gist.github.com/611255
7
9
 
8
10
  *Warning*: this is my first C code in years. It may blow up your PC after leaking memory all
9
11
  over the place, killing a kitten in the process. You have been warned.
@@ -94,7 +94,7 @@ VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALU
94
94
  }
95
95
 
96
96
  // Select the pixel decoder function for this color mode.
97
- PIXEL (*pixel_decoder)(int, BYTE*, int, VALUE);
97
+ PIXEL (*pixel_decoder)(int, BYTE*, int, VALUE) = NULL;
98
98
  switch (FIX2INT(color_mode)) {
99
99
  case OILY_PNG_COLOR_GRAYSCALE: pixel_decoder = &oily_png_decode_pixel_grayscale; break;
100
100
  case OILY_PNG_COLOR_TRUECOLOR: pixel_decoder = &oily_png_decode_pixel_truecolor; break;
@@ -1,33 +1,35 @@
1
1
  #include "oily_png_ext.h"
2
2
 
3
- void oily_png_encode_pixel(PIXEL pixel, int color_mode, BYTE* bytes, int pos, VALUE palette) {
4
- switch (color_mode) {
5
- case OILY_PNG_COLOR_GRAYSCALE:
6
- bytes[pos] = R_BYTE(pixel);
7
- break;
8
- case OILY_PNG_COLOR_TRUECOLOR:
9
- bytes[pos + 0] = R_BYTE(pixel);
10
- bytes[pos + 1] = G_BYTE(pixel);
11
- bytes[pos + 2] = B_BYTE(pixel);
12
- break;
13
- case OILY_PNG_COLOR_INDEXED:
14
- bytes[pos] = (BYTE) NUM2UINT(rb_funcall(palette, rb_intern("index"), 1, UINT2NUM(pixel)));
15
- break;
16
- case OILY_PNG_COLOR_GRAYSCALE_ALPHA:
17
- bytes[pos + 0] = R_BYTE(pixel);
18
- bytes[pos + 1] = A_BYTE(pixel);
19
- break;
20
- case OILY_PNG_COLOR_TRUECOLOR_ALPHA:
21
- bytes[pos + 0] = R_BYTE(pixel);
22
- bytes[pos + 1] = G_BYTE(pixel);
23
- bytes[pos + 2] = B_BYTE(pixel);
24
- bytes[pos + 3] = A_BYTE(pixel);
25
- break;
26
- default:
27
- rb_raise(rb_eRuntimeError, "Unsupported color mode: %d", color_mode);
28
- }
3
+ ///// Pixel encoding functions //////////////////////////////////////////
4
+
5
+ void oily_png_encode_pixel_grayscale(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
6
+ bytes[pos] = R_BYTE(pixel);
29
7
  }
30
8
 
9
+ void oily_png_encode_pixel_grayscale_alpha(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
10
+ bytes[pos + 0] = R_BYTE(pixel);
11
+ bytes[pos + 1] = A_BYTE(pixel);
12
+ }
13
+
14
+ void oily_png_encode_pixel_truecolor(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
15
+ bytes[pos + 0] = R_BYTE(pixel);
16
+ bytes[pos + 1] = G_BYTE(pixel);
17
+ bytes[pos + 2] = B_BYTE(pixel);
18
+ }
19
+
20
+ void oily_png_encode_pixel_truecolor_alpha(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
21
+ bytes[pos + 0] = R_BYTE(pixel);
22
+ bytes[pos + 1] = G_BYTE(pixel);
23
+ bytes[pos + 2] = B_BYTE(pixel);
24
+ bytes[pos + 3] = A_BYTE(pixel);
25
+ }
26
+
27
+ void oily_png_encode_pixel_indexed(PIXEL pixel, BYTE* bytes, int pos, VALUE palette) {
28
+ bytes[pos] = (BYTE) NUM2UINT(rb_funcall(palette, rb_intern("index"), 1, UINT2NUM(pixel)));
29
+ }
30
+
31
+ ///// Scanline filtering functions //////////////////////////////////////////
32
+
31
33
  void oily_png_encode_filter_sub(BYTE* bytes, int pos, int line_size, int pixel_size) {
32
34
  int x;
33
35
  for (x = line_size - 1; x > pixel_size; x--) {
@@ -66,7 +68,6 @@ void oily_png_encode_filter_paeth(BYTE* bytes, int pos, int line_size, int pixel
66
68
  pr = (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c);
67
69
  FILTER_BYTE(bytes[pos + x], pr);
68
70
  }
69
-
70
71
  }
71
72
 
72
73
  VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE color_mode, VALUE filtering) {
@@ -80,6 +81,7 @@ VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE c
80
81
  rb_raise(rb_eRuntimeError, "The number of pixels does not match the canvas dimensions.");
81
82
  }
82
83
 
84
+ // Get the encoding palette if we're encoding to an indexed bytestream.
83
85
  VALUE palette = Qnil;
84
86
  if (FIX2INT(color_mode) == OILY_PNG_COLOR_INDEXED) {
85
87
  palette = rb_funcall(self, rb_intern("encoding_palette"), 0);
@@ -92,6 +94,18 @@ VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE c
92
94
  // Allocate memory for the byte array.
93
95
  BYTE* bytes = ALLOCA_N(BYTE, pass_size);
94
96
 
97
+ // Select out pixel encoder function based on the color mode.
98
+ void (*pixel_encoder)(PIXEL, BYTE*, int, VALUE) = NULL;
99
+ switch (FIX2INT(color_mode)) {
100
+ case OILY_PNG_COLOR_GRAYSCALE: pixel_encoder = &oily_png_encode_pixel_grayscale; break;
101
+ case OILY_PNG_COLOR_TRUECOLOR: pixel_encoder = &oily_png_encode_pixel_truecolor; break;
102
+ case OILY_PNG_COLOR_INDEXED: pixel_encoder = &oily_png_encode_pixel_indexed; break;
103
+ case OILY_PNG_COLOR_GRAYSCALE_ALPHA: pixel_encoder = &oily_png_encode_pixel_grayscale_alpha; break;
104
+ case OILY_PNG_COLOR_TRUECOLOR_ALPHA: pixel_encoder = &oily_png_encode_pixel_truecolor_alpha; break;
105
+ default: rb_raise(rb_eRuntimeError, "Unsupported color mode: %d", color_mode);
106
+ }
107
+
108
+ // Loop over all the pixels to encode them into the byte array.
95
109
  PIXEL pixel;
96
110
  int x, y, pos;
97
111
  for (y = 0; y < height; y++) {
@@ -100,22 +114,30 @@ VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE c
100
114
  for (x = 0; x < width; x++) {
101
115
  pixel = NUM2UINT(rb_ary_entry(pixels, y * height + x));
102
116
  pos = (line_size * y) + (pixel_size * x) + 1;
103
- oily_png_encode_pixel(pixel, FIX2INT(color_mode), bytes, pos, palette);
117
+ pixel_encoder(pixel, bytes, pos, palette);
104
118
  }
105
119
  }
106
120
 
121
+ // Check if we are going to apply any filtering
107
122
  if (FIX2INT(filtering) != OILY_PNG_FILTER_NONE) {
123
+
124
+ // Assign the chosen filter function to the scanline_filter variable.
125
+ void (*scanline_filter)(BYTE*, int, int, int) = NULL;
126
+ switch (FIX2INT(filtering)) {
127
+ case OILY_PNG_FILTER_SUB: scanline_filter = &oily_png_encode_filter_sub; break;
128
+ case OILY_PNG_FILTER_UP: scanline_filter = &oily_png_encode_filter_up; break;
129
+ case OILY_PNG_FILTER_AVERAGE: scanline_filter = &oily_png_encode_filter_average; break;
130
+ case OILY_PNG_FILTER_PAETH: scanline_filter = &oily_png_encode_filter_paeth; break;
131
+ default: rb_raise(rb_eRuntimeError, "Unsupported filter type: %d", FIX2INT(filtering));
132
+ }
133
+
134
+ // Now, apply the scanline_filter function to every line, backwards.
108
135
  for (y = height - 1; y >= 0; y--) {
109
- switch (FIX2INT(filtering)) {
110
- case OILY_PNG_FILTER_SUB: oily_png_encode_filter_sub( bytes, line_size * y, line_size, pixel_size); break;
111
- case OILY_PNG_FILTER_UP: oily_png_encode_filter_up( bytes, line_size * y, line_size, pixel_size); break;
112
- case OILY_PNG_FILTER_AVERAGE: oily_png_encode_filter_average( bytes, line_size * y, line_size, pixel_size); break;
113
- case OILY_PNG_FILTER_PAETH: oily_png_encode_filter_paeth( bytes, line_size * y, line_size, pixel_size); break;
114
- default: rb_raise(rb_eRuntimeError, "Unsupported filter type: %d", FIX2INT(filtering));
115
- }
136
+ scanline_filter(bytes, line_size * y, line_size, pixel_size);
116
137
  }
117
138
  }
118
139
 
140
+ // Append to encoded image pass to the output stream.
119
141
  rb_str_cat(stream, (char*) bytes, pass_size);
120
142
  return Qnil;
121
143
  }
data/lib/oily_png.rb CHANGED
@@ -2,7 +2,7 @@ require 'chunky_png'
2
2
 
3
3
  module OilyPNG
4
4
 
5
- VERSION = "0.0.6"
5
+ VERSION = "0.0.7"
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.0.6"
8
- s.date = "2010-10-06"
7
+ s.version = "0.0.7"
8
+ s.date = "2010-10-07"
9
9
 
10
10
  s.summary = "Native mixin to speed up ChunkyPNG"
11
11
  s.description = <<-EOT
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oily_png
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ - 7
10
+ version: 0.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Willem van Bergen
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-06 00:00:00 +02:00
18
+ date: 2010-10-07 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency