Module: NL::FastPng::PngExt
- Defined in:
- ext/nl-fast_png/png_ext.c
Class Method Summary collapse
-
.store_png(width, height, depth, data) ⇒ Object
compression).
Class Method Details
.store_png(width, height, depth, data) ⇒ Object
compression). 16-bit data is expected to be in little-endian order.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'ext/nl-fast_png/png_ext.c', line 92
VALUE rb_store_png(VALUE self, VALUE width, VALUE height, VALUE depth, VALUE data)
{
VALUE outbuf;
VALUE errstr;
VALUE ret;
unsigned int w, h, d;
png_structp png_ptr;
png_infop info_ptr;
Check_Type(data, T_STRING);
w = NUM2UINT(width);
h = NUM2UINT(height);
d = NUM2UINT(depth);
if(d != 8 && d != 16) {
rb_raise(rb_eArgError, "Depth must be either 8 or 16 (got %u).", d);
}
if(RSTRING_LEN(data) < w * h * (d / 8)) {
rb_raise(rb_eArgError, "Data must contain at least %u bytes (got %zd).", w * h * (d / 8), (ssize_t)RSTRING_LEN(data));
}
outbuf = rb_str_buf_new(0);
if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &errstr, error_func, warn_func))) {
rb_raise(rb_eStandardError, "Unable to create PNG writing structure: %s\n", RSTRING_PTR(errstr));
}
if(!(info_ptr = png_create_info_struct(png_ptr))) {
png_destroy_write_struct(&png_ptr, NULL);
rb_raise(rb_eStandardError, "Unable to create PNG info structure: %s\n", RSTRING_PTR(errstr));
}
if(setjmp(png_jmpbuf(png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
rb_raise(rb_eStandardError, "A libpng error occurred: %s\n", RSTRING_PTR(errstr));
}
png_set_write_fn(png_ptr, &outbuf, write_func, flush_func);
png_set_IHDR(png_ptr, info_ptr, w, h, d,
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_filter(png_ptr, 0, PNG_FILTER_SUB);
png_set_compression_level(png_ptr, Z_BEST_SPEED);
png_write_info(png_ptr, info_ptr);
// FIXME: this is accessing a Ruby string's contents without the GVL; is that a problem?
ret = rb_thread_call_without_gvl(
store_png_blocking,
&(struct kinpng_info){
.w = w, .h = h, .d = d, .data = RSTRING_PTR(data), .png_ptr = png_ptr, .info_ptr = info_ptr
},
NULL,
NULL
);
if(ret == NULL) {
rb_raise(rb_eStandardError, "A libpng error occurred while writing: %s\n", RSTRING_PTR(errstr));
}
if(setjmp(png_jmpbuf(png_ptr))) {
rb_raise(rb_eStandardError, "A libpng error occurred: %s\n", RSTRING_PTR(errstr));
}
png_destroy_write_struct(&png_ptr, &info_ptr);
return outbuf;
}
|