oily_png-1.1.0/0000755000004100000410000000000012110154624013355 5ustar www-datawww-dataoily_png-1.1.0/.travis.yml0000644000004100000410000000033212110154624015464 0ustar www-datawww-datalanguage: ruby script: bundle exec rake rvm: - 1.8.7 - 1.9.2 - 1.9.3 - ruby-head - ree - rbx-18mode - rbx-19mode matrix: allow_failures: - rvm: rbx-18mode - rvm: rbx-19mode - rvm: ruby-head oily_png-1.1.0/ext/0000755000004100000410000000000012110154624014155 5ustar www-datawww-dataoily_png-1.1.0/ext/oily_png/0000755000004100000410000000000012110154624015775 5ustar www-datawww-dataoily_png-1.1.0/ext/oily_png/resampling.c0000644000004100000410000001421312110154624020303 0ustar www-datawww-data#include "oily_png_ext.h" #include void oily_png_generate_steps_residues(long width, long new_width, long *steps, long *residues) { long base_step = width / new_width; long err_step = (width % new_width) << 1; long denominator = new_width << 1; long index; long err; /* We require an arithmetic modolus and rounding to the left of zero * This is standard Ruby behaviour (I hope!) but differs with how C/Java * typically handle integer division and modulo. But since we are workig * in mixed numbers, Ruby's convention is especially convienent */ if (width >= new_width) { index = (width - new_width) / denominator; err = (width - new_width) % denominator; } else { index = (width - new_width) / denominator - 1; err = denominator - ((new_width - width) % denominator); } long i; for (i=0; i < new_width; i++){ if (residues != NULL) { steps[i] = index; residues[i] = (long) round(255.0 * (float) err / (float) denominator); } else { /* If residues aren't requested, we round to the nearest pixel */ if (err < new_width) { steps[i] = index; } else { steps[i] = index + 1; } } index += base_step; err += err_step; if (err >= denominator) { index += 1; err -= denominator; } } } VALUE oily_png_canvas_steps(VALUE self, VALUE v_width, VALUE v_new_width) { UNUSED_PARAMETER(self); long width = NUM2LONG(v_width); long new_width = NUM2LONG(v_new_width); long *steps = ALLOC_N(long, new_width); VALUE ret = rb_ary_new2(new_width); oily_png_generate_steps_residues(width, new_width, steps, NULL); long i; for (i=0; i < new_width; i++) { rb_ary_store(ret, i, LONG2FIX(steps[i])); } /* This is an unprotected allocation; it will leak on exception. * However, rb_ary_store should not generate one as we have * pre-allocated the array. */ xfree(steps); steps = NULL; return ret; } VALUE oily_png_canvas_steps_residues(VALUE self, VALUE v_width, VALUE v_new_width) { UNUSED_PARAMETER(self); long width = NUM2LONG(v_width); long new_width = NUM2LONG(v_new_width); VALUE ret_steps = rb_ary_new2(new_width); VALUE ret_residues = rb_ary_new2(new_width); long *steps = ALLOC_N(long, new_width); long *residues = ALLOC_N(long, new_width); oily_png_generate_steps_residues(width, new_width, steps, residues); long i; for (i=0; i < new_width; i++) { rb_ary_store(ret_steps, i, LONG2FIX(steps[i])); rb_ary_store(ret_residues, i, LONG2FIX(residues[i])); } /* This is an unprotected allocation; it will leak on exception. * However, rb_ary_store should not generate one as we have * pre-allocated the array. */ xfree(steps); steps = NULL; xfree(residues); residues = NULL; /* We return multiple values */ VALUE ret = rb_ary_new2(2); rb_ary_store(ret, 0, ret_steps); rb_ary_store(ret, 1, ret_residues); return ret; } VALUE oily_png_canvas_resample_nearest_neighbor_bang(VALUE self, VALUE v_new_width, VALUE v_new_height) { long new_width = NUM2LONG(v_new_width); long new_height = NUM2LONG(v_new_height); long self_width = NUM2LONG(rb_funcall(self, rb_intern("width"), 0)); long self_height = NUM2LONG(rb_funcall(self, rb_intern("height"), 0)); VALUE pixels = rb_ary_new2(new_width*new_height); VALUE source = rb_iv_get(self, "@pixels"); long *steps_x = ALLOC_N(long, new_width); long *steps_y = ALLOC_N(long, new_height); oily_png_generate_steps_residues(self_width, new_width, steps_x, NULL); oily_png_generate_steps_residues(self_height, new_height, steps_y, NULL); long index = 0; long x, y; long src_index; for (y=0; y < new_height; y++) { for (x = 0; x < new_width; x++) { src_index = steps_y[y] * self_width + steps_x[x]; VALUE pixel = rb_ary_entry(source, src_index); rb_ary_store(pixels, index, pixel); index++; } } xfree(steps_x); steps_x = NULL; xfree(steps_y); steps_y = NULL; rb_iv_set(self, "@pixels", pixels); rb_iv_set(self, "@width", LONG2NUM(new_width)); rb_iv_set(self, "@height", LONG2NUM(new_height)); return self; } VALUE oily_png_canvas_resample_bilinear_bang(VALUE self, VALUE v_new_width, VALUE v_new_height) { long new_width = NUM2LONG(v_new_width); long new_height = NUM2LONG(v_new_height); long self_width = NUM2LONG(rb_funcall(self, rb_intern("width"), 0)); long self_height = NUM2LONG(rb_funcall(self, rb_intern("height"), 0)); VALUE pixels = rb_ary_new2(new_width*new_height); VALUE source = rb_iv_get(self, "@pixels"); long *index_x = ALLOC_N(long, new_width); long *index_y = ALLOC_N(long, new_height); long *interp_x = ALLOC_N(long, new_width); long *interp_y = ALLOC_N(long, new_height); oily_png_generate_steps_residues(self_width, new_width, index_x, interp_x); oily_png_generate_steps_residues(self_height, new_height, index_y, interp_y); long index = 0; long x, y; long y1, y2, x1, x2; uint32_t y_residue, x_residue; uint32_t pixel_11, pixel_21, pixel_12, pixel_22; uint32_t pixel_top, pixel_bot; for (y = 0; y < new_height; y++) { y1 = index_y[y] < 0 ? 0 : index_y[y]; y2 = y1+1 >= self_height ? self_height-1 : y1+1; y_residue = interp_y[y]; for (x = 0; x < new_width; x++) { x1 = index_x[x] < 0 ? 0 : index_x[x]; x2 = x1+1 >= self_width ? self_height-1 : x1+1; x_residue = interp_x[x]; pixel_11 = NUM2UINT(rb_ary_entry(source, y1*self_width + x1)); pixel_21 = NUM2UINT(rb_ary_entry(source, y1*self_width + x2)); pixel_12 = NUM2UINT(rb_ary_entry(source, y2*self_width + x1)); pixel_22 = NUM2UINT(rb_ary_entry(source, y2*self_width + x2)); pixel_top = oily_png_color_interpolate_quick(pixel_21, pixel_11, x_residue); pixel_bot = oily_png_color_interpolate_quick(pixel_22, pixel_12, x_residue); rb_ary_store(pixels, index++, UINT2NUM(oily_png_color_interpolate_quick(pixel_bot, pixel_top, y_residue))); } } xfree(index_x); xfree(index_y); xfree(interp_x); xfree(interp_y); interp_x = NULL; interp_y = NULL; rb_iv_set(self, "@pixels", pixels); rb_iv_set(self, "@width", LONG2NUM(new_width)); rb_iv_set(self, "@height", LONG2NUM(new_height)); return self; } oily_png-1.1.0/ext/oily_png/extconf.rb0000644000004100000410000000011012110154624017760 0ustar www-datawww-datarequire 'mkmf' $CFLAGS << ' -Wall' create_makefile('oily_png/oily_png') oily_png-1.1.0/ext/oily_png/operations.c0000644000004100000410000001340512110154624020327 0ustar www-datawww-data#include "oily_png_ext.h" void oily_png_check_size_constraints(long self_width, long self_height, long other_width, long other_height, long offset_x, long offset_y){ // For now, these raise a standard runtime error. They should however raise custom exception classes (OutOfBounds) if(self_width < other_width + offset_x){ rb_raise(rb_eRuntimeError, "Background image width is too small!"); } if(self_height < other_height + offset_y){ rb_raise(rb_eRuntimeError, "Background image height is too small!"); } } VALUE oily_png_compose_bang(int argc, VALUE *argv, VALUE self) { // Corresponds to the other image(foreground) that we want to compose onto this one(background). VALUE other; // The offsets are optional arguments, so these may or may not be null pointers. // We'll prefix them with 'opt' to identify this. VALUE opt_offset_x; VALUE opt_offset_y; // Scan the passed in arguments, and populate the above-declared variables. Notice that '12' // specifies that oily_png_compose_bang takes in 1 required parameter, and 2 optional ones (the offsets) rb_scan_args(argc, argv, "12", &other,&opt_offset_x,&opt_offset_y); // Regardless of whether offsets were provided, we must specify a default value for them since they will // be used in calculating the position of the composed element. long offset_x = 0; long offset_y = 0; // If offsets were provided, then the opt_offset_* variables will not be null pointers. FIXNUM_P checks // whether they point to a fixnum object. If they do, then we can safely assign our offset_* variables to the values. if(FIXNUM_P(opt_offset_x)){ offset_x = FIX2LONG(opt_offset_x); } if(FIXNUM_P(opt_offset_y)){ offset_y = FIX2LONG(opt_offset_y); } // Get the dimension data for both foreground and background images. long self_width = FIX2LONG(rb_funcall(self, rb_intern("width"), 0)); long self_height = FIX2LONG(rb_funcall(self, rb_intern("height"), 0)); long other_width = FIX2LONG(rb_funcall(other, rb_intern("width"), 0)); long other_height = FIX2LONG(rb_funcall(other, rb_intern("height"), 0)); // Make sure that the 'other' image fits within the current image. If it doesn't, an exception is raised // and the operation should be aborted. oily_png_check_size_constraints( self_width, self_height, other_width, other_height, offset_x, offset_y ); // Get the pixel data for both the foreground(other) and background(self) pixels. VALUE* bg_pixels = RARRAY_PTR(rb_funcall(self, rb_intern("pixels"), 0)); VALUE* fg_pixels = RARRAY_PTR(rb_funcall(other, rb_intern("pixels"), 0)); long x = 0; long y = 0; long bg_index = 0; // corresponds to the current index in the bg_pixels array. for( y = 0; y < other_height; y++ ){ for( x = 0; x < other_width; x++ ){ // We need to find the value of bg_index twice, so we only calculate and store it once. bg_index = ( x + offset_x ) + ( y + offset_y ) * self_width; // Replace the background pixel with the composition of background + foreground bg_pixels[bg_index] = UINT2NUM( oily_png_compose_color( NUM2UINT( fg_pixels[x+ y * other_width] ), NUM2UINT( bg_pixels[bg_index] ) ) ); } } return self; } VALUE oily_png_replace_bang(int argc, VALUE *argv, VALUE self) { // Corresponds to the other image(foreground) that we want to compose onto this one(background). VALUE other; // The offsets are optional arguments, so these may or may not be null pointers. // We'll prefix them with 'opt' to identify this. VALUE opt_offset_x; VALUE opt_offset_y; // Scan the passed in arguments, and populate the above-declared variables. Notice that '12' // specifies that oily_png_compose_bang takes in 1 required parameter, and 2 optional ones (the offsets) rb_scan_args(argc, argv, "12", &other,&opt_offset_x,&opt_offset_y); // Regardless of whether offsets were provided, we must specify a default value for them since they will // be used in calculating the position of the composed element. long offset_x = 0; long offset_y = 0; // If offsets were provided, then the opt_offset_* variables will not be null pointers. FIXNUM_P checks // whether they point to a fixnum object. If they do, then we can safely assign our offset_* variables to the values. if(FIXNUM_P(opt_offset_x)){ offset_x = FIX2LONG(opt_offset_x); } if(FIXNUM_P(opt_offset_y)){ offset_y = FIX2LONG(opt_offset_y); } // Get the dimension data for both foreground and background images. long self_width = FIX2LONG(rb_funcall(self, rb_intern("width"), 0)); long self_height = FIX2LONG(rb_funcall(self, rb_intern("height"), 0)); long other_width = FIX2LONG(rb_funcall(other, rb_intern("width"), 0)); long other_height = FIX2LONG(rb_funcall(other, rb_intern("height"), 0)); // Make sure that the 'other' image fits within the current image. If it doesn't, an exception is raised // and the operation should be aborted. oily_png_check_size_constraints( self_width, self_height, other_width, other_height, offset_x, offset_y ); // Get the pixel data for both the foreground(other) and background(self) pixels. VALUE* bg_pixels = RARRAY_PTR(rb_funcall(self, rb_intern("pixels"), 0)); VALUE* fg_pixels = RARRAY_PTR(rb_funcall(other, rb_intern("pixels"), 0)); long x = 0; long y = 0; long bg_index = 0; // corresponds to the current index in the bg_pixels array. for( y = 0; y < other_height; y++ ){ for( x = 0; x < other_width; x++ ){ // We need to find the value of bg_index twice, so we only calculate and store it once. bg_index = ( x + offset_x ) + ( y + offset_y ) * self_width; // Replace the background pixel with the composition of background + foreground bg_pixels[bg_index] = fg_pixels[x+ y * other_width]; } } return self; } oily_png-1.1.0/ext/oily_png/color.c0000644000004100000410000000364712110154624017271 0ustar www-datawww-data#include "oily_png_ext.h" PIXEL oily_png_compose_color(PIXEL fg, PIXEL bg) { BYTE a_com, new_r, new_g, new_b, new_a; // Check for simple cases first if ((A_BYTE(fg) == 0xff) || (A_BYTE(bg) == 0x00)) return fg; if (A_BYTE(fg) == 0x00) return bg; // Calculate the new values using fast 8-bit multiplication a_com = INT8_MULTIPLY(0xff - A_BYTE(fg), A_BYTE(bg)); new_r = INT8_MULTIPLY(A_BYTE(fg), R_BYTE(fg)) + INT8_MULTIPLY(a_com, R_BYTE(bg)); new_g = INT8_MULTIPLY(A_BYTE(fg), G_BYTE(fg)) + INT8_MULTIPLY(a_com, G_BYTE(bg)); new_b = INT8_MULTIPLY(A_BYTE(fg), B_BYTE(fg)) + INT8_MULTIPLY(a_com, B_BYTE(bg)); new_a = A_BYTE(fg) + a_com; return BUILD_PIXEL(new_r, new_g, new_b, new_a); } PIXEL oily_png_color_interpolate_quick(PIXEL fg, PIXEL bg, int alpha) { BYTE a_com, new_r, new_g, new_b, new_a; if (alpha >= 255) return fg; if (alpha <= 0) return bg; a_com = 255 - alpha; new_r = INT8_MULTIPLY(alpha, R_BYTE(fg)) + INT8_MULTIPLY(a_com, R_BYTE(bg)); new_g = INT8_MULTIPLY(alpha, G_BYTE(fg)) + INT8_MULTIPLY(a_com, G_BYTE(bg)); new_b = INT8_MULTIPLY(alpha, B_BYTE(fg)) + INT8_MULTIPLY(a_com, B_BYTE(bg)); new_a = INT8_MULTIPLY(alpha, A_BYTE(fg)) + INT8_MULTIPLY(a_com, A_BYTE(bg)); return BUILD_PIXEL(new_r, new_g, new_b, new_a); } VALUE oily_png_color_compose_quick(VALUE self, VALUE fg_color, VALUE bg_color) { UNUSED_PARAMETER(self); return UINT2NUM(oily_png_compose_color(NUM2UINT(fg_color), NUM2UINT(bg_color))); } VALUE oily_png_color_r(VALUE self, VALUE value) { UNUSED_PARAMETER(self); return INT2FIX(R_BYTE(NUM2UINT(value))); } VALUE oily_png_color_g(VALUE self, VALUE value) { UNUSED_PARAMETER(self); return INT2FIX(G_BYTE(NUM2UINT(value))); } VALUE oily_png_color_b(VALUE self, VALUE value) { UNUSED_PARAMETER(self); return INT2FIX(B_BYTE(NUM2UINT(value))); } VALUE oily_png_color_a(VALUE self, VALUE value) { UNUSED_PARAMETER(self); return INT2FIX(A_BYTE(NUM2UINT(value))); } oily_png-1.1.0/ext/oily_png/resampling.h0000644000004100000410000000136112110154624020310 0ustar www-datawww-data#ifndef OILY_PNG_RESAMPLING_H #define OILY_PNG_RESAMPLING_H /* * Generates the interpolation steps (nearest neighbour) through two values. */ void oily_png_generate_steps_residues(long width, long new_width, long *steps, long *residues); /* * Generates the interpolation steps through two values. * * Returns a Ruby Array */ VALUE oily_png_canvas_steps_residues(VALUE self, VALUE width, VALUE new_width); VALUE oily_png_canvas_steps(VALUE self, VALUE width, VALUE new_width); /* * Performs nearest neighbor interpolation on the Canvas */ VALUE oily_png_canvas_resample_nearest_neighbor_bang(VALUE self, VALUE new_width, VALUE new_height); VALUE oily_png_canvas_resample_bilinear_bang(VALUE self, VALUE new_width, VALUE new_height); #endif oily_png-1.1.0/ext/oily_png/png_encoding.c0000644000004100000410000003070312110154624020576 0ustar www-datawww-data#include "oily_png_ext.h" ///// Scanline filtering functions ////////////////////////////////////////// void oily_png_encode_filter_sub(BYTE* bytes, long pos, long line_size, char pixel_size) { long x; for (x = line_size - 1; x > pixel_size; x--) { FILTER_BYTE(bytes[pos + x], bytes[pos + x - pixel_size]); } } void oily_png_encode_filter_up(BYTE* bytes, long pos, long line_size, char pixel_size) { UNUSED_PARAMETER(pixel_size); long x; if (pos >= line_size) { for (x = line_size - 1; x > 0; x--) { FILTER_BYTE(bytes[pos + x], bytes[pos + x - line_size]); } } } void oily_png_encode_filter_average(BYTE* bytes, long pos, long line_size, char pixel_size) { long x; BYTE a, b; for (x = line_size - 1; x > 0; x--) { a = (x > pixel_size) ? bytes[pos + x - pixel_size] : 0; b = (pos >= line_size) ? bytes[pos + x - line_size] : 0; FILTER_BYTE(bytes[pos + x], (a + b) >> 1); } } void oily_png_encode_filter_paeth(BYTE* bytes, long pos, long line_size, char pixel_size) { long x; int p, pa, pb, pc; BYTE a, b, c, pr; for (x = line_size - 1; x > 0; x--) { a = (x > pixel_size) ? bytes[pos + x - pixel_size] : 0; b = (pos >= line_size) ? bytes[pos + x - line_size] : 0; c = (pos >= line_size && x > pixel_size) ? bytes[pos + x - line_size - pixel_size] : 0; p = a + b - c; pa = abs(p - a); pb = abs(p - b); pc = abs(p - c); pr = (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c); FILTER_BYTE(bytes[pos + x], pr); } } ///// Scanline encoding functions ////////////////////////////////////////// // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons. // We'll uses the same to remain compatible with ChunkyPNG. void oily_png_encode_scanline_grayscale_1bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; BYTE p1, p2, p3, p4, p5, p6, p7, p8; for (x = 0; x < width; x += 8) { p1 = (x + 0 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 0))) >> 7); p2 = (x + 1 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 1))) >> 7); p3 = (x + 2 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 2))) >> 7); p4 = (x + 3 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 3))) >> 7); p5 = (x + 4 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 4))) >> 7); p6 = (x + 5 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 5))) >> 7); p7 = (x + 6 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 6))) >> 7); p8 = (x + 7 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 7))) >> 7); bytes[x >> 3] = (BYTE) ((p1 << 7) | (p2 << 6) | (p3 << 5) | (p4 << 4) | (p5 << 3) | (p6 << 2) | (p7 << 1) | (p8)); } } // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons. // We'll uses the same to remain compatible with ChunkyPNG. void oily_png_encode_scanline_grayscale_2bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; BYTE p1, p2, p3, p4; for (x = 0; x < width; x += 4) { p1 = (x + 0 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 0))) >> 6); p2 = (x + 1 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 1))) >> 6); p3 = (x + 2 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 2))) >> 6); p4 = (x + 3 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 3))) >> 6); bytes[x >> 2] = (BYTE) ((p1 << 6) | (p2 << 4) | (p3 << 2) | (p4)); } } // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons. // We'll uses the same to remain compatible with ChunkyPNG. void oily_png_encode_scanline_grayscale_4bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; BYTE p1, p2; for (x = 0; x < width; x += 2) { p1 = (x + 0 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 0))) >> 4); p2 = (x + 1 >= width) ? 0 : (B_BYTE(NUM2UINT(rb_ary_entry(pixels, y * width + x + 1))) >> 4); bytes[x >> 1] = (BYTE) ((p1 << 4) | (p2)); } } // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons. // We'll uses the same to remain compatible with ChunkyPNG. void oily_png_encode_scanline_grayscale_8bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; PIXEL pixel; for (x = 0; x < width; x++) { pixel = NUM2UINT(rb_ary_entry(pixels, y * width + x)); bytes[x] = B_BYTE(pixel); } } // Assume R == G == B. ChunkyPNG uses the B byte fot performance reasons. // We'll uses the same to remain compatible with ChunkyPNG. void oily_png_encode_scanline_grayscale_alpha_8bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; PIXEL pixel; for (x = 0; x < width; x++) { pixel = NUM2UINT(rb_ary_entry(pixels, y * width + x)); bytes[x * 2 + 0] = B_BYTE(pixel); bytes[x * 2 + 1] = A_BYTE(pixel); } } void oily_png_encode_scanline_indexed_8bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { long x; for (x = 0; x < width; x++) { bytes[x] = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x); } } void oily_png_encode_scanline_indexed_4bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { long x; BYTE p1, p2; for (x = 0; x < width; x += 2) { p1 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 0); p2 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 1); bytes[x >> 1] = (BYTE) ((p1 << 4) | (p2)); } } void oily_png_encode_scanline_indexed_2bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { long x; BYTE p1, p2, p3, p4; for (x = 0; x < width; x += 4) { p1 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 0); p2 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 1); p3 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 2); p4 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 3); bytes[x >> 2] = (BYTE) ((p1 << 6) | (p2 << 4) | (p3 << 2) | (p4)); } } void oily_png_encode_scanline_indexed_1bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { long x; BYTE p1, p2, p3, p4, p5, p6, p7, p8; for (x = 0; x < width; x += 8) { p1 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 0); p2 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 1); p3 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 2); p4 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 3); p5 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 4); p6 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 5); p7 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 6); p8 = ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x + 7); bytes[x >> 3] = (BYTE) ((p1 << 7) | (p2 << 6) | (p3 << 5) | (p4 << 4) | (p5 << 3) | (p6 << 2) | (p7 << 1) | (p8)); } } void oily_png_encode_scanline_truecolor_8bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; PIXEL pixel; for (x = 0; x < width; x++) { pixel = NUM2UINT(rb_ary_entry(pixels, y * width + x)); bytes[x * 3 + 0] = R_BYTE(pixel); bytes[x * 3 + 1] = G_BYTE(pixel); bytes[x * 3 + 2] = B_BYTE(pixel); } } void oily_png_encode_scanline_truecolor_alpha_8bit(BYTE* bytes, VALUE pixels, long y, long width, VALUE encoding_palette) { UNUSED_PARAMETER(encoding_palette); long x; PIXEL pixel; for (x = 0; x < width; x++) { pixel = NUM2UINT(rb_ary_entry(pixels, y * width + x)); bytes[x * 4 + 0] = R_BYTE(pixel); bytes[x * 4 + 1] = G_BYTE(pixel); bytes[x * 4 + 2] = B_BYTE(pixel); bytes[x * 4 + 3] = A_BYTE(pixel); } } scanline_encoder_func oily_png_encode_scanline_func(char color_mode, char bit_depth) { switch (color_mode) { case OILY_PNG_COLOR_GRAYSCALE: switch (bit_depth) { case 8: return &oily_png_encode_scanline_grayscale_8bit; case 4: return &oily_png_encode_scanline_grayscale_4bit; case 2: return &oily_png_encode_scanline_grayscale_2bit; case 1: return &oily_png_encode_scanline_grayscale_1bit; default: return NULL; } case OILY_PNG_COLOR_GRAYSCALE_ALPHA: switch (bit_depth) { case 8: return &oily_png_encode_scanline_grayscale_alpha_8bit; default: return NULL; } case OILY_PNG_COLOR_INDEXED: switch (bit_depth) { case 8: return &oily_png_encode_scanline_indexed_8bit; case 4: return &oily_png_encode_scanline_indexed_4bit; case 2: return &oily_png_encode_scanline_indexed_2bit; case 1: return &oily_png_encode_scanline_indexed_1bit; default: return NULL; } case OILY_PNG_COLOR_TRUECOLOR: switch (bit_depth) { case 8: return &oily_png_encode_scanline_truecolor_8bit; default: return NULL; } case OILY_PNG_COLOR_TRUECOLOR_ALPHA: switch (bit_depth) { case 8: return &oily_png_encode_scanline_truecolor_alpha_8bit; default: return NULL; } default: return NULL; } } ///////////////////////////////////////////////////////////////////// // ENCODING AN IMAGE PASS ///////////////////////////////////////////////////////////////////// VALUE oily_png_encode_palette(VALUE self) { VALUE palette_instance = rb_funcall(self, rb_intern("encoding_palette"), 0); if (palette_instance != Qnil) { VALUE encoding_map = rb_iv_get(palette_instance, "@encoding_map"); if (rb_funcall(encoding_map, rb_intern("kind_of?"), 1, rb_cHash) == Qtrue) { return encoding_map; } } rb_raise(rb_eRuntimeError, "Could not retrieve a decoding palette for this image!"); } VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE color_mode, VALUE bit_depth, VALUE filtering) { UNUSED_PARAMETER(bit_depth); // Get the data char depth = (char) FIX2INT(bit_depth); long width = FIX2LONG(rb_funcall(self, rb_intern("width"), 0)); long height = FIX2LONG(rb_funcall(self, rb_intern("height"), 0)); VALUE pixels = rb_funcall(self, rb_intern("pixels"), 0); if (RARRAY_LEN(pixels) != width * height) { rb_raise(rb_eRuntimeError, "The number of pixels does not match the canvas dimensions."); } // Get the encoding palette if we're encoding to an indexed bytestream. VALUE encoding_palette = Qnil; if (FIX2INT(color_mode) == OILY_PNG_COLOR_INDEXED) { encoding_palette = oily_png_encode_palette(self); } char pixel_size = oily_png_pixel_bytesize(FIX2INT(color_mode), depth); long line_size = oily_png_scanline_bytesize(FIX2INT(color_mode), depth, width); long pass_size = oily_png_pass_bytesize(FIX2INT(color_mode), depth, width, height); // Allocate memory for the byte array. BYTE* bytes = ALLOC_N(BYTE, pass_size); // Get the scanline encoder function. scanline_encoder_func scanline_encoder = oily_png_encode_scanline_func(FIX2INT(color_mode), depth); if (scanline_encoder == NULL) { rb_raise(rb_eRuntimeError, "No encoder for color mode %d and bit depth %d", FIX2INT(color_mode), depth); } long y, pos; for (y = height - 1; y >= 0; y--) { pos = line_size * y; bytes[pos] = (BYTE) FIX2INT(filtering); scanline_encoder(bytes + pos + 1, pixels, y, width, encoding_palette); } if (FIX2INT(filtering) != OILY_PNG_FILTER_NONE) { // Get the scanline filter function void (*scanline_filter)(BYTE*, long, long, char) = NULL; switch (FIX2INT(filtering)) { case OILY_PNG_FILTER_SUB: scanline_filter = &oily_png_encode_filter_sub; break; case OILY_PNG_FILTER_UP: scanline_filter = &oily_png_encode_filter_up; break; case OILY_PNG_FILTER_AVERAGE: scanline_filter = &oily_png_encode_filter_average; break; case OILY_PNG_FILTER_PAETH: scanline_filter = &oily_png_encode_filter_paeth; break; default: rb_raise(rb_eRuntimeError, "Unsupported filter type: %d", FIX2INT(filtering)); } for (y = height - 1; y >= 0; y--) { scanline_filter(bytes, line_size * y, line_size, pixel_size); } } // Append to encoded image pass to the output stream. rb_str_cat(stream, (char*) bytes, pass_size); xfree(bytes); return Qnil; } oily_png-1.1.0/ext/oily_png/color.h0000644000004100000410000000217112110154624017265 0ustar www-datawww-data#ifndef OILY_PNG_COLOR_H #define OILY_PNG_COLOR_H #define R_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0xff000000) >> 24)) #define G_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x00ff0000) >> 16)) #define B_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x0000ff00) >> 8)) #define A_BYTE(pixel) ((BYTE) (((pixel) & (PIXEL) 0x000000ff))) #define BUILD_PIXEL(r, g, b, a) (((PIXEL) (r) << 24) + ((PIXEL) (g) << 16) + ((PIXEL) (b) << 8) + (PIXEL) (a)) #define INT8_MULTIPLY(a, b) (((((a) * (b) + 0x80) >> 8) + ((a) * (b) + 0x80)) >> 8) /* Ruby replacement method for color composition using alpha transparency. This method should replace ChunkyPNG::Color.compose_quick */ VALUE oily_png_color_compose_quick(VALUE self, VALUE fg_color, VALUE bg_color); /* Color composition using alpha transparency. */ PIXEL oily_png_compose_color(PIXEL fg, PIXEL bg); PIXEL oily_png_color_interpolate_quick(PIXEL fg, PIXEL bg, int alpha); /* Accessors */ VALUE oily_png_color_r(VALUE self, VALUE pixel); VALUE oily_png_color_g(VALUE self, VALUE pixel); VALUE oily_png_color_b(VALUE self, VALUE pixel); VALUE oily_png_color_a(VALUE self, VALUE pixel); #endif oily_png-1.1.0/ext/oily_png/png_encoding.h0000644000004100000410000000161512110154624020603 0ustar www-datawww-data#ifndef OILY_PNG_PNG_ENCODING_H #define OILY_PNG_PNG_ENCODING_H #define FILTER_BYTE(byte, adjustment) byte = (BYTE) (((byte) - (adjustment)) & 0x000000ff) #define ENCODING_PALETTE_INDEX(encoding_palette, pixels, width, y, x) (((x) < (width)) ? ((BYTE) NUM2UINT(rb_hash_aref(encoding_palette, rb_ary_entry(pixels, (y) * (width) + (x))))) : 0) typedef void(*scanline_encoder_func)(BYTE*, VALUE, long, long, VALUE); /* Encodes an image and append it to the stream. A normal PNG will only have one pass and call this method once, while interlaced images are split up in 7 distinct images. This method will be called for every one of these images, reusing the stream. This function should replace ChunkyPNG::Canvas::PNGEncoding.encode_png_image_pass_to_stream */ VALUE oily_png_encode_png_image_pass_to_stream(VALUE self, VALUE stream, VALUE color_mode, VALUE bit_depth, VALUE filtering); #endif oily_png-1.1.0/ext/oily_png/oily_png_ext.c0000644000004100000410000000530312110154624020642 0ustar www-datawww-data#include "oily_png_ext.h" void Init_oily_png() { VALUE OilyPNG = rb_define_module("OilyPNG"); VALUE OilyPNG_Canvas = rb_define_module_under(OilyPNG, "Resampling"); rb_define_private_method(OilyPNG_Canvas, "steps_residues", oily_png_canvas_steps_residues, 2); rb_define_private_method(OilyPNG_Canvas, "steps", oily_png_canvas_steps, 2); rb_define_method(OilyPNG_Canvas, "resample_nearest_neighbor!", oily_png_canvas_resample_nearest_neighbor_bang, 2); rb_define_method(OilyPNG_Canvas, "resample_bilinear!", oily_png_canvas_resample_bilinear_bang, 2); // Setup decoding module VALUE OilyPNG_PNGDecoding = rb_define_module_under(OilyPNG, "PNGDecoding"); rb_define_method(OilyPNG_PNGDecoding, "decode_png_image_pass", oily_png_decode_png_image_pass, 6); // Setup encoding module VALUE OilyPNG_PNGEncoding = rb_define_module_under(OilyPNG, "PNGEncoding"); rb_define_method(OilyPNG_PNGEncoding, "encode_png_image_pass_to_stream", oily_png_encode_png_image_pass_to_stream, 4); // Setup Color module VALUE OilyPNG_Color = rb_define_module_under(OilyPNG, "Color"); rb_define_method(OilyPNG_Color, "compose_quick", oily_png_color_compose_quick, 2); rb_define_method(OilyPNG_Color, "r", oily_png_color_r, 1); rb_define_method(OilyPNG_Color, "g", oily_png_color_g, 1); rb_define_method(OilyPNG_Color, "b", oily_png_color_b, 1); rb_define_method(OilyPNG_Color, "a", oily_png_color_a, 1); // Setup Operations module VALUE OilyPNG_Operations = rb_define_module_under(OilyPNG, "Operations"); rb_define_method(OilyPNG_Operations, "compose!", oily_png_compose_bang, -1); rb_define_method(OilyPNG_Operations, "replace!", oily_png_replace_bang, -1); } char oily_png_samples_per_pixel(char color_mode) { switch (color_mode) { case OILY_PNG_COLOR_GRAYSCALE: return 1; case OILY_PNG_COLOR_TRUECOLOR: return 3; case OILY_PNG_COLOR_INDEXED: return 1; case OILY_PNG_COLOR_GRAYSCALE_ALPHA: return 2; case OILY_PNG_COLOR_TRUECOLOR_ALPHA: return 4; default: rb_raise(rb_eRuntimeError, "Unsupported color mode: %d", color_mode); } } char oily_png_pixel_bitsize(char color_mode, char bit_depth) { return oily_png_samples_per_pixel(color_mode) * bit_depth; } char oily_png_pixel_bytesize(char color_mode, char bit_depth) { return (bit_depth < 8) ? 1 : (oily_png_pixel_bitsize(color_mode, bit_depth) + 7) >> 3; } long oily_png_scanline_bytesize(char color_mode, char bit_depth, long width) { return (8 + ((oily_png_pixel_bitsize(color_mode, bit_depth) * width) + 7)) >> 3; } long oily_png_pass_bytesize(char color_mode, char bit_depth, long width, long height) { return (width == 0 || height == 0) ? 0 : (oily_png_scanline_bytesize(color_mode, bit_depth, width)) * height; } oily_png-1.1.0/ext/oily_png/png_decoding.h0000644000004100000410000000221112110154624020562 0ustar www-datawww-data#ifndef OILY_PNG_PNG_DECODING_H #define OILY_PNG_PNG_DECODING_H #define UNFILTER_BYTE(byte, adjustment) byte = (BYTE) (((byte) + (adjustment)) & 0x000000ff) #define ADD_PIXEL_FROM_PALLETE(pixels, decoding_palette, palette_entry) \ if (RARRAY_LEN(decoding_palette) > (palette_entry)) { \ rb_ary_push(pixels, rb_ary_entry(decoding_palette, (palette_entry))); \ } else { \ rb_raise(rb_eRuntimeError, "The decoding palette does not have %d entries!", (palette_entry)); \ } #define ADD_PIXEL_FROM_RGBA(pixels, r, g, b, a) rb_ary_push(pixels, UINT2NUM(BUILD_PIXEL(r,g,b,a))); typedef void(*scanline_decoder_func)(VALUE, BYTE*, long, long, VALUE); /* Decodes an image pass from the given byte stream at the given position. A normal PNG will only have one pass that consumes the entire stream, while an interlaced image requires 7 passes which are loaded from different starting positions. This function shouild replace ChunkyPNG::Canvas::PNGDecoding.decode_png_image_pass */ VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALUE height, VALUE color_mode, VALUE depth, VALUE start_pos); #endif oily_png-1.1.0/ext/oily_png/oily_png_ext.h0000644000004100000410000000413012110154624020644 0ustar www-datawww-data#ifndef OILY_PNG_OILY_PNG_EXT #define OILY_PNG_OILY_PNG_EXT #include "ruby.h" #define RSTRING_NOT_MODIFIED // PNG color mode constants #define OILY_PNG_COLOR_GRAYSCALE 0 #define OILY_PNG_COLOR_TRUECOLOR 2 #define OILY_PNG_COLOR_INDEXED 3 #define OILY_PNG_COLOR_GRAYSCALE_ALPHA 4 #define OILY_PNG_COLOR_TRUECOLOR_ALPHA 6 // PNG filter constants #define OILY_PNG_FILTER_NONE 0 #define OILY_PNG_FILTER_SUB 1 #define OILY_PNG_FILTER_UP 2 #define OILY_PNG_FILTER_AVERAGE 3 #define OILY_PNG_FILTER_PAETH 4 // Macro to surpress warnings about unused parameters. #define UNUSED_PARAMETER(param) (void) param // Type definitions typedef unsigned int PIXEL; // Pixels use 32 bits unsigned integers typedef unsigned char BYTE; // Bytes use 8 bits unsigned integers #include "png_decoding.h" #include "png_encoding.h" #include "color.h" #include "operations.h" #include "resampling.h" /* Initialize the extension by creating the OilyPNG modules, and registering the encoding and decoding replacement functions. Note, this does not actually replace functionality in ChunkyPNG; you will need to extend the ChunkyPNG::Canvas class with the OilyPNG::PNGDecoding module to speed up decoding, and include OilyPNG::PNGEncoding into the same class to speed up encoding. This is done in lib/oily_png.rb */ void Init_oily_png(); /* Returns the number of samples per pixel for a given color mode */ char oily_png_samples_per_pixel(char color_mode); /* Returns the number of bits per pixel for a given color mode and bit depth. */ char oily_png_pixel_bitsize(char color_mode, char bit_depth); /* Returns the number of bytes per pixel for a given color mode and bit depth. */ char oily_png_pixel_bytesize(char color_mode, char bit_depth); /* Returns the number of bytes per scanline for a given width, color mode and bit depth. */ long oily_png_scanline_bytesize(char color_mode, char bit_depth, long width); /* Returns the number of bytes in an image pass with the given properties. */ long oily_png_pass_bytesize(char color_mode, char bit_depth, long width, long height); #endif oily_png-1.1.0/ext/oily_png/png_decoding.c0000644000004100000410000003426612110154624020574 0ustar www-datawww-data#include "oily_png_ext.h" ///////////////////////////////////////////////////////////////////// // UNFILTERING SCANLINES ///////////////////////////////////////////////////////////////////// // Decodes a SUB filtered scanline at the given position in the byte array void oily_png_decode_filter_sub(BYTE* bytes, long pos, long line_length, char pixel_size) { long i; for (i = 1 + pixel_size; i < line_length; i++) { UNFILTER_BYTE(bytes[pos + i], bytes[pos + i - pixel_size]); } } // Decodes an UP filtered scanline at the given position in the byte array void oily_png_decode_filter_up(BYTE* bytes, long pos, long line_size, char pixel_size) { UNUSED_PARAMETER(pixel_size); long i; if (pos >= line_size) { // The first line is not filtered because there is no privous line for (i = 1; i < line_size; i++) { UNFILTER_BYTE(bytes[pos + i], bytes[pos + i - line_size]); } } } // Decodes an AVERAGE filtered scanline at the given position in the byte array void oily_png_decode_filter_average(BYTE* bytes, long pos, long line_size, char pixel_size) { long i; BYTE a, b; for (i = 1; i < line_size; i++) { a = (i > pixel_size) ? bytes[pos + i - pixel_size] : 0; b = (pos >= line_size) ? bytes[pos + i - line_size] : 0; UNFILTER_BYTE(bytes[pos + i], (a + b) >> 1); } } // Decodes a PAETH filtered scanline at the given position in the byte array void oily_png_decode_filter_paeth(BYTE* bytes, long pos, long line_size, char pixel_size) { BYTE a, b, c, pr; long i, p, pa, pb, pc; for (i = 1; i < line_size; i++) { a = (i > pixel_size) ? bytes[pos + i - pixel_size] : 0; b = (pos >= line_size) ? bytes[pos + i - line_size] : 0; c = (pos >= line_size && i > pixel_size) ? bytes[pos + i - line_size - pixel_size] : 0; p = a + b - c; pa = (p > a) ? p - a : a - p; pb = (p > b) ? p - b : b - p; pc = (p > c) ? p - c : c - p; pr = (pa <= pb) ? (pa <= pc ? a : c) : (pb <= pc ? b : c); UNFILTER_BYTE(bytes[pos + i], pr); } } ///////////////////////////////////////////////////////////////////// // BIT HANDLING ///////////////////////////////////////////////////////////////////// BYTE oily_png_extract_1bit_element(BYTE* bytes, long start, long x) { BYTE byte = bytes[start + 1 + (x >> 3)]; char bitshift = 7 - (x & (BYTE) 0x07); return (byte & (0x01 << bitshift)) >> bitshift; } BYTE oily_png_extract_2bit_element(BYTE* bytes, long start, long x) { BYTE byte = bytes[start + 1 + (x >> 2)]; char bitshift = (6 - ((x & (BYTE) 0x03) << 1)); return (byte & (0x03 << bitshift)) >> bitshift; } BYTE oily_png_extract_4bit_element(BYTE* bytes, long start, long x) { return ((x & 0x01) == 0) ? ((bytes[(start) + 1 + ((x) >> 1)] & (BYTE) 0xf0) >> 4) : (bytes[(start) + 1 + ((x) >> 1)] & (BYTE) 0x0f); } BYTE oily_png_resample_1bit_element(BYTE* bytes, long start, long x) { BYTE value = oily_png_extract_1bit_element(bytes, start, x); return (value == 0) ? 0x00 : 0xff; } BYTE oily_png_resample_2bit_element(BYTE* bytes, long start, long x) { return oily_png_extract_2bit_element(bytes, start, x) * 85; } BYTE oily_png_resample_4bit_element(BYTE* bytes, long start, long x) { return oily_png_extract_4bit_element(bytes, start, x) * 17; } ///////////////////////////////////////////////////////////////////// // PIXEL DECODING SCANLINES ///////////////////////////////////////////////////////////////////// void oily_png_decode_scanline_grayscale_1bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, oily_png_resample_1bit_element(bytes, start, x), oily_png_resample_1bit_element(bytes, start, x), oily_png_resample_1bit_element(bytes, start, x), 0xff); } } void oily_png_decode_scanline_grayscale_2bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, oily_png_resample_2bit_element(bytes, start, x), oily_png_resample_2bit_element(bytes, start, x), oily_png_resample_2bit_element(bytes, start, x), 0xff); } } void oily_png_decode_scanline_grayscale_4bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, oily_png_resample_4bit_element(bytes, start, x), oily_png_resample_4bit_element(bytes, start, x), oily_png_resample_4bit_element(bytes, start, x), 0xff); } } void oily_png_decode_scanline_grayscale_8bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + x], bytes[start + 1 + x], bytes[start + 1 + x], 0xff); } } void oily_png_decode_scanline_grayscale_16bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 2)], bytes[start + 1 + (x * 2)], bytes[start + 1 + (x * 2)], 0xff); } } void oily_png_decode_scanline_grayscale_alpha_8bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 2) + 0], bytes[start + 1 + (x * 2) + 0], bytes[start + 1 + (x * 2) + 0], bytes[start + 1 + (x * 2) + 1]); } } void oily_png_decode_scanline_grayscale_alpha_16bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 4) + 0], bytes[start + 1 + (x * 4) + 0], bytes[start + 1 + (x * 4) + 0], bytes[start + 1 + (x * 4) + 2]); } } void oily_png_decode_scanline_indexed_1bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_PALLETE(pixels, decoding_palette, oily_png_extract_1bit_element(bytes, start, x)); } } void oily_png_decode_scanline_indexed_2bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_PALLETE(pixels, decoding_palette, oily_png_extract_2bit_element(bytes, start, x)); } } void oily_png_decode_scanline_indexed_4bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_PALLETE(pixels, decoding_palette, oily_png_extract_4bit_element(bytes, start, x)); } } void oily_png_decode_scanline_indexed_8bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_PALLETE(pixels, decoding_palette, bytes[start + 1 + x]); } } void oily_png_decode_scanline_truecolor_8bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 3) + 0], bytes[start + 1 + (x * 3) + 1], bytes[start + 1 + (x * 3) + 2], 0xff); } } void oily_png_decode_scanline_truecolor_16bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 6) + 0], bytes[start + 1 + (x * 6) + 2], bytes[start + 1 + (x * 6) + 4], 0xff); } } void oily_png_decode_scanline_truecolor_alpha_8bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 4) + 0], bytes[start + 1 + (x * 4) + 1], bytes[start + 1 + (x * 4) + 2], bytes[start + 1 + (x * 4) + 3]); } } void oily_png_decode_scanline_truecolor_alpha_16bit(VALUE pixels, BYTE* bytes, long start, long width, VALUE decoding_palette) { UNUSED_PARAMETER(decoding_palette); long x; for (x = 0; x < width; x++) { ADD_PIXEL_FROM_RGBA(pixels, bytes[start + 1 + (x * 8) + 0], bytes[start + 1 + (x * 8) + 2], bytes[start + 1 + (x * 8) + 4], bytes[start + 1 + (x * 8) + 6]); } } scanline_decoder_func oily_png_decode_scanline_func(int color_mode, int bit_depth) { switch (color_mode) { case OILY_PNG_COLOR_GRAYSCALE: switch (bit_depth) { case 1: return &oily_png_decode_scanline_grayscale_1bit; case 2: return &oily_png_decode_scanline_grayscale_2bit; case 4: return &oily_png_decode_scanline_grayscale_4bit; case 8: return &oily_png_decode_scanline_grayscale_8bit; case 16: return &oily_png_decode_scanline_grayscale_16bit; default: return NULL; } case OILY_PNG_COLOR_TRUECOLOR: switch (bit_depth) { case 8: return &oily_png_decode_scanline_truecolor_8bit; case 16: return &oily_png_decode_scanline_truecolor_16bit; default: return NULL; } case OILY_PNG_COLOR_INDEXED: switch (bit_depth) { case 1: return &oily_png_decode_scanline_indexed_1bit; case 2: return &oily_png_decode_scanline_indexed_2bit; case 4: return &oily_png_decode_scanline_indexed_4bit; case 8: return &oily_png_decode_scanline_indexed_8bit; default: return NULL; } case OILY_PNG_COLOR_GRAYSCALE_ALPHA: switch (bit_depth) { case 8: return &oily_png_decode_scanline_grayscale_alpha_8bit; case 16: return &oily_png_decode_scanline_grayscale_alpha_16bit; default: return NULL; } case OILY_PNG_COLOR_TRUECOLOR_ALPHA: switch (bit_depth) { case 8: return &oily_png_decode_scanline_truecolor_alpha_8bit; case 16: return &oily_png_decode_scanline_truecolor_alpha_16bit; default: return NULL; } default: return NULL; } } ///////////////////////////////////////////////////////////////////// // DECODING AN IMAGE PASS ///////////////////////////////////////////////////////////////////// VALUE oily_png_decode_palette(VALUE self) { VALUE palette_instance = rb_funcall(self, rb_intern("decoding_palette"), 0); if (palette_instance != Qnil) { VALUE decoding_map = rb_iv_get(palette_instance, "@decoding_map"); if (rb_funcall(decoding_map, rb_intern("kind_of?"), 1, rb_cArray) == Qtrue) { return decoding_map; } } rb_raise(rb_eRuntimeError, "Could not retrieve a decoding palette for this image!"); } VALUE oily_png_decode_png_image_pass(VALUE self, VALUE stream, VALUE width, VALUE height, VALUE color_mode, VALUE depth, VALUE start_pos) { VALUE pixels = rb_ary_new(); if ((FIX2LONG(height) > 0) && (FIX2LONG(width) > 0)) { char pixel_size = oily_png_pixel_bytesize(FIX2INT(color_mode), FIX2INT(depth)); long line_size = oily_png_scanline_bytesize(FIX2INT(color_mode), FIX2INT(depth), FIX2LONG(width)); long pass_size = oily_png_pass_bytesize(FIX2INT(color_mode), FIX2INT(depth), FIX2LONG(width), FIX2LONG(height)); // Make sure that the stream is large enough to contain our pass. if (RSTRING_LEN(stream) < pass_size + FIX2LONG(start_pos)) { rb_raise(rb_eRuntimeError, "The length of the stream is too short to contain the image!"); } // Copy the bytes for this pass from the stream to a separate location // so we can work on this byte array directly. BYTE* bytes = ALLOC_N(BYTE, pass_size); memcpy(bytes, RSTRING_PTR(stream) + FIX2LONG(start_pos), pass_size); // Get the decoding palette for indexed images. VALUE decoding_palette = Qnil; if (FIX2INT(color_mode) == OILY_PNG_COLOR_INDEXED) { decoding_palette = oily_png_decode_palette(self); } // Select the scanline decoder function for this color mode and bit depth. scanline_decoder_func scanline_decoder = oily_png_decode_scanline_func(FIX2INT(color_mode), FIX2INT(depth)); if (scanline_decoder == NULL) { rb_raise(rb_eRuntimeError, "No decoder for color mode %d and bit depth %d", FIX2INT(color_mode), FIX2INT(depth)); } long y, line_start; for (y = 0; y < FIX2LONG(height); y++) { line_start = y * line_size; // Apply filering to the line switch (bytes[line_start]) { case OILY_PNG_FILTER_NONE: break; case OILY_PNG_FILTER_SUB: oily_png_decode_filter_sub( bytes, line_start, line_size, pixel_size); break; case OILY_PNG_FILTER_UP: oily_png_decode_filter_up( bytes, line_start, line_size, pixel_size); break; case OILY_PNG_FILTER_AVERAGE: oily_png_decode_filter_average( bytes, line_start, line_size, pixel_size); break; case OILY_PNG_FILTER_PAETH: oily_png_decode_filter_paeth( bytes, line_start, line_size, pixel_size); break; default: rb_raise(rb_eRuntimeError, "Filter type not supported: %d", bytes[line_start]); } // Set the filter byte to 0 because the bytearray is now unfiltered. bytes[line_start] = OILY_PNG_FILTER_NONE; scanline_decoder(pixels, bytes, line_start, FIX2LONG(width), decoding_palette); } xfree(bytes); } // Now, return a new ChunkyPNG::Canvas instance with the decoded pixels. return rb_funcall(self, rb_intern("new"), 3, width, height, pixels); } oily_png-1.1.0/ext/oily_png/operations.h0000644000004100000410000000304312110154624020331 0ustar www-datawww-data#ifndef OILY_PNG_OPERATIONS_H #define OILY_PNG_OPERATIONS_H /* Checks whether an image 'other' can fits into 'self'. Takes offset into account. An exception is raised if the check fails. Instead of taking in an object 'self' and an object 'other' and then calculating their parameters, we ask for the respective height and width directly. This is because these variables will need to be calculated by 'rb_intern()' within the method calling oily_png_check_size_constraints (ex: oily_png_compose), so there's no use in calculating them twice. */ void oily_png_check_size_constraints(long self_width, long self_height, long other_width, long other_height, long offset_x, long offset_y); /* C replacement method for composing another image onto this image using alpha blending. TODO: Implement functionality with ChunkyPNG and OilyPNG so that an image can be composited onto another regardless of its size: however, only the intersecting elements of both images should be mixed. This method should replace ChunkyPNG::Canvas.compose! */ VALUE oily_png_compose_bang(int argc, VALUE *argv, VALUE c); /* C replacement method for composing another image onto this image by simply replacing pixels. TODO: Implement functionality with ChunkyPNG and OilyPNG so that an image can be composited onto another regardless of its size: however, only the intersecting elements of both images should be mixed. This method should replace ChunkyPNG::Canvas.replace! */ VALUE oily_png_replace_bang(int argc, VALUE *argv, VALUE c); #endif oily_png-1.1.0/tasks/0000755000004100000410000000000012110154624014502 5ustar www-datawww-dataoily_png-1.1.0/tasks/testing.rake0000644000004100000410000000362412110154624017030 0ustar www-datawww-datatask(:verify, :png_file) do |task, args| require 'rubygems' require 'bundler/setup' require 'chunky_png' require 'oily_png/oily_png_ext' class OilyPNG::Canvas < ChunkyPNG::Canvas extend OilyPNG::PNGDecoding include OilyPNG::PNGEncoding end file = args[:png_file] || ENV['PNG_FILE'] raise "Please specify a valid PNG file to verify!" unless File.exist?(file.to_s) decoding_reference = ChunkyPNG::Canvas.from_file(file) decoding_oily_png = OilyPNG::Canvas.from_file(file) if decoding_reference == decoding_oily_png puts "Decoding test succeeded!" else puts "Decoding test FAILED!" end oily_png = OilyPNG::Canvas.from_canvas(decoding_reference) [ChunkyPNG::FILTER_NONE, ChunkyPNG::FILTER_SUB, ChunkyPNG::FILTER_UP, ChunkyPNG::FILTER_AVERAGE, ChunkyPNG::FILTER_PAETH].each do |filter_method| encoding_reference = decoding_reference.to_blob(:filtering => filter_method, :color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA) encoding_oily_png = oily_png.to_blob(:filtering => filter_method, :color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA) if encoding_reference == encoding_oily_png puts "Encoding test succeeded for filter method #{filter_method}!" else puts "Encoding test FAILED for filter method #{filter_method}!" end end [ChunkyPNG::COLOR_GRAYSCALE, ChunkyPNG::COLOR_GRAYSCALE_ALPHA, ChunkyPNG::COLOR_INDEXED, ChunkyPNG::COLOR_TRUECOLOR, ChunkyPNG::COLOR_TRUECOLOR_ALPHA].each do |color_mode| encoding_reference = decoding_reference.to_blob(:filtering => ChunkyPNG::FILTER_NONE, :color_mode => color_mode) encoding_oily_png = oily_png.to_blob(:filtering => ChunkyPNG::FILTER_NONE, :color_mode => color_mode) if encoding_reference == encoding_oily_png puts "Encoding test succeeded for color mode #{color_mode}!" else puts "Decoding test FAILED for color mode #{color_mode}!" end end end oily_png-1.1.0/tasks/github-gem.rake0000644000004100000410000003201512110154624017377 0ustar www-datawww-datarequire 'rubygems' require 'rake' require 'rake/tasklib' require 'date' require 'set' module GithubGem # Detects the gemspc file of this project using heuristics. def self.detect_gemspec_file FileList['*.gemspec'].first end # Detects the main include file of this project using heuristics def self.detect_main_include if File.exist?(File.expand_path("../lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb", detect_gemspec_file)) "lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb" elsif FileList['lib/*.rb'].length == 1 FileList['lib/*.rb'].first else nil end end class RakeTasks include Rake::DSL if Rake.const_defined?('DSL') attr_reader :gemspec, :modified_files attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch # Initializes the settings, yields itself for configuration # and defines the rake tasks based on the gemspec file. def initialize(task_namespace = :gem) @gemspec_file = GithubGem.detect_gemspec_file @task_namespace = task_namespace @main_include = GithubGem.detect_main_include @modified_files = Set.new @root_dir = Dir.pwd @test_pattern = 'test/**/*_test.rb' @spec_pattern = 'spec/**/*_spec.rb' @local_branch = 'master' @remote = 'origin' @remote_branch = 'master' yield(self) if block_given? load_gemspec! define_tasks! end protected def git @git ||= ENV['GIT'] || 'git' end # Define Unit test tasks def define_test_tasks! require 'rake/testtask' namespace(:test) do Rake::TestTask.new(:basic) do |t| t.pattern = test_pattern t.verbose = true t.libs << 'test' end end desc "Run all unit tests for #{gemspec.name}" task(:test => ['test:basic']) end # Defines RSpec tasks def define_rspec_tasks! require 'rspec/core/rake_task' namespace(:spec) do desc "Verify all RSpec examples for #{gemspec.name}" RSpec::Core::RakeTask.new(:basic) do |t| t.pattern = spec_pattern end desc "Verify all RSpec examples for #{gemspec.name} and output specdoc" RSpec::Core::RakeTask.new(:specdoc) do |t| t.pattern = spec_pattern t.rspec_opts = ['--format', 'documentation', '--color'] end desc "Run RCov on specs for #{gemspec.name}" RSpec::Core::RakeTask.new(:rcov) do |t| t.pattern = spec_pattern t.rcov = true t.rcov_opts = ['--exclude', '"spec/*,gems/*"', '--rails'] end end desc "Verify all RSpec examples for #{gemspec.name} and output specdoc" task(:spec => ['spec:specdoc']) end # Defines the rake tasks def define_tasks! define_test_tasks! if has_tests? define_rspec_tasks! if has_specs? namespace(@task_namespace) do desc "Updates the filelist in the gemspec file" task(:manifest) { manifest_task } desc "Builds the .gem package" task(:build => :manifest) { build_task } desc "Sets the version of the gem in the gemspec" task(:set_version => [:check_version, :check_current_branch]) { version_task } task(:check_version => :fetch_origin) { check_version_task } task(:fetch_origin) { fetch_origin_task } task(:check_current_branch) { check_current_branch_task } task(:check_clean_status) { check_clean_status_task } task(:check_not_diverged => :fetch_origin) { check_not_diverged_task } checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version] checks.unshift('spec:basic') if has_specs? checks.unshift('test:basic') if has_tests? # checks.push << [:check_rubyforge] if gemspec.rubyforge_project desc "Perform all checks that would occur before a release" task(:release_checks => checks) release_tasks = [:release_checks, :set_version, :build, :github_release, :gemcutter_release] # release_tasks << [:rubyforge_release] if gemspec.rubyforge_project desc "Release a new version of the gem using the VERSION environment variable" task(:release => release_tasks) { release_task } namespace(:release) do desc "Release the next version of the gem, by incrementing the last version segment by 1" task(:next => [:next_version] + release_tasks) { release_task } desc "Release the next version of the gem, using a patch increment (0.0.1)" task(:patch => [:next_patch_version] + release_tasks) { release_task } desc "Release the next version of the gem, using a minor increment (0.1.0)" task(:minor => [:next_minor_version] + release_tasks) { release_task } desc "Release the next version of the gem, using a major increment (1.0.0)" task(:major => [:next_major_version] + release_tasks) { release_task } end # task(:check_rubyforge) { check_rubyforge_task } # task(:rubyforge_release) { rubyforge_release_task } task(:gemcutter_release) { gemcutter_release_task } task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task } task(:tag_version) { tag_version_task } task(:commit_modified_files) { commit_modified_files_task } task(:next_version) { next_version_task } task(:next_patch_version) { next_version_task(:patch) } task(:next_minor_version) { next_version_task(:minor) } task(:next_major_version) { next_version_task(:major) } desc "Updates the gem release tasks with the latest version on Github" task(:update_tasks) { update_tasks_task } end end # Updates the files list and test_files list in the gemspec file using the list of files # in the repository and the spec/test file pattern. def manifest_task # Load all the gem's files using "git ls-files" repository_files = `#{git} ls-files`.split("\n") test_files = Dir[test_pattern] + Dir[spec_pattern] update_gemspec(:files, repository_files) update_gemspec(:test_files, repository_files & test_files) end # Builds the gem def build_task sh "gem build -q #{gemspec_file}" Dir.mkdir('pkg') unless File.exist?('pkg') sh "mv #{gemspec.name}-#{gemspec.version}.gem pkg/#{gemspec.name}-#{gemspec.version}.gem" end def newest_version `#{git} tag`.split("\n").map { |tag| tag.split('-').last }.compact.map { |v| Gem::Version.new(v) }.max || Gem::Version.new('0.0.0') end def next_version(increment = nil) next_version = newest_version.segments increment_index = case increment when :micro then 3 when :patch then 2 when :minor then 1 when :major then 0 else next_version.length - 1 end next_version[increment_index] ||= 0 next_version[increment_index] = next_version[increment_index].succ ((increment_index + 1)...next_version.length).each { |i| next_version[i] = 0 } Gem::Version.new(next_version.join('.')) end def next_version_task(increment = nil) ENV['VERSION'] = next_version(increment).version puts "Releasing version #{ENV['VERSION']}..." end # Updates the version number in the gemspec file, the VERSION constant in the main # include file and the contents of the VERSION file. def version_task update_gemspec(:version, ENV['VERSION']) if ENV['VERSION'] update_gemspec(:date, Date.today) update_version_file(gemspec.version) update_version_constant(gemspec.version) end def check_version_task raise "#{ENV['VERSION']} is not a valid version number!" if ENV['VERSION'] && !Gem::Version.correct?(ENV['VERSION']) proposed_version = Gem::Version.new((ENV['VERSION'] || gemspec.version).dup) raise "This version (#{proposed_version}) is not higher than the highest tagged version (#{newest_version})" if newest_version >= proposed_version end # Checks whether the current branch is not diverged from the remote branch def check_not_diverged_task raise "The current branch is diverged from the remote branch!" if `#{git} rev-list HEAD..#{remote}/#{remote_branch}`.split("\n").any? end # Checks whether the repository status ic clean def check_clean_status_task raise "The current working copy contains modifications" if `#{git} ls-files -m`.split("\n").any? end # Checks whether the current branch is correct def check_current_branch_task raise "Currently not on #{local_branch} branch!" unless `#{git} branch`.split("\n").detect { |b| /^\* / =~ b } == "* #{local_branch}" end # Fetches the latest updates from Github def fetch_origin_task sh git, 'fetch', remote end # Commits every file that has been changed by the release task. def commit_modified_files_task really_modified = `#{git} ls-files -m #{modified_files.entries.join(' ')}`.split("\n") if really_modified.any? really_modified.each { |file| sh git, 'add', file } sh git, 'commit', '-m', "Released #{gemspec.name} gem version #{gemspec.version}." end end # Adds a tag for the released version def tag_version_task sh git, 'tag', '-a', "#{gemspec.name}-#{gemspec.version}", '-m', "Released #{gemspec.name} gem version #{gemspec.version}." end # Pushes the changes and tag to github def github_release_task sh git, 'push', '--tags', remote, remote_branch end def gemcutter_release_task sh "gem", 'push', "pkg/#{gemspec.name}-#{gemspec.version}.gem" end # Gem release task. # All work is done by the task's dependencies, so just display a release completed message. def release_task puts puts "Release successful." end private # Checks whether this project has any RSpec files def has_specs? FileList[spec_pattern].any? end # Checks whether this project has any unit test files def has_tests? FileList[test_pattern].any? end # Loads the gemspec file def load_gemspec! @gemspec = eval(File.read(@gemspec_file)) end # Updates the VERSION file with the new version def update_version_file(version) if File.exists?('VERSION') File.open('VERSION', 'w') { |f| f << version.to_s } modified_files << 'VERSION' end end # Updates the VERSION constant in the main include file if it exists def update_version_constant(version) if main_include && File.exist?(main_include) file_contents = File.read(main_include) if file_contents.sub!(/^(\s+VERSION\s*=\s*)[^\s].*$/) { $1 + version.to_s.inspect } File.open(main_include, 'w') { |f| f << file_contents } modified_files << main_include end end end # Updates an attribute of the gemspec file. # This function will open the file, and search/replace the attribute using a regular expression. def update_gemspec(attribute, new_value, literal = false) unless literal new_value = case new_value when Array then "%w(#{new_value.join(' ')})" when Hash, String then new_value.inspect when Date then new_value.strftime('%Y-%m-%d').inspect else raise "Cannot write value #{new_value.inspect} to gemspec file!" end end spec = File.read(gemspec_file) regexp = Regexp.new('^(\s+\w+\.' + Regexp.quote(attribute.to_s) + '\s*=\s*)[^\s].*$') if spec.sub!(regexp) { $1 + new_value } File.open(gemspec_file, 'w') { |f| f << spec } modified_files << gemspec_file # Reload the gemspec so the changes are incorporated load_gemspec! # Also mark the Gemfile.lock file as changed because of the new version. modified_files << 'Gemfile.lock' if File.exist?(File.join(root_dir, 'Gemfile.lock')) end end # Updates the tasks file using the latest file found on Github def update_tasks_task require 'net/https' require 'uri' uri = URI.parse('https://raw.github.com/wvanbergen/github-gem/master/tasks/github-gem.rake') http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE response = http.request(Net::HTTP::Get.new(uri.path)) if Net::HTTPSuccess === response open(__FILE__, "w") { |file| file.write(response.body) } relative_file = File.expand_path(__FILE__).sub(%r[^#{@root_dir}/], '') if `#{git} ls-files -m #{relative_file}`.split("\n").any? sh git, 'add', relative_file sh git, 'commit', '-m', "Updated to latest gem release management tasks." else puts "Release managament tasks already are at the latest version." end else raise "Download failed with HTTP status #{response.code}!" end end end end oily_png-1.1.0/LICENSE0000644000004100000410000000204512110154624014363 0ustar www-datawww-dataCopyright (c) 2010 Willem van Bergen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. oily_png-1.1.0/README.rdoc0000644000004100000410000000174612110154624015173 0ustar www-datawww-data= OilyPNG OilyPNG is a Ruby C extension to speed up the pure Ruby ChunkyPNG library. It is a standalone module, so it does not require LibPNG, ImageMagick or any other library. Currently it has an alternative implementation of decoding and encoding PNGs, making these operations much faster, especially for PNG images that apply filtering. Performance comparison: http://gist.github.com/611255 *Warning*: this is my first C code in years. It may blow up your PC after leaking memory all over the place, killing a kitten in the process. You have been warned. == Usage 1. First install the gem and make it available to your project. 2. Use require "oily_png" instead of require "chunky_png" 3. Presto! Now use ChunkyPNG as you normally would and get an instant speedup. See http://github.com/wvanbergen/chunky_png/wiki for more information on how to use the ChunkyPNG API. == About License: MIT (see LICENSE) This C module is written by Willem van Bergen with help from Dirkjan Bussink. oily_png-1.1.0/Rakefile0000644000004100000410000000074212110154624015025 0ustar www-datawww-dataDir['tasks/*.rake'].each { |file| load(file) } require 'rake/extensiontask' gem_management_tasks = GithubGem::RakeTasks.new(:gem) Rake::ExtensionTask.new('oily_png', gem_management_tasks.gemspec) do |ext| ext.lib_dir = File.join('lib', 'oily_png') end Rake::Task['spec'].prerequisites << :compile Rake::Task['spec:basic'].prerequisites << :compile Rake::Task['spec:rcov'].prerequisites << :compile Rake::Task['spec:specdoc'].prerequisites << :compile task :default => [:spec] oily_png-1.1.0/.infinity_test0000644000004100000410000000077012110154624016252 0ustar www-datawww-datainfinity_test do use :rubies => %w(1.8.6 1.8.7 1.9.2 ree rbx), :test_framework => :rspec before(:each_ruby) do |environment| environment.system('bundle install') environment.system('rake compile') end after(:each_ruby) do |environment| environment.system("rake clean_and_clobber_without_verbose") end heuristics do add("^ext/*/(.*)\.c") do |file| run :all => :tests end add("^ext/*/(.*)\.h") do |file| run :all => :tests end end end oily_png-1.1.0/spec/0000755000004100000410000000000012110154624014307 5ustar www-datawww-dataoily_png-1.1.0/spec/resampling_spec.rb0000644000004100000410000000373312110154624020015 0ustar www-datawww-datarequire 'spec_helper' describe OilyPNG::Resampling do include OilyPNG::Resampling describe '#steps' do it "should generate the steps from 4 to 8 as [0,0,1,1,2,2,3,3]" do steps(4,8).should == [0,0,1,1,2,2,3,3] end it "should generate the steps the same as ChunkyPNG" do image = ChunkyPNG::Image.new(1,1) steps(2,8).should == image.send(:steps,2,8) steps(2,11).should == image.send(:steps,2,11) steps(11,5).should == image.send(:steps,11,5) end end describe '#resample_nearest_neighbor!' do before(:all) { @reference = ChunkyPNG::Canvas.from_file(resource_file('nonsquare.png'))} it "should resample [0,1,2,3] to 4x4 properly" do OilyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(4,4).should == OilyPNG::Canvas.new(4,4,[0,0,1,1,0,0,1,1,2,2,3,3,2,2,3,3]) end it "should resample [0,1,2,3] to 99x45 as ChunkyPNG does" do ChunkyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(99,45).should == OilyPNG::Canvas.new(2,2,[0,1,2,3]).resample_nearest_neighbor(99,45) end it "should resample an image to 10x20 as ChunkyPNG does" do @reference.resample_nearest_neighbor(10,20).should == OilyPNG::Canvas.from_canvas(@reference).resample_nearest_neighbor(10,20) end it "should resample an image to 11x19 as ChunkyPNG does" do @reference.resample_nearest_neighbor(11,19).should == OilyPNG::Canvas.from_canvas(@reference).resample_nearest_neighbor(11,19) end end describe '#resample_bilinear!' do before(:all) { @reference = ChunkyPNG::Canvas.from_file(resource_file('nonsquare.png'))} it "should resample an image to 10x20 as ChunkyPNG does" do @reference.resample_bilinear(10,20).should == OilyPNG::Canvas.from_canvas(@reference).resample_bilinear(10,20) end it "should resample an image to 11x19 as ChunkyPNG does" do @reference.resample_bilinear(11,19).should == OilyPNG::Canvas.from_canvas(@reference).resample_bilinear(11,19) end end end oily_png-1.1.0/spec/spec_helper.rb0000644000004100000410000000155012110154624017126 0ustar www-datawww-datarequire 'rubygems' require 'bundler/setup' require 'chunky_png' require 'oily_png/canvas' module ResourceHelper def resource_files Dir[File.join(File.dirname(__FILE__), 'resources', '*.png')] end end module CanvasHelper def resource_files(pattern = "*.png") Dir[File.join(File.dirname(__FILE__), 'resources', pattern)] end def resource_file(name) File.join(File.dirname(__FILE__), 'resources', name) end def display(canvas) filename = resource_file('_tmp.png') canvas.to_datastream.save(filename) `open #{filename}` end def reference_canvas(name) ChunkyPNG::Canvas.from_file(resource_file("#{name}.png")) end def oily_reference_canvas(name) OilyPNG::Canvas.from_file(resource_file("#{name}.png")) end end RSpec.configure do |config| config.extend ResourceHelper config.include CanvasHelper end oily_png-1.1.0/spec/decoding_spec.rb0000644000004100000410000000426212110154624017426 0ustar www-datawww-datarequire 'spec_helper' describe OilyPNG::PNGDecoding do it "should call ChunkyPNG::Color.pixel_bytesize in the pure ruby version" do ChunkyPNG::Color.should_receive(:pixel_bytesize).and_return(3) ChunkyPNG::Canvas.from_file(resource_file('square.png')) end it "should not call ChunkyPNG::Color.pixel_bytesize in the native version" do ChunkyPNG::Color.should_not_receive(:pixel_bytesize) OilyPNG::Canvas.from_file(resource_file('square.png')) end context 'decoding different filtering methods' do before(:all) { @reference = ChunkyPNG::Canvas.from_file(resource_file('nonsquare.png'))} it "should decode NONE filtering exactly the same as ChunkyPNG" do filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_NONE) ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data) end it "should decode SUB filtering exactly the same as ChunkyPNG" do filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_SUB) ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data) end it "should decode UP filtering exactly the same as ChunkyPNG" do filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_UP) ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data) end it "should decode AVERAGE filtering exactly the same as ChunkyPNG" do filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_AVERAGE) ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data) end it "should decode PAETH filtering exactly the same as ChunkyPNG" do filtered_data = @reference.to_blob(:filtering => ChunkyPNG::FILTER_PAETH) ChunkyPNG::Canvas.from_blob(filtered_data).should == OilyPNG::Canvas.from_blob(filtered_data) end end context 'decoding compatibility with ChunkyPNG' do resource_files.each do |file| it "should #{File.basename(file)} the same as ChunkyPNG" do OilyPNG::Canvas.from_file(file).pixels.should == ChunkyPNG::Canvas.from_file(file).pixels end end end end oily_png-1.1.0/spec/operations_spec.rb0000644000004100000410000000416512110154624020037 0ustar www-datawww-datarequire 'spec_helper' describe OilyPNG::Operations do describe '#compose!' do subject { oily_reference_canvas('operations') } it "should compose two images without offset exactly the same way as ChunkyPNG" do subcanvas = ChunkyPNG::Canvas.new(4, 8, ChunkyPNG::Color.rgba(0, 0, 0, 75)) subject.compose!(subcanvas) ChunkyPNG::Canvas.from_canvas(subject).should == reference_canvas('operations').compose(subcanvas) end it "should compose two images with offset exactly the same way as ChunkyPNG" do subject.compose!(ChunkyPNG::Canvas.new(4, 8, ChunkyPNG::Color.rgba(0, 0, 0, 75)), 8, 4) subject.should == oily_reference_canvas('composited') end it "should return itself" do subject.compose!(OilyPNG::Canvas.new(1,1)).should equal(subject) end it "should raise an exception when the pixels to compose fall outside the image" do # For now this raises a runtime error, but it should probably raise a ChunkyPNG::OutOfBounds error lambda { subject.compose!(OilyPNG::Canvas.new(1,1), 16, 16) }.should raise_error end end describe '#replace!' do subject { oily_reference_canvas('operations') } it "should compose two images without offset exactly the same way as ChunkyPNG" do subcanvas = ChunkyPNG::Canvas.new(3, 2, ChunkyPNG::Color.rgb(200, 255, 0)) subject.replace!(subcanvas) ChunkyPNG::Canvas.from_canvas(subject).should == reference_canvas('operations').replace(subcanvas) end it "should compose two images with offset exactly the same way as ChunkyPNG" do subject.replace!(ChunkyPNG::Canvas.new(3, 2, ChunkyPNG::Color.rgb(200, 255, 0)), 5, 4) subject.should == oily_reference_canvas('replaced') end it "should return itself" do subject.replace!(OilyPNG::Canvas.new(1,1)).should equal(subject) end it "should raise an exception when the pixels to compose fall outside the image" do # For now this raises a runtime error, but it should probably raise a ChunkyPNG::OutOfBounds error lambda { subject.replace!(OilyPNG::Canvas.new(1,1), 16, 16) }.should raise_error end end end oily_png-1.1.0/spec/encoding_spec.rb0000644000004100000410000002013412110154624017434 0ustar www-datawww-datarequire 'spec_helper' describe OilyPNG::PNGEncoding do context 'encoding different color settings without palette' do before do @canvas = ChunkyPNG::Canvas.from_file(resource_file('gray.png')) @oily_canvas = OilyPNG::Canvas.from_canvas(@canvas) end it "should encode an image using 8-bit grayscale correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 8, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 8, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 4-bit grayscale correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 4, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 4, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 2-bit grayscale correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 2, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 2, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 1-bit grayscale correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 1, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE, 1, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 8-bit grayscale alpha correctly" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 8, ChunkyPNG::FILTER_NONE) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 8, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 8-bit truecolor correctly" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_NONE) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 8-bit truecolor alpha correctly" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 8, ChunkyPNG::FILTER_NONE) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 8, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end end context 'encoding with paletted images using different bitrates' do before do @canvas = ChunkyPNG::Canvas.from_file(resource_file('gray.png')) @oily_canvas = OilyPNG::Canvas.from_canvas(@canvas) @canvas.encoding_palette = @canvas.palette @canvas.encoding_palette.to_plte_chunk @oily_canvas.encoding_palette = @oily_canvas.palette @oily_canvas.encoding_palette.to_plte_chunk end it "should encode an image using 8-bit indexed colors correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 8, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 8, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 4-bit indexed colors correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 4, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 4, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 2-bit indexed colors correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 2, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 2, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode an image using 1-bit indexed colors correctly" do @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 1, ChunkyPNG::FILTER_NONE) @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_INDEXED, 1, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end end context 'encoding different filters' do before do @canvas = ChunkyPNG::Canvas.from_file(resource_file('nonsquare.png')) @oily_canvas = OilyPNG::Canvas.from_canvas(@canvas) end it "should encode correctly with no filtering" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_NONE) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_NONE) stream1.should == stream2 end it "should encode correctly with sub filtering" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_SUB) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_SUB) stream1.should == stream2 end it "should encode correctly with up filtering" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_UP) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_UP) stream1.should == stream2 end it "should encode correctly with average filtering" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_AVERAGE) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_AVERAGE) stream1.should == stream2 end it "should encode correctly with paeth filtering" do @oily_canvas.send(:encode_png_image_pass_to_stream, stream1 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_PAETH) @canvas.send(:encode_png_image_pass_to_stream, stream2 = ChunkyPNG::Datastream.empty_bytearray, ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::FILTER_PAETH) stream1.should == stream2 end end it "should encode an interlaced image correctly" do canvas = ChunkyPNG::Canvas.from_file(resource_file('interlaced.png')) data = OilyPNG::Canvas.from_canvas(canvas).to_blob(:interlace => true) ds = ChunkyPNG::Datastream.from_blob(data) ds.header_chunk.interlace.should == ChunkyPNG::INTERLACING_ADAM7 ChunkyPNG::Canvas.from_datastream(ds).should == canvas end end oily_png-1.1.0/spec/color_spec.rb0000644000004100000410000000222312110154624016763 0ustar www-datawww-datarequire 'spec_helper' describe OilyPNG::Color do include OilyPNG::Color before(:each) do @white = 0xffffffff @black = 0x000000ff @opaque = 0x0a6496ff @non_opaque = 0x0a649664 @fully_transparent = 0x0a649600 end describe '#compose_quick' do it "should use the foregorund color as is when the background color is fully transparent" do compose_quick(@non_opaque, @fully_transparent).should == @non_opaque end it "should use the foregorund color as is when an opaque color is given as foreground color" do compose_quick(@opaque, @white).should == @opaque end it "should use the background color as is when a fully transparent pixel is given as foreground color" do compose_quick(@fully_transparent, @white).should == @white end it "should compose pixels correctly" do compose_quick(@non_opaque, @white).should == 0x9fc2d6ff end it "should compose colors exactly the same as ChunkyPNG" do fg, bg = rand(0xffffffff), rand(0xffffffff) compose_quick(fg, bg).should == ChunkyPNG::Color.compose_quick(fg, bg) end end endoily_png-1.1.0/spec/resources/0000755000004100000410000000000012110154624016321 5ustar www-datawww-dataoily_png-1.1.0/spec/resources/tp0n1g08.png0000755000004100000410000000126112110154624020313 0ustar www-datawww-dataPNG  IHDR V%(gAMA1_hIDATx}]HqM2?rY65K]hddaQQ؅ldHPAt}t+BRUaH E-6kL9[_du{\{9Gr-_[qŃ=CX=. .Zmm9sn'%.o=?Ud^g#!{}]DЯvu1ޤGb];;0~Y4$pϐKd[/{j:Ru>Gcèۚp!]v4[>ˎξu#~ENŒ].?+FSD^RSe:^z52E$8 &*az$"a lUEy9Z*XWr=+pȶSM l;h ϫt;\rlnn 0(RVۂP%>rB-)ԙnQIHL0˧2ky݄:Ubrd,)gk;(~V٬uGU@Y޾ vK$j 8P=MIƻ9WR'uf5]K.ݣ6< ,=ۂ?)͚IENDB`oily_png-1.1.0/spec/resources/tbrn2c08.png0000755000004100000410000000250312110154624020374 0ustar www-datawww-dataPNG  IHDR gAMA1_tRNS33ObKGD3'|IDATx_hSw?@#^i/4@of4Z`UVf )X1`}Hp` CO v,fP; -Hcb$=ddf]w=99k}6G^|:x(޽{&E1& @Q'O_>nO&#HooaqqC8W^]z5 x8D",/fۏNp8vm~~~`d21;KF\ZXX8"۷o'''3ѹ߅<002V+Ϟ01nϟ?~Dt]O,!˸,,`2q@4Lm3ĉPa0~dt^o8xK竵3/، d˔A-W:k;tuu5b\`0(IA 7յ`hp8𡅾;`hhHzoo(WhhM C8$)y@`0xIkJ:\.i4UUX,@N cǎEўZFUр'O={ӧO;;;Gz IENDB`oily_png-1.1.0/spec/resources/basn2c16.png0000755000004100000410000000045612110154624020356 0ustar www-datawww-dataPNG  IHDR 1gAMA1_IDATxՖ 0DA~&fzE=֠B>/drs~='3_Zwt(p3p]`_yt?t(C\l52L̩g I@g.`(`g Dg&((`60Y`zl(P49܀:{z*zȟmt3ΞAO3B^IENDB`oily_png-1.1.0/spec/resources/tbgn2c16.png0000755000004100000410000000371212110154624020363 0ustar www-datawww-dataPNG  IHDR 1gAMA1_tRNSYbKGDމc]IDATxX_HbiD  I  ƅ 6.Bq`*(`‹6 jYBȅrIHA!9CFxSgwWs<{djjjjj ywwwww!ICJT*J\[[[[[[cccccC WVVVVV`0H$DcX,_=FfvrH$----Noǣh4bx `0:N\. d2ᅮt*JR?ŋFc>/d<$t:  B>p|||||lv{~UHo0Ғr\<< BQje3 B@M,S&JpKs:N\O,r)ټw·d^ '@  UnL&dxa>|8J% )BBx灭ݻwͲ, l6˗jj5wt~ ~}6jZ7 J΍hThrXxe#T*`zeOY~[l6*W`͛7oy<dz loBP(DU@>:::::v:Y@oI*y`xaB*&&vp:GF8Nux~o'ӧ'O'OVWb.rnx5 L&IzFh48&(x8< 4T&@0H `b"HDfl~xD"H7i@6f, RT*B(2ٗy[Z[|>EzI |x|JPЅV{gg$ˊ}y,b\kE89= LOWUUUt:N~g2L&)|P( 3i). P Drz)Td`0 Y V֖N3PyF?F 03,+d2YG ..({U`'6{vvvvv033 kk@#|| ={<{q:iZVKAL  X,SjhцE_?Qt:Nh4Fp8ٮ.1MD[ *>er\.cYeY奞Aޠ@Vj4< 0࠘ qnjFH>Na::`"Ijsn>7ҍ7*1yT@HI$@$2ܬ--bpohhhhh ޳Dzz^r\NHw0D|a2r&˦,KX^+Aoooooo%w8RAZ܌n:*WUd U~hfl6奻^uL<:::::Z>.H$I%+t NOOOOOwKwgѴ[b_XXXXXX _-Jw7JMGP2F2Dڇ(*{^-w)SRRդ߿J uZ*|+n}}}}}}''''''-/ ᵅ IENDB`oily_png-1.1.0/spec/resources/operations.png0000644000004100000410000000020112110154624021203 0ustar www-datawww-dataPNG  IHDRh6HIDATxcb`/_ 0o`?`310F5j:&ҫIENDB`oily_png-1.1.0/spec/resources/tbbn1g04.png0000755000004100000410000000064312110154624020356 0ustar www-datawww-dataPNG  IHDR )gAMA1_tRNSXbKGD#2>IDATxUKAd[jH-5(5(O 'W:[":EEt-jv.<3`vBwqg&W? -³[#Τ}O$CptjL:dt}Kߩz}\}|x,ryT$eѐY\D5Z$a3Fު`Y\Ռ:T4b2(h%sn݆oEd=d2ܙBcF5μWhQd *F&Ny7zAwe\/x7rL#"ckLiq6>G΢HIENDB`oily_png-1.1.0/spec/resources/s39i3p04.png0000755000004100000410000000064412110154624020234 0ustar www-datawww-dataPNG  IHDR'' |gAMA1_sBITw'PLTEwwwwww;IDATxm1r0EǓ N."pʵ;ZJnQS:TV1/{f3T` Di@QhjZjvJJ85=P*0 zS`9!T5k=- K#<͚_.ܥ?Nubo&8:/G„"L,B MǔvkNhy>xxppWpX9çe(wx:Ι4e5߹?N|.@ny 5 IENDB`oily_png-1.1.0/spec/resources/basn0g01.png0000755000004100000410000000024412110154624020345 0ustar www-datawww-dataPNG  IHDR [GYgAMA1_[IDATx-̱ 0 J z4o< aEQ/ҤlΩ%SS4W!K&=Bs%%^ڲoj0i.)ano0eI//IENDB`oily_png-1.1.0/spec/resources/s07n3p02.png0000755000004100000410000000021212110154624020221 0ustar www-datawww-dataPNG  IHDR<@gAMA1_sBITw PLTEwwCIDATxcj í9 7H qy ]mIENDB`oily_png-1.1.0/spec/resources/tbbn3p08.png0000755000004100000410000000215012110154624020370 0ustar www-datawww-dataPNG  IHDR DgAMA1_PLTE""ssQ DDb ffs sssoookkkgggUUUggQQQMMM88 V 333////+/++w||+'s+++o'''x ###UMMM < oo/8' UUM M  bb UU3لww<<D ||| bbb"^^^ZZZ''xxxxssooDDD@@@ff<<< UU444MM|EE<<"""<33"D''<  // m4#tRNS@fbKGD \IDATxc`XW_!^.aaҡ^KE],C:OWF\` T%ڭg➗#~aξNlEdDU4.-S s D-JjA*t2g#3)"gįp(0I5{8 H\ _ $a}Fc7@y1`vY/rU&K­PqL%B}?aaDL*_*h>Md'R@C r+ ³L bXZ%J!F8N7) ( .&  $v̆Kwq10i^̼0>m8 jQ9/KxvYžL8xqI+s'IENDB`oily_png-1.1.0/spec/resources/s40i3p04.png0000755000004100000410000000054512110154624020224 0ustar www-datawww-dataPNG  IHDR(( וgAMA1_sBITw'PLTEwwwwww;IDATx 0EZk]dRPN7upqg'B YP1BCᐼ<DZrQeA|$`O sc#WLYDOLILȾ{aWvD( cNٮaXDCapl5pQDV @"$֓I#U&!AHt xnR=͈ki^ jNp{xIENDB`oily_png-1.1.0/spec/resources/s33n3p04.png0000755000004100000410000000051112110154624020224 0ustar www-datawww-dataPNG  IHDR!!\gAMA1_sBITw'PLTEwwwwww;IDATx]- W7pp ]WFp- +ƒ|Jop .[+j1Oe ]lD78Z;W갮kLWă⑻E=qx6U3QkT.:])T:IpPM#I?xxIJAhjW :M\ɩ]3b֓1%IENDB`oily_png-1.1.0/spec/resources/basi0g16.png0000755000004100000410000000045312110154624020350 0ustar www-datawww-dataPNG  IHDR qgAMA1_IDATx;0DI ]0S ,D @C#IVhk& \lX5R 2'+d~G @4 @4߁@\\y9۩ܵEkQט-} Q FAQ wbk@|DVIENDB`oily_png-1.1.0/spec/resources/basn0g08.png0000755000004100000410000000021212110154624020347 0ustar www-datawww-dataPNG  IHDR V%(gAMA1_AIDATxcd`$ȳ )?`y00gdy\ q10edPq5YIENDB`oily_png-1.1.0/spec/resources/square.png0000644000004100000410000000020112110154624020320 0ustar www-datawww-dataPNG  IHDRh6HIDATxcb`/_ 0o`?`310F5j:&ҫIENDB`oily_png-1.1.0/spec/resources/s02i3p01.png0000755000004100000410000000016212110154624020212 0ustar www-datawww-dataPNG  IHDR?gAMA1_sBITwPLTE\/% IDATxc`gIENDB`oily_png-1.1.0/spec/resources/s03i3p01.png0000755000004100000410000000016612110154624020217 0ustar www-datawww-dataPNG  IHDRjgAMA1_sBITwPLTEw奟 IDATxc`LAIENDB`oily_png-1.1.0/spec/resources/basn6a08.png0000755000004100000410000000027012110154624020353 0ustar www-datawww-dataPNG  IHDR szzgAMA1_oIDATx1 0 F'dhO?U!ExRP(M(ي0^{~3uG XN5"}\TB\.y 6{@<P6@R LIENDB`oily_png-1.1.0/spec/resources/basi2c16.png0000755000004100000410000000112312110154624020341 0ustar www-datawww-dataPNG  IHDR ۏvgAMA1_ IDATxՖ!s0?8a>Vx?0.;Xx0p0 SW+c Y}+EI$ ottЅ Awj88:A?/ĠnqsT`z4u-⋋=wTK\*< e7 M@x޶"&nܛ9f5|>IEtSqEUvvhƫ ^R\TjVz=XtodɎap~~ p}c ׍{3lvB}ކ|9:^TyJz5%WkFƫ%X go|h7#aL$7u)7ݬP?*>WU4^Y+/WZO?{1+^ |{ w u'0oh5HM@3~ݸ7sf7k.7e-/NK?RxZ s'@/eAY@ [?p| HQtu yfKϼQ-ѪHM@3~ݸ7sf7k.ԇ _|IV?4ħځN,'[3kXf|>o$_NY%an }MEFj0&fqo攛n\~|[~|!~ݻj%VyN&#āHFq@ ҊU;2t`@2zKoT۵3=-nj7#aL$7Vlvkeݻμ K@pR (#8grRKX4L;V݌14׍{3\67aZi.3o~`i޻ {pi 3 =)opQqdv%)3{>5XaXiH4ь̤+[h7#aL$׀fiZV!_ Cɽ?x~;w1[o zDE3ؓI~]Rl~%yZ+1S5ISZj݈VF˜H.~xVv: N]mx⁍/43}Ȉ c'ݛ l/Ib*aS1Q&1%?3j݈VD\9߭;wR'3j=K3Y ҕx{vi 1\[SΦx>lOcJF ޒ4ŨuWGjO9hn$83*}}§Rw~;@4k7syv|aE%aL>  j0&3gƫˁȽ_BAqޓ=vA&folnon4|6jd.dndoGq?eí۵IENDB`oily_png-1.1.0/spec/resources/s37i3p04.png0000755000004100000410000000061112110154624020224 0ustar www-datawww-dataPNG  IHDR%%@ gAMA1_sBITw'PLTEwwwwww;IDATxe;0Q NL.`h쭨hSRڥr(70̲˷`FCj} |n(`,,䜖jK)#)(8n P M$0 6!a?ؑ\Zs!*V}6nJ_Dؐ w9)/ggL x q%x \r/Rx [JsFNk-8F߮Rz'#?IENDB`oily_png-1.1.0/spec/resources/s33i3p04.png0000755000004100000410000000060112110154624020217 0ustar www-datawww-dataPNG  IHDR!!gAMA1_sBITw'PLTEwwwwww;IDATx]1r0E?0(xFHܸSKε+4>y˒Vo 4Ĺp:4a`5$9k L~FQZ #J3^K?Z]T4Z?&ikEJ 3) ]aVYEh-oĻ$`*1sPxKE= "aXIDo-MBC:e֖)Zir450NRk[]IldnaȕGR[_{Q_E6bp&],P]I4?t3P]jP33/2Z߈)IENDB`oily_png-1.1.0/spec/resources/s38n3p04.png0000755000004100000410000000036512110154624020240 0ustar www-datawww-dataPNG  IHDR&&ZgAMA1_sBITw'PLTEwwwwww;jIDATxc`eG`$61 !fpCCl* L1lvX*`q*b 0h-܌81 bhb)`@da1-i+άDIENDB`oily_png-1.1.0/spec/resources/basn0g04.png0000755000004100000410000000022112110154624020343 0ustar www-datawww-dataPNG  IHDR )gAMA1_HIDATxc``TR26vq MK+/g CA*wLrPV#ݽT3r%GAIENDB`oily_png-1.1.0/spec/resources/basn4a08.png0000755000004100000410000000017612110154624020356 0ustar www-datawww-dataPNG  IHDR sgAMA1_5IDATxch41",(,?a0T1`4GÀ*hP* }IENDB`oily_png-1.1.0/spec/resources/basn3p04.png0000755000004100000410000000033012110154624020360 0ustar www-datawww-dataPNG  IHDR TggAMA1_sBITw-PLTE""fwDDҰIGIDATxc =sfժrcwfd C+(H*ŅTݻq@*)#MK#G{7}IENDB`oily_png-1.1.0/spec/resources/s09n3p02.png0000755000004100000410000000021712110154624020230 0ustar www-datawww-dataPNG  IHDR gAMA1_sBITw PLTEwwVdIDATxc` V,XB q iejC#IENDB`oily_png-1.1.0/spec/resources/s40n3p04.png0000755000004100000410000000040012110154624020217 0ustar www-datawww-dataPNG  IHDR((~Х^gAMA1_sBITw'PLTEwwwwww;uIDATxб 0 DC,!alE6H%2EHVNRbG@!FeQk7^ Bؚp877*,mWBMwG)Rc!wu'gWpH])IENDB`oily_png-1.1.0/spec/resources/nonsquare.png0000644000004100000410000001701712110154624021050 0ustar www-datawww-dataPNG  IHDRP(i`}NiCCPICC ProfilexYgXͲM%Er$HHZҒsJR ""`D `}>ϝ癞wkzm-8 0ܼƿ Xeܯ_R96lzxð @79_n X"0DP ?$n&х?H OyW?o Hmc/dn\Ů_HK/JoZ-V@hfFIܤR:JULu.K/x<ēG& ~ZZډ::"u73/AEp$ru^aHƈƃ&&(GZJZ!ZmZgXBki(tJ&e/?_`133x02T12QD.DL!V"FY C+L LLvLLLL(faf#f\f ,\,,,,WXFYX9XX=Y3YYY屵bG[Ge_`P qdr4s<998889qqsrsZf.^!hy xne-]woo_ߖ?@@ xzBBB>BEBքE텏 /Ċԋ%jV>Ê)}KKd#{0{T3)I--)Y/9y-{?J J9JIݗږV~! c,,.YV\$[*D g $**/!)_.Tp@BOE%P+JJJeJʌT0*:*I**ͪ$.-繯zߜ:yi ^ WsӚ|nZZZ5ZŴ}/kԑ չۭ3gз/џ2767X1T03ޏo?oɨhX8τڤdT4Դ|/̈́Ź)W"!,od[]/Yѱɵya+jacGkdWgfgo?}P`vC#α!C;)8;M9}3s 5W%-7sJoFe+$]RiCˣcS3󝗺Wׂ)EMBe.߷wߎcEk@[ C_`_wPtHDpztj鐕PК0(pXk8#r8!1Yeu->:0z0F<&#]A8t)'/hLvD(='I )5iڣTG>JNObҞʕz$u.0>&=4}ڱCrg23=2 I'dNU-?=xr"O36>?6ԁS7 x 2 v9P(hشgJ|JKuJ82z-*RUUoV WVa"VU߿|&ӵV}uJuu8/.75^r1 4E4zu٤+ׅ ȼ ݌2:fӮ~[;:J;:sRvnܽ|\KϋރO,}p^}?x_e@qG n )|uXe}dHר1{O LNg/y;zr 'ԕg sRĔ$8;\>[|nJJէ>,]\}S7si~ncbSq77yZ[4ۍnYwwFw߾ӽЃ%'~_C~Oli>Zjx:2<- y?6qw3g;ϻ_ľ{a*iL٬ל{o=ߩ.0,_zd̷O:+Ն_]|CGO킝_`:ce¾]ȦQhhE vLU,}KdA>ep+%D|DkŖ$$Jػ!)sT<^T1GiDj_]Bjnhx>b&b.gjj%g-hCc]}L@GCJNN;g\j\<ܵH5z4og%2y_`~ {9!aMQ?#b1bOY!+ʑޣ))iS_˘̺}'M4N-=_YRL]Ultdȹ㕯kPij/Il`~šѳ)jvsS7V[V6v[:ovi=~} kS@ڠ#!|GcO&H&Oq=<_~WUS'^O̅IOtbG^|\_QY ѭm?N*́$c5NcTrxC5rt) t\ֳl}O9?rxyu\S -ЈʈيIT\Vq+0̡jFޗQyUCNހ}ۆWe~=pϬȜlb`feKm;iWm|P0Xri].fDId!M{tz}ǕC=O n< =.0B/s(X81P<&)P"&)㑑ɞ)ʩ4ikgd|ȼUuB)*g:d~^h)o O,q(U-cGvNOLJ>vXMńڀ.7\qko*zѵ7[[Y{J8y;{zV~>8m8ov8ׄdgC7^ }==Cc}f1qwԺnsK{V;%@8 ``4/Lh@p(lH)f%$|PnԋMHK}A"(Ҝ١ӦF/N_ HT#20~e:,<>qs?w&%/'>*,XaQg1WqO=1{˥ڥ'e~{#DWK*uԚiikm{d^g"kj ,<עܲ ]}v?tǙZL >L:H1dGdkd esMI92:!}CVBNNBs3/\3nhon!R޶uooݍ>cg=901Tь뷩 KWW+}nxSgkj;!Jc..0>ATG@P9M#`ߢP(OT6}Я`0f4L'R}Kc p% )NJ,YTTYT,jM? 44EH%:4;{"-!S stVyַl6t\R阸ǦcfD[~xC'j/kX˭Ymh rOX_ Ht̂ Fre20 >("JanPhJ]@_Fcx00Ř qǖ`p8_561E1˜Cr^@77Qcg fNi uknnl1ypy'OϮmm;";A;-=DЏS;;_3oggrggRl @5"{٭]ۂ| pHYs  gIDAThMh\UO^&OӘĦZbI-i*CjX*q.D PpS A".h,HC%*BҐH!`ӘIk'ys'y3?9w=h= CCC266&sss*n݊R\\,eeeRWW'---W&K~ޑvE855%233#^TT$ )v e}}}f~$ G13I3S第ݻwΝ;^\"LLL&{Ço* MI's̏LNNƵe4vuuŕ7yK`OOOܨ5/o.rcǜDVDqj$t@T< DwK7*q$}=? KJd6Z흃ٯ}p^'R7SUj^sȈ&yG׶C̓.},>8e Kxoq\Z"kN>-Ut80LYNv3i:l۸" @7|6ȄDթ6߶-{ngAo|=0gV_cM~(tiDm;ez.^ Z;е{P>F;U5MftY B##[xhd nM@ۙIܖ@P.`hO0FЉnm15rV`ѳnHy7:Cǖ4Fl*s~&'f(]HsVEAЛ-9x1JOl.;n+xw.UQ&n ϼr$w'#v! Թb }l z+ڏ7/"& d :l%N!ijgϺơ؁MD,\7yf~iJ@' Xn<S8\&$PT8 .HK+LJEppד?Ev-2W&biZƺ zA?^wNGIENDB`oily_png-1.1.0/spec/resources/interlaced.png0000644000004100000410000000041712110154624021143 0ustar www-datawww-dataPNG  IHDRhtEXtSoftwareAdobe ImageReadyqe<IDATxb gHv?@1DA" @p 01 `Ւ:ƪ SRR3(:`ƀLsF]8M!h@aD2H&E8N xU":`AT͛A `J0bZ& a@(Pr&U+E'mIENDB`oily_png-1.1.0/spec/resources/s36i3p04.png0000755000004100000410000000054412110154624020230 0ustar www-datawww-dataPNG  IHDR$$d)=gAMA1_sBITw'PLTEwwwwww;IDATx 0F?ӷ"]IQv iwqpvrTjbMI xA(;ވVLIFqxfSB0'zWs%Ñm rtȁ \Ap9*e} u} GT_`-U$ڪz3Q?, 0h+8郱oe(8Eb_zةj ,a*muuZ9?.IENDB`oily_png-1.1.0/spec/resources/basi3p01.png0000755000004100000410000000020412110154624020350 0ustar www-datawww-dataPNG  IHDR >!gAMA1_PLTE""fl&)IDATxc`P CѰ1Ù3IH6?@@!( B-vÞIENDB`oily_png-1.1.0/spec/resources/s04n3p01.png0000755000004100000410000000017112110154624020221 0ustar www-datawww-dataPNG  IHDR? =gAMA1_sBITwPLTEwCIDATxc0?  IENDB`oily_png-1.1.0/spec/resources/s06n3p02.png0000755000004100000410000000020312110154624020220 0ustar www-datawww-dataPNG  IHDRgAMA1_sBITw PLTEwEhIDATxcXaj02V-9_)pIENDB`oily_png-1.1.0/spec/resources/s06i3p02.png0000755000004100000410000000021712110154624020220 0ustar www-datawww-dataPNG  IHDR7MgAMA1_sBITw PLTEwEh"IDATxch`h` - +<"&0LH`XYLe$IENDB`oily_png-1.1.0/spec/resources/s01i3p01.png0000755000004100000410000000016112110154624020210 0ustar www-datawww-dataPNG  IHDRRf\gAMA1_sBITwPLTExW IDATxc`HqIENDB`oily_png-1.1.0/spec/resources/s36n3p04.png0000755000004100000410000000040212110154624020226 0ustar www-datawww-dataPNG  IHDR$$.gAMA1_sBITw'PLTEwwwwww;wIDATxc`eG$! .dp]]h*t !,[*`:B,!,Bl7݅,NEPWB BB Є$BB62`XoIӑIENDB`oily_png-1.1.0/spec/resources/tbgn3p08.png0000755000004100000410000000215012110154624020375 0ustar www-datawww-dataPNG  IHDR DgAMA1_PLTE""ssQ DDb ffs sssoookkkgggUUUggQQQMMM88 V 333////+/++w||+'s+++o'''x ###UMMM < oo/8' UUM M  bb UU3لww<<D ||| bbb"^^^ZZZ''xxxxssooDDD@@@ff<<< UU444MM|EE<<"""<33"D''<  // m4#tRNS@fbKGDf |dIDATxc`XW_!^.aaҡ^KE],C:OWF\` T%ڭg➗#~aξNlEdDU4.-S s D-JjA*t2g#3)"gįp(0I5{8 H\ _ $a}Fc7@y1`vY/rU&K­PqL%B}?aaDL*_*h>Md'R@C r+ ³L bXZ%J!F8N7) ( .&  $v̆Kwq10i^̼0>m8 jQ9/KxvYžL8xqI+s'IENDB`oily_png-1.1.0/spec/resources/s08n3p02.png0000755000004100000410000000021312110154624020223 0ustar www-datawww-dataPNG  IHDRaVgAMA1_sBITw PLTEwwYIDATxc```ZA =V=LIENDB`oily_png-1.1.0/spec/resources/s32i3p04.png0000755000004100000410000000054312110154624020223 0ustar www-datawww-dataPNG  IHDR SWQgAMA1_sBITw'PLTEwwwwww;IDATx}0F?E~S׆$F:5q,섁3$XV)16͗ù6H^|GO6vjPhq SXL!0Z(-`FUʂ $Lz*>=& r%@=E"t6;s2 q2wzE¥0l%=!޲Z;7R҄#IENDB`oily_png-1.1.0/spec/resources/tbyn3p08.png0000755000004100000410000000215312110154624020422 0ustar www-datawww-dataPNG  IHDR DgAMA1_ PLTE""ssQ DDb ffs sssoookkkgggUUUggQQQMMM88 V 333////+/++w||+'s+++o'''x ###UMMM < oo/8' UUM M  bb UU3لww<<D ||| bbb"^^^ZZZ''xxxxssooDDD@@@ff<<< UU444MM|EE<<"""<33"D''<  // ftRNS@fbKGD bIDATxc`XW_!^.aaҡ^KE],C:OWF\` T%ڭg➗#~aξNlEdDU4.-S s D-JjA*t2g#3)"gįp(0I5{8 H\ _ $a}Fc7@y1`vY/rU&K­PqL%B}?aaDL*_*h>Md'R@C r+ ³L bXZ%J!F8N7) ( .&  $v̆Kwq10i^̼0>m8 jQ9/KxvYžL8xqI+s'IENDB`oily_png-1.1.0/spec/resources/basi0g01.png0000755000004100000410000000033112110154624020335 0ustar www-datawww-dataPNG  IHDR ,wgAMA1_IDATx-10 EƂz.z' V9cX,e5|KxOp笹pi\Yc*L'Dd[6癹+MKOKzҍ2-czpEHp-/zQ!塌Qf"IENDB`oily_png-1.1.0/spec/resources/basn4a16.png0000755000004100000410000000423612110154624020356 0ustar www-datawww-dataPNG  IHDR n<gAMA1_UIDATxŗ_h[cHuRGT(8B-P.%4BiKaw]HɐXf%$zmiJWGc9w~t5O>>`eaX=`Ԃ±8G?]e _^X.wGO3wd3 gZú|'fef[Z!p&ކuh`c:oȇtri^g)X]UVZ l-5C`T$u!Z??p߅Cgj@dƱt-YY˅ae}';Ȁ~B@3 x'͌B ^SA#nr2r:QfGR`fAdv <@_"AÃևðqXZ3S:܀{Ճ< ';B 1/s,ZYߣ` `pg=U<@#뿃נ/`6,њ̀U]轏@`7&kc{ ? %:4o6JވaKGaɄ ? @= !e/sVVCpA5AhΠ.Ak%,?%!V[?hv@[/  !~Q`ZJHV@ס, \Z-tVKuVai *(a0ס  =i0Vކ.a{hQf\5 |ee8 l9QF haeXC9wnA D`6_Bh^SygLgv]~dA_ lwSR; I[VF&;5l :F$g 8h=ox yot| 'Q2 ,44c94O!1DӲͷ+3߲M:$m+?=*|~5{Wb zC`W݄辥< Cu㰈"j Q}8p|$;>.;/؏a 4/@ н[/E})x6훏m^=t)y#!ËGT/So SMO]]#7*gǏl!qXkdQa59G2 5e5$l (+畸2ۥ_$`Wb?@0 9E{Bk80/ƲVRZYxYf\ Nv{k By_@SaJcKjT𔥞cVE^>[v]7R>܉\i@)]SBBy$Ғh('eϭia;cҹ; МkX]HM%I%ŎUz]„Xj"22CO+h ɴ )oF\ܼ27 h+' wCQRY\-4-dA.Hax4,@ᜲ$o{ dJ;v,& C˧T$3ӔgVWsϓ<yhB# FP!v Vޔl X$p]y]\._s=,l7Gd){&TLK(}Z)h+V %@{gd"iiqૢ]Z^<y wPg+ЮB;  s%/ڟ gU<=DPw?({!l7d̀t:9-xIb z 4thFk2*<#~WQ\ 4eύpNf.J,OAdžN 6lf-ȌcGR3*%dE((\0){n$KJ3`38`ek+-w53&7yiIqRfqXAh٪wϤ50o0N N6 O= YU]IENDB`oily_png-1.1.0/spec/resources/s37n3p04.png0000755000004100000410000000052012110154624020230 0ustar www-datawww-dataPNG  IHDR%%7=0gAMA1_sBITw'PLTEwwwwww;IDATxe-@/M' '؄ z Vp)3x3@|Iz#S<#u*dUa02qEKϾ,27Fxlj<ɹ)Pz?KwWs:kPѤW2 -W]s' jeG KޭۯG|QV IENDB`oily_png-1.1.0/spec/resources/tp0n3p08.png0000755000004100000410000000214012110154624020323 0ustar www-datawww-dataPNG  IHDR DgAMA1_PLTE""ssQ DDb ffs sssoookkkgggUUUggQQQMMM88 V 333////+/++w||+'s+++o'''x ###UMMM < oo/8' UUM M  bb UU3لww<<D ||| bbb"^^^ZZZ''xxxxssooDDD@@@ff<<< UU444MM|EE<<"""<33"D''<  // 2lIDATx}_ QeBeF"[2YHȣ6%VVk }^( e ݋wѳO},g V1Mrnƾ@2 wfCx>+cKQ–[-ȱ䈻#0Dfݦ%#v3nwd@\ qjɲ TYs%IENDB`oily_png-1.1.0/spec/resources/basi2c08.png0000755000004100000410000000047312110154624020351 0ustar www-datawww-dataPNG  IHDR 5gAMA1_IDATxՓA! D{x=Ys3hhf gZYd1b|V%}֠Ɯ7~gv>^/-Jcm smXTmcm @%K,: 뻇oތ! ~>6K2m4?)u7,㍝4ueqCYcgg' i!lB4M\x2s&߆OiҮC-hDýgt<Kzz)]}?30.W\ZQKiپnp7Bn(A ;`n~"OÎ, :X@apy(b.7 9-#X1s;WhPfS!6ئrͬ’(T(o+ܟ| KWcf޶܀ fC>A y(kfPEMpx4t! ٟ%kx370%8$NA-!xzX!jl5+ .S3;-[W~u>Gtu,_WՁS7_ի:aTnZM߳0ctµvx,jq(VAyOjoBe-oA>k+?3V̮ū!xS [3O01 'wj칷d/SU槜wpx6kfi]^.#jkFS dF0,~Fef[7}^X݆@-xOC^#AQA ̋ɇ2B*Kik * \,koBZJ<w||&f(o@)Lirm^[Я.OFJ[_ye_uJȿ:)d!?eC;2zFW^'d2)d2#z3\8MoU(P̮Yӗ,Q lȞuN]s#ǯ\++rB|\H!e7n5]߷#BR r ,9gG$  ; &(\ ?k%{M+0lrow[O2Ip An;nC[0c5 {r Fچl늺fVXH] Y6_{6 Y-%B !?2uHM̋B45VL? cp>f֖ܷfEW!+7oB`30~&k74z<©̋uC_?0/MoB3 cV2|*( aHA$aAy٫.}fs]yu]uN΁Uh = =Ms>=ㅢ0%-C/ SRRaHv {a`z>C0EPs ʜGB't:p4t@IBK,# )ȏ7 _MHoFH,k*nvR3΅!nw!WIЅQ2 o? 7O0`7ȓ0eHTlͷ5 ƺ ?@w.3`>aoW phJς~ CoA&A>cQHoR): ӡ\^7_cbtƮSQr '!<PoA^r]P+a"0$L0d2&ȝ0`pttͥ4Wce_׋ȺYqa@f3dR 0\N~ UTcZ$XCϙ!C(9q>3Z_3=g@ BޛW;I`RU}]N;ծTC.(σ@3;`|ۡh thA ϙHZ7A4۞$lZHxjks# !(M@LO@ ,{022 ' }g|P\_{@MLG25 >i!'505-0e 䅜Bk)F[a"J+[4Bo+PA(x|%EqXk@G>3c٤ehu![HPSB 9!! 9uyBROH)!}B?+Bz]H6!f9z@ȱ+*!'~ $_B*T2gys >!H{I9lIENDB`oily_png-1.1.0/spec/resources/tbwn3p08.png0000755000004100000410000000215312110154624020420 0ustar www-datawww-dataPNG  IHDR DgAMA1_ PLTE""ssQ DDb ffs sssoookkkgggUUUggQQQMMM88 V 333////+/++w||+'s+++o'''x ###UMMM < oo/8' UUM M  bb UU3لww<<D ||| bbb"^^^ZZZ''xxxxssooDDD@@@ff<<< UU444MM|EE<<"""<33"D''<  // K+tRNS@fbKGD bIDATxc`XW_!^.aaҡ^KE],C:OWF\` T%ڭg➗#~aξNlEdDU4.-S s D-JjA*t2g#3)"gįp(0I5{8 H\ _ $a}Fc7@y1`vY/rU&K­PqL%B}?aaDL*_*h>Md'R@C r+ ³L bXZ%J!F8N7) ( .&  $v̆Kwq10i^̼0>m8 jQ9/KxvYžL8xqI+s'IENDB`oily_png-1.1.0/spec/resources/s05n3p02.png0000755000004100000410000000020112110154624020215 0ustar www-datawww-dataPNG  IHDRvgAMA1_sBITw PLTEwAsIDATxcX0a"\*JIENDB`oily_png-1.1.0/spec/resources/basi0g04.png0000755000004100000410000000036712110154624020351 0ustar www-datawww-dataPNG  IHDR gAMA1_IDATxeQ0D:(u AAAAA$TI~ò¶EuEĺCsGjw<# ^bs8Al.iGZ'(CYd:"k@i2Gpr:1(Kkce s {ig 826N'MIENDB`oily_png-1.1.0/spec/resources/basi0g08.png0000755000004100000410000000037612110154624020355 0ustar www-datawww-dataPNG  IHDR !gAMA1_IDATx] 0B{C%>x!Kܦ$]!2,$UIBH"*V$$ŏ Jl, lܲ 9:eSW}q@Şp쿣;_|?/ >&&*JNBKK_22x< 0: fiAޞ]\"rqa2|ۛdkj&&zz֦v 05MMuvnh`0TTd9:ƆFDȶmn%53 ke(/^S#Av/#,0 '0N5X S vc0jXw`  p>U0 N x!<۰ .^ nZs` z\?0! oa<~Np&023 0 tx C8, `#G0srIENDB`oily_png-1.1.0/spec/resources/tbwn1g16.png0000755000004100000410000000217212110154624020405 0ustar www-datawww-dataPNG  IHDR kgAMA1_tRNSĬbKGD1IDATxUMLm–ʊ݂-kjh@D$!1!&z01WB"(k' h$h kXi!ǵJ~G3<;;3؂$l%8ݻg047/ ۧ<Ǐfjc߿GwS'F08xd:}Գgcc>ZEfiihsJGFr9Z\-}$Þ=w>z41qBW\_pW\gu$ s<929yVw7X>e2SSK1AAfaѺ:$DBFE?bNv`^NS2@mm}}Up"""cm lVy(*`cc:t V(OJ&ҥK SLddڅa~KQ> JKL|YxJ$VfVVʷSD7IENDB`oily_png-1.1.0/spec/resources/s32n3p04.png0000755000004100000410000000040712110154624020227 0ustar www-datawww-dataPNG  IHDR TggAMA1_sBITw'PLTEwwwwww;|IDATxѽ Wq zZ6w +'a0MHR\GrvX41$TxAsŖ?hnsof]A[ $ \V~01YB6ipaHz&.IENDB`oily_png-1.1.0/spec/resources/s05i3p02.png0000755000004100000410000000020612110154624020215 0ustar www-datawww-dataPNG  IHDRgAMA1_sBITw PLTEwAsIDATxch`h`X";tOm"Mp$FEIENDB`oily_png-1.1.0/spec/resources/basn3p08.png0000755000004100000410000000240612110154624020372 0ustar www-datawww-dataPNG  IHDR DgAMA1_PLTE"Dww :w""""Uffff"DDUU"DDUU3DDff3D"ffD33U*D˺[""f2Ucw:DDkfBkܺ33sJw{"w332fDwJf""UUDff3UwwDwffD"w"3333cU3{UUUUf܃wwUUww""DD3ԪU*U˴f3BSD̙"Sww333Ĉwff""UU"DD[wfwws33wD""U"f 3bIDATx GHd+;3 ekXegа**4h lޣY2W%syiHCL*;8"KE6sx'HK?Y9sģ>1~!'B 0IENDB`oily_png-1.1.0/spec/resources/basn2c08.png0000755000004100000410000000022112110154624020345 0ustar www-datawww-dataPNG  IHDR gAMA1_HIDATx 0 @r;D++ ; }Lx@J„(t8#@pw^@KIENDB`oily_png-1.1.0/spec/resources/basi6a16.png0000755000004100000410000001012412110154624020344 0ustar www-datawww-dataPNG  IHDR T!gAMA1_ IDATxݙktU՝}&$@h⍠("І`YЎ" BZ.oY(ZAG$P t 8B[#CIIk_̇$̸Y]gc}m&ZCmI6D#?$XVIͮl̏d׽OB6nnm|¶,()^VnhO*sL-5S< ΍:wx4SEݰ# 𛷍[w8[ u,ZZY: ʊ+$n Pna WݹP^ql}cC#~NZ`^Z$;VWãȖG68F쾰=0@@ SCMpmr/$0J?B?;燈tKi ">SͭVUgTYъ2sAw厊D|Ɏ$d:|sGW#ߘ,  PU*Ԇ͒4C=3Q86sS-C?"SWkK/:[l; ~-&g]۔Bj+SwݗTQ@id'D|_0$[]d)u]3/U'NJ&:=V!``wS W uTBWAUD|UjՒ9U>z1ulh0,9h H=0HF-_0M-R_V[[TSϪ C7dg$@~s9%@Vm֋㔷ޓKN]]35 _#igT}ޙ3c\s  {$)cng*c4&'[9X`}'p 1g>"@BlOjbc%Q4Ի`RVUuH3 eMл@,Lr%е̬i(?XQ-7z(m626 ~Pt2o@ċPgCƁy.`$Jg]q0pUzOs$ɒ%}䦿^)cdmXrSd8j -7!ܘNSו qpH@8fʹn]Ʉ*yU.O.~UZ_4ö*p2Ib늦-D/.l_YY0E%; )7eBkGD!-7KJ@&ڕI:Mi㊽FaPŀ!oyF(Qp\rs@I{5w_8*-#yfvC۫"ʒ*%&%iO:6@8-'*S,dHNn-L] 8tJo26VA8:jgM hw*OogY=|=@j>@3mq2N)@U̿)*K KGk;aR<\/| bp:C=&R2}F2\r~_Wڮێ5e:DV[:850b-{l4K uAzPY/V.yA p H%L;k*h gZ1=LlС \m$M=_/ ,50!2[s!B}n(ӽϽԡ}" RP\WzHlA+50$!8oo E3@Et6BشpdGC[ PHN> K.`C +P!ҿo!_aCA-CLnQhr ->u157"v0  a{6reDCB%[>C> }"03a8:LR ,0D=4C܆">$D@n1v]f=g3b1/BPv@͐!Xڌ.&Aö g>7jYJ} ^k @jm&+ceVUhlMTB+ o5@*ot'|զޱVL]vQP_ Z40+XhV{#I+f3*#-Y;;ɗi@^rBXbVQAD{0b_l $@ p3,n<(nPPޑ(-Z4%~eE"RR`2JY]Z1 _0ߗ(([Zc2uH.t w%@fg@fCҧE @II(ZD 흧U) E@ZBR;ijaKX,2uHtbLֻ~{ p*_|Vp; 2_:>(ux h2  R[ }d}#VL;.*>m[>:c,gL7piR )qv{.@zW3@aCVS%d6UVpޠTPuu J%z#?&|tE+QOl5jvyԑN-Cϛo7uS!9Cd2Rl{ ŵ 3`/vot.PpSGUY)UV12 P^4Т55 A8Z^۹NK4S)8Y܃rrMۖc;5vCơ R{cҳt/{VS2|WμdvdWBB\>dQ.w- k`"mm#M޷J<K9ʖ\R|+sK~ 8tqm ȫGUV)E*aeWTiRJјuJv8=g韮YtmQKa znޙh;:~+P򶎷JW=)gONzg}f%;in<9_UjCV@N¬ jYehɋ*PH$$q{/ϵP^gѽgCã_n>=Ő XUн:}Lzl4%?  J |!nI/;) ۟M\٫X+NާW4-4A,2z w 9\* KR"2@Lw+tJ()g`qb %!RϞ|O}S+ckY1 V|jT {;cޙPv W"6"!ׁCC8?u2 BcM_np5X' Qvzgn "CgqEL9j[^.V^ck;`m+ jtKOX$F@$Cp#$Ap$*!r Gb; .ਖ?0̀@ r"`s{#dGR-0# #)O&_hPT4y`}~(M C/BmPt!7C]CLksk\c{"8q쉆ppiCxCCd)w!q!6Ca kп0w4 }~C,)gi(nO&#HooaqqC8W^]z5 x8D",/fۏNp8vm~~~`d21;KF\ZXX8"۷o'''3ѹ߅<002V+Ϟ01nϟ?~Dt]O,!˸,,`2q@4Lm3ĉPa0~dt^o8xK竵3/، d˔A-W:k;tuu5b\`0(IA 7յ`hp8𡅾;`hhHzoo(WhhM C8$)y@`0xIkJ:\.i4UUX,@N cǎEўZFUр'O={ӧO;;;Gz IENDB`oily_png-1.1.0/spec/resources/s09i3p02.png0000755000004100000410000000022312110154624020220 0ustar www-datawww-dataPNG  IHDR gAMA1_sBITw PLTEwwVd#IDATxc`@ X ^3\b  duFIENDB`oily_png-1.1.0/spec/resources/basi3p02.png0000755000004100000410000000030112110154624020347 0ustar www-datawww-dataPNG  IHDR ygAMA1_sBIT|.w PLTEe?+QIDATxcxǰ]̌!9J޸b.??dCH dJHR?t#B,*9Z}uIENDB`oily_png-1.1.0/spec/resources/s03n3p01.png0000755000004100000410000000017012110154624020217 0ustar www-datawww-dataPNG  IHDRl'gAMA1_sBITwPLTEw奟IDATxc``p``A91 KIENDB`oily_png-1.1.0/spec/resources/s39n3p04.png0000755000004100000410000000054012110154624020234 0ustar www-datawww-dataPNG  IHDR''~LgAMA1_sBITw'PLTEwwwwww;IDATxm!@GHzp 8,šW1CufICgf`2(6 'Zж =E'̪ 'QuEyJڟd0`7~mdUg/C>d(U>ѱb'LWtec+`:4nh7zob/ Ǫ O/5+IENDB`oily_png-1.1.0/spec/resources/basn0g02.png0000755000004100000410000000015012110154624020342 0ustar www-datawww-dataPNG  IHDR =gAMA1_IDATxc`]0PS3 cI IENDB`oily_png-1.1.0/spec/resources/basi6a08.png0000755000004100000410000000055112110154624020350 0ustar www-datawww-dataPNG  IHDR }JbgAMA1_ IDATxŕAN0EAfAME*q *e@ՔAHɊ|?'dG` 9c:1Ⓣ{=k ֵS˰gc. 3{_m /N @-~'.lM1! jѠ D h=F`u@]`^-^%x zRhb!9:XF/h.䋱 lY PtP΀W(3mYm πu(ש P:JSiNsBIENDB`oily_png-1.1.0/spec/resources/tp1n3p08.png0000755000004100000410000000213312110154624020326 0ustar www-datawww-dataPNG  IHDR DgAMA1_PLTE""ssQ DDb ffs sssoookkkgggUUUggQQQMMM88 V 333////+/++w||+'s+++o'''x ###UMMM < oo/8' UUM M  bb UU3لww<<D ||| bbb"^^^ZZZ''xxxxssooDDD@@@ff<<< UU444MM|EE<<"""<33"D''<  // m4#tRNS@fIDATxc`XW_!^.aaҡ^KE],C:OWF\` T%ڭg➗#~aξNlEdDU4.-S s D-JjA*t2g#3)"gįp(0I5{8 H\ _ $a}Fc7@y1`vY/rU&K­PqL%B}?aaDL*_*h>Md'R@C r+ ³L bXZ%J!F8N7) ( .&  $v̆Kwq10i^̼0>m8 jQ9/KxvYžL8xqI+s'IENDB`oily_png-1.1.0/spec/resources/s35i3p04.png0000755000004100000410000000061712110154624020230 0ustar www-datawww-dataPNG  IHDR##gAMA1_sBITw'PLTEwwwwww;IDATxe=PQv@Xـ  zs;&}!rBї 8ycec:1 4;0'9]L(PFڄ唪*1j1-FtH?׹HD"nƮMM;-ww+T0q=މ^fBu/ep cA%q)uMa8VFL`?Ha; L[ΉqЊiIENDB`oily_png-1.1.0/spec/resources/basi0g02.png0000755000004100000410000000023212110154624020336 0ustar www-datawww-dataPNG  IHDR k gAMA1_QIDATxcPb`r`p16nDgg]!dDCH dJHR? 0A 9RM}IENDB`oily_png-1.1.0/spec/resources/gray.png0000644000004100000410000000011112110154624017762 0ustar www-datawww-dataPNG  IHDR YaIDATxcLa&3/Nx 2]IENDB`oily_png-1.1.0/spec/resources/s38i3p04.png0000755000004100000410000000054512110154624020233 0ustar www-datawww-dataPNG  IHDR&&- gAMA1_sBITw'PLTEwwwwww;IDATx? @XA_EZF6i4475 :E@Hީn#9SЎOQbdTw)q!o;s+;qZIc|jb[P4i|aljƕAn6 S4zg4Xn8m uM/$yC;+|<ױ;^y}kvob땗){zB|DyEIENDB`oily_png-1.1.0/spec/resources/s08i3p02.png0000755000004100000410000000022512110154624020221 0ustar www-datawww-dataPNG  IHDRffgAMA1_sBITw PLTEwwY%IDATxc` ~`Ǡ0aXAAPPpJIENDB`oily_png-1.1.0/spec/resources/s07i3p02.png0000755000004100000410000000022512110154624020220 0ustar www-datawww-dataPNG  IHDR;gAMA1_sBITw PLTEwwC%IDATxc8p 3aH? Wcn UIENDB`oily_png-1.1.0/spec/resources/tbbn2c16.png0000755000004100000410000000371212110154624020356 0ustar www-datawww-dataPNG  IHDR 1gAMA1_tRNSYbKGDGe]IDATxX_HbiD  I  ƅ 6.Bq`*(`‹6 jYBȅrIHA!9CFxSgwWs<{djjjjj ywwwww!ICJT*J\[[[[[[cccccC WVVVVV`0H$DcX,_=FfvrH$----Noǣh4bx `0:N\. d2ᅮt*JR?ŋFc>/d<$t:  B>p|||||lv{~UHo0Ғr\<< BQje3 B@M,S&JpKs:N\O,r)ټw·d^ '@  UnL&dxa>|8J% )BBx灭ݻwͲ, l6˗jj5wt~ ~}6jZ7 J΍hThrXxe#T*`zeOY~[l6*W`͛7oy<dz loBP(DU@>:::::v:Y@oI*y`xaB*&&vp:GF8Nux~o'ӧ'O'OVWb.rnx5 L&IzFh48&(x8< 4T&@0H `b"HDfl~xD"H7i@6f, RT*B(2ٗy[Z[|>EzI |x|JPЅV{gg$ˊ}y,b\kE89= LOWUUUt:N~g2L&)|P( 3i). P Drz)Td`0 Y V֖N3PyF?F 03,+d2YG ..({U`'6{vvvvv033 kk@#|| ={<{q:iZVKAL  X,SjhцE_?Qt:Nh4Fp8ٮ.1MD[ *>er\.cYeY奞Aޠ@Vj4< 0࠘ qnjFH>Na::`"Ijsn>7ҍ7*1yT@HI$@$2ܬ--bpohhhhh ޳Dzz^r\NHw0D|a2r&˦,KX^+Aoooooo%w8RAZ܌n:*WUd U~hfl6奻^uL<:::::Z>.H$I%+t NOOOOOwKwgѴ[b_XXXXXX _-Jw7JMGP2F2Dڇ(*{^-w)SRRդ߿J uZ*|+n}}}}}}''''''-/ ᵅ IENDB`oily_png-1.1.0/metadata.yml0000644000004100000410000001316312110154624015664 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: oily_png version: !ruby/object:Gem::Version version: 1.1.0 prerelease: platform: ruby authors: - Willem van Bergen autorequire: bindir: bin cert_chain: [] date: 2013-02-15 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: chunky_png requirement: &70329825895620 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.2.7 type: :runtime prerelease: false version_requirements: *70329825895620 - !ruby/object:Gem::Dependency name: rake requirement: &70329825894740 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: *70329825894740 - !ruby/object:Gem::Dependency name: rake-compiler requirement: &70329825892520 !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: *70329825892520 - !ruby/object:Gem::Dependency name: rspec requirement: &70329825890860 !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: '2' type: :development prerelease: false version_requirements: *70329825890860 description: ! ' This Ruby C extenstion defines a module that can be included into ChunkyPNG to improve its speed. ' email: - willem@railsdoctors.com executables: [] extensions: - ext/oily_png/extconf.rb extra_rdoc_files: - README.rdoc files: - .gitignore - .infinity_test - .travis.yml - Gemfile - LICENSE - README.rdoc - Rakefile - ext/oily_png/color.c - ext/oily_png/color.h - ext/oily_png/extconf.rb - ext/oily_png/oily_png_ext.c - ext/oily_png/oily_png_ext.h - ext/oily_png/operations.c - ext/oily_png/operations.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 - ext/oily_png/resampling.c - ext/oily_png/resampling.h - lib/oily_png.rb - lib/oily_png/canvas.rb - oily_png.gemspec - spec/color_spec.rb - spec/decoding_spec.rb - spec/encoding_spec.rb - spec/operations_spec.rb - spec/resampling_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/composited.png - spec/resources/gray.png - spec/resources/interlaced.png - spec/resources/nonsquare.png - spec/resources/operations.png - spec/resources/replaced.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/resources/tbbn1g04.png - spec/resources/tbbn2c16.png - spec/resources/tbbn3p08.png - spec/resources/tbgn2c16.png - spec/resources/tbgn3p08.png - spec/resources/tbrn2c08.png - spec/resources/tbwn1g16.png - spec/resources/tbwn3p08.png - spec/resources/tbyn3p08.png - spec/resources/tp0n1g08.png - spec/resources/tp0n2c08.png - spec/resources/tp0n3p08.png - spec/resources/tp1n3p08.png - spec/spec_helper.rb - tasks/github-gem.rake - tasks/testing.rake homepage: http://wiki.github.com/wvanbergen/oily_png licenses: [] post_install_message: rdoc_options: - --title - oily_png - --main - README.rdoc - --line-numbers - --inline-source require_paths: - lib - ext required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: oily_png rubygems_version: 1.8.16 signing_key: specification_version: 3 summary: Native mixin to speed up ChunkyPNG test_files: - spec/color_spec.rb - spec/decoding_spec.rb - spec/encoding_spec.rb - spec/operations_spec.rb - spec/resampling_spec.rb oily_png-1.1.0/Gemfile0000644000004100000410000000031612110154624014650 0ustar www-datawww-datasource :rubygems if ENV['CHUNKY_PNG'] gem 'chunky_png', :path => ENV['CHUNKY_PNG'] gem 'oily_png', :path => File.dirname(__FILE__) gem 'rake' gem 'rake-compiler' gem 'rspec' else gemspec end oily_png-1.1.0/oily_png.gemspec0000644000004100000410000001036112110154624016543 0ustar www-datawww-dataGem::Specification.new do |s| s.name = 'oily_png' s.rubyforge_project = s.name # Do not change the version and date fields by hand. This will be done # automatically by the gem release script. s.version = "1.1.0" s.date = "2013-02-15" s.summary = "Native mixin to speed up ChunkyPNG" s.description = <<-EOT This Ruby C extenstion defines a module that can be included into ChunkyPNG to improve its speed. EOT s.authors = ['Willem van Bergen'] s.email = ['willem@railsdoctors.com'] s.homepage = 'http://wiki.github.com/wvanbergen/oily_png' s.extensions = ["ext/oily_png/extconf.rb"] s.require_paths = ["lib", "ext"] s.add_runtime_dependency('chunky_png', '~> 1.2.7') s.add_development_dependency('rake') s.add_development_dependency('rake-compiler') s.add_development_dependency('rspec', '~> 2') s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source' s.extra_rdoc_files = ['README.rdoc'] # Do not change the files and test_files fields by hand. This will be done # automatically by the gem release script. s.files = %w(.gitignore .infinity_test .travis.yml Gemfile LICENSE README.rdoc Rakefile ext/oily_png/color.c ext/oily_png/color.h ext/oily_png/extconf.rb ext/oily_png/oily_png_ext.c ext/oily_png/oily_png_ext.h ext/oily_png/operations.c ext/oily_png/operations.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 ext/oily_png/resampling.c ext/oily_png/resampling.h lib/oily_png.rb lib/oily_png/canvas.rb oily_png.gemspec spec/color_spec.rb spec/decoding_spec.rb spec/encoding_spec.rb spec/operations_spec.rb spec/resampling_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/composited.png spec/resources/gray.png spec/resources/interlaced.png spec/resources/nonsquare.png spec/resources/operations.png spec/resources/replaced.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/resources/tbbn1g04.png spec/resources/tbbn2c16.png spec/resources/tbbn3p08.png spec/resources/tbgn2c16.png spec/resources/tbgn3p08.png spec/resources/tbrn2c08.png spec/resources/tbwn1g16.png spec/resources/tbwn3p08.png spec/resources/tbyn3p08.png spec/resources/tp0n1g08.png spec/resources/tp0n2c08.png spec/resources/tp0n3p08.png spec/resources/tp1n3p08.png spec/spec_helper.rb tasks/github-gem.rake tasks/testing.rake) s.test_files = %w(spec/color_spec.rb spec/decoding_spec.rb spec/encoding_spec.rb spec/operations_spec.rb spec/resampling_spec.rb) end oily_png-1.1.0/.gitignore0000644000004100000410000000016412110154624015346 0ustar www-datawww-dataMakefile /conftest.dSYM *.bundle *.o *.rbc /.bundle/ Gemfile.lock /pkg oily_png-*.gem .DS_Store /spec/resources/_*.*oily_png-1.1.0/lib/0000755000004100000410000000000012110154624014123 5ustar www-datawww-dataoily_png-1.1.0/lib/oily_png.rb0000644000004100000410000000072612110154624016275 0ustar www-datawww-datarequire 'chunky_png' module OilyPNG VERSION = "1.1.0" def self.included(base) base::Canvas.send(:extend, OilyPNG::PNGDecoding) base::Canvas.send(:include, OilyPNG::PNGEncoding) base::Color.send(:include, OilyPNG::Color) base::Color.extend OilyPNG::Color base::Canvas.send(:include, OilyPNG::Resampling) end end require 'oily_png/oily_png' require 'oily_png/canvas' # Include mixin into ChunkyPNG ChunkyPNG.send(:include, OilyPNG) oily_png-1.1.0/lib/oily_png/0000755000004100000410000000000012110154624015743 5ustar www-datawww-dataoily_png-1.1.0/lib/oily_png/canvas.rb0000644000004100000410000000042612110154624017545 0ustar www-datawww-datarequire 'chunky_png' require 'oily_png/oily_png' module OilyPNG class Canvas < ChunkyPNG::Canvas extend OilyPNG::PNGDecoding include OilyPNG::PNGEncoding include OilyPNG::Operations include OilyPNG::Resampling end module Color extend self end end