/** * Graphics::PNG is PNG library * * @author DATE Ken (as Itacchi) / ge6537@i.bekkoame.ne.jp * @code-name Aoi * @see http://www.isc.meiji.ac.jp/~ee77038/ruby/ * $Id: writer.c,v 1.1 2000/09/27 17:55:25 date Exp date $ */ #include "libpng.h" #define PNG_WROTE_INFO_BEFORE_PLTE 0x400 #define WRITE_STATUS_FN "write_status_fn" VALUE cWriter; /* * ----------------------- * utility function for * Graphics::PNG::Writer * ----------------------- */ static void writer_free(png_obj) png_object *png_obj; { if (png_obj->fp) fclose(png_obj->fp); if (png_obj->info->valid & PNG_INFO_PLTE) free(png_obj->info->palette); if (png_obj->info->valid & PNG_INFO_tRNS) free(png_obj->info->trans); png_destroy_write_struct(&png_obj->obj, &png_obj->info); free(png_obj); } static void png_default_error(png_ptr, message) png_structp png_ptr; png_const_charp message; { rb_raise(ePngError, "Ruby/libpng error: %s\n", message); } static void png_default_warning(png_ptr, message) png_structp png_ptr; png_const_charp message; { rb_warning("Ruby/libpng warning: %s\n", message); } static void write_row_callback(png_ptr, row_number, pass) png_structp png_ptr; png_uint_32 row_number; int pass; { VALUE proc; if(png_ptr == NULL || row_number > PNG_MAX_UINT || pass > 7) return; proc = rb_iv_get(cReader, WRITE_STATUS_FN); if (NIL_P(proc)) return; rb_funcall(proc, rb_intern("call"), 2, INT2NUM(row_number), INT2FIX(pass)); } /* * ----------------------- * class method of * Graphics::PNG::Writer * ----------------------- */ static VALUE writer_new(klass, file) VALUE klass, file; { FILE *fp; OpenFile *fptr; VALUE new_obj; png_object *png_obj; Check_Type(file, T_STRING); if ((fp = fopen(STR2CSTR(file), "wb")) == NULL){ rb_raise(rb_eException, "can't open: %s", STR2CSTR(file)); return Qnil; } /* create PNG object */ new_obj = Data_Make_Struct(klass, png_object, NULL, writer_free, png_obj); png_obj->fp = fp; png_obj->obj = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_default_error, png_default_warning); if (png_obj->obj == NULL){ fclose(fp); rb_raise(rb_eException, "can't create PNG object (failer to create write struct)"); return Qnil; } png_obj->info = png_create_info_struct(png_obj->obj); if (png_obj->info == NULL){ fclose(fp); png_destroy_write_struct(&png_obj->obj, (png_infopp)NULL); rb_raise(rb_eException, "can't create PNG object (failer to create info struct)"); return Qnil; } png_obj->end_info = png_create_info_struct(png_obj->obj); if (png_obj->end_info == NULL){ fclose(fp); png_destroy_write_struct(&png_obj->obj, &png_obj->info); rb_raise(rb_eException, "can't create PNG object (failer to create info struct)"); return Qnil; } if (setjmp(png_jmpbuf(png_obj->obj))){ fclose(fp); png_destroy_info_struct(png_obj->obj, &png_obj->end_info); png_destroy_write_struct(&png_obj->obj, &png_obj->info); rb_raise(rb_eException, "can't create PNG object (failer to create write struct)"); return Qnil; } png_init_io(png_obj->obj, png_obj->fp); rb_obj_call_init(new_obj, 1, &file); return new_obj; } /* * ----------------------- * instance method of * Graphics::PNG::Writer * ----------------------- */ static VALUE writer_initialize(obj) VALUE obj; { return Qnil; } #if defined(PNG_READ_BACKGROUND_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED static VALUE libpng_writer_set_background(obj, background_color, background_gamma_code, need_expand, background_gamma) VALUE obj, background_color, background_gamma_code, need_expand, background_gamma; { png_object *png_obj; png_color_16p bg_color; IS_COLOR_16_P(background_color); FIXNUM_P(background_gamma_code); FIXNUM_P(need_expand); Check_Type(background_gamma, T_FLOAT); GET_PNG_VAL(obj, png_obj); Data_Get_Struct(background_color, png_color_16, bg_color); png_set_background(png_obj->obj, bg_color, NUM2INT(background_gamma_code), NUM2INT(need_expand), RFLOAT(background_gamma)->value); return Qnil; } #endif /* PNG_FLOATING_POINT_SUPPORTED */ #endif /* PNG_READ_BACKGROUND_SUPPORTED */ #if defined(PNG_WRITE_BGR_SUPPORTED) static VALUE libpng_writer_set_bgr(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_bgr(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_BGR_SUPPORTED */ #if defined(PNG_bKGD_SUPPORTED) static VALUE libpng_writer_set_bKGD(obj, background) VALUE obj, background; { png_object *png_obj; png_color_16p bg_color; IS_COLOR_16_P(background); GET_PNG_VAL(obj, png_obj); Data_Get_Struct(background, png_color_16, bg_color); png_set_bKGD(png_obj->obj, png_obj->info, bg_color); return Qnil; } #endif /* PNG_bKGD_SUPPORTED */ #if defined(PNG_cHRM_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED static VALUE libpng_writer_set_cHRM(obj, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y) VALUE obj, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; { png_object *png_obj; Check_Type(white_x, T_FLOAT); Check_Type(white_y, T_FLOAT); Check_Type(red_x, T_FLOAT); Check_Type(red_y, T_FLOAT); Check_Type(green_x, T_FLOAT); Check_Type(green_y, T_FLOAT); Check_Type(blue_x, T_FLOAT); Check_Type(blue_y, T_FLOAT); GET_PNG_VAL(obj, png_obj); png_set_cHRM(png_obj->obj, png_obj->info, RFLOAT(white_x)->value, RFLOAT(white_y)->value, RFLOAT(red_x)->value, RFLOAT(red_y)->value, RFLOAT(green_x)->value, RFLOAT(green_y)->value, RFLOAT(blue_x)->value, RFLOAT(blue_y)->value); return Qnil; } #endif /* PNG_FLOATING_POINT_SUPPORTED */ #ifdef PNG_FIXED_POINT_SUPPORTED static VALUE libpng_writer_set_cHRM_fixed(obj, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y) VALUE obj, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; { png_object *png_obj; FIXNUM_P(white_x); FIXNUM_P(white_y); FIXNUM_P(red_x); FIXNUM_P(red_y); FIXNUM_P(green_x); FIXNUM_P(green_y); FIXNUM_P(blue_x); FIXNUM_P(blue_y); GET_PNG_VAL(obj, png_obj); png_set_cHRM_fixed(png_obj->obj, png_obj->info, NUM2LONG(white_x), NUM2LONG(white_y), NUM2LONG(red_x), NUM2LONG(red_y), NUM2LONG(green_x), NUM2LONG(green_y), NUM2LONG(blue_x), NUM2LONG(blue_y)); return Qnil; } #endif /* PNG_FIXED_POINT_SUPPORTED */ #endif /* PNG_cHRM_SUPPORTED */ static VALUE libpng_writer_set_compression_level(obj, level) VALUE obj, level; { png_object *png_obj; FIXNUM_P(level); GET_PNG_VAL(obj, png_obj); png_set_compression_level(png_obj->obj, FIX2INT(level)); return Qnil; } static VALUE libpng_writer_set_compression_mem_level(obj, mem_level) VALUE obj, mem_level; { png_object *png_obj; FIXNUM_P(mem_level); GET_PNG_VAL(obj, png_obj); png_set_compression_mem_level(png_obj->obj, FIX2INT(mem_level)); return Qnil; } static VALUE libpng_writer_set_compression_method(obj, method) VALUE obj, method; { png_object *png_obj; FIXNUM_P(method); GET_PNG_VAL(obj, png_obj); png_set_compression_method(png_obj->obj, FIX2INT(method)); return Qnil; } static VALUE libpng_writer_set_compression_strategy(obj, strategy) VALUE obj, strategy; { png_object *png_obj; FIXNUM_P(strategy); GET_PNG_VAL(obj, png_obj); png_set_compression_strategy(png_obj->obj, FIX2INT(strategy)); return Qnil; } static VALUE libpng_writer_set_compression_window_bits(obj, window_bits) VALUE obj, window_bits; { png_object *png_obj; FIXNUM_P(window_bits); GET_PNG_VAL(obj, png_obj); png_set_compression_window_bits(png_obj->obj, FIX2INT(window_bits)); return Qnil; } static VALUE libpng_writer_set_crc_action(obj, crit_action, ancil_action) VALUE obj, crit_action, ancil_action; { png_object *png_obj; FIXNUM_P(crit_action); FIXNUM_P(ancil_action); GET_PNG_VAL(obj, png_obj); png_set_crc_action(png_obj->obj, FIX2INT(crit_action), FIX2INT(ancil_action)); return Qnil; } #if defined(PNG_READ_DITHER_SUPPORTED) static VALUE libpng_writer_set_dither(obj, palettes, maximum_colors, histogram, full_dither) VALUE obj, palettes, maximum_colors, histogram, full_dither; { png_object *png_obj; png_colorp dither_palette; png_color *color; png_uint_16p dither_histogram; int num_palette, i; Check_Type(palettes, T_ARRAY); FIXNUM_P(maximum_colors); Check_Type(histogram, T_ARRAY); FIXNUM_P(full_dither); GET_PNG_VAL(obj, png_obj); num_palette = RARRAY(palettes)->len; dither_palette = ALLOCA_N(png_color, num_palette); for (i=0; iptr[i], png_color, color); dither_palette[i] = *color; } dither_histogram = ALLOCA_N(png_uint_16, RARRAY(histogram)->len); for (i=0; ilen; i++){ dither_histogram[i] = FIX2INT(RARRAY(histogram)->ptr[i]); } png_set_dither(png_obj->obj, dither_palette, num_palette, FIX2INT(maximum_colors), dither_histogram, FIX2INT(full_dither)); return Qnil; } #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) static VALUE libpng_writer_set_filler(obj, filler, flags) VALUE obj, filler, flags; { png_object *png_obj; FIXNUM_P(filler); FIXNUM_P(flags); GET_PNG_VAL(obj, png_obj); png_set_filler(png_obj->obj, NUM2LONG(filler), FIX2INT(flags)); return Qnil; } #endif /* PNG_WRITE_FILLER_SUPPORTED */ static VALUE libpng_writer_set_filter(obj, method, filters) VALUE obj, method, filters; { png_object *png_obj; FIXNUM_P(method); FIXNUM_P(filters); GET_PNG_VAL(obj, png_obj); png_set_filter(png_obj->obj, FIX2INT(method), FIX2INT(filters)); return Qnil; } #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED static VALUE libpng_writer_set_filter_heuristics(obj, heuristic_method, filter_weights, filter_costs) VALUE obj, heuristic_method, filter_weights, filter_costs; { png_object *png_obj; int num_weights, i; png_doublep weights, costs; FIXNUM_P(heuristic_method); Check_Type(filter_weights, T_ARRAY); GET_PNG_VAL(obj, png_obj); num_weights = RARRAY(filter_weights)->len; weights = ALLOCA_N(double, num_weights); for (i=0; iptr[i], T_FLOAT); weights[i] = NUM2DBL(RARRAY(filter_weights)->ptr[i]); } switch (TYPE(filter_costs)){ case T_NIL: png_set_filter_heuristics(png_obj->obj, FIX2INT(heuristic_method), num_weights, weights, NULL); break; case T_ARRAY: costs = ALLOCA_N(double, num_weights); for (i=0; iptr[i], T_FLOAT); costs[i] = NUM2DBL(RARRAY(filter_costs)->ptr[i]); } png_set_filter_heuristics(png_obj->obj, FIX2INT(heuristic_method), num_weights, weights, costs); break; default: rb_raise(rb_eTypeError, "wrong argument type %s (expected ARRAY/nil)", rb_class2name(CLASS_OF(filter_costs))); } return Qnil; } #endif /* PNG_FLOATING_POINT_SUPPORTED */ #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ #if defined(PNG_WRITE_FLUSH_SUPPORTED) static VALUE libpng_writer_set_flush(obj, nrows) VALUE obj, nrows; { png_object *png_obj; FIXNUM_P(nrows); GET_PNG_VAL(obj, png_obj); png_set_flush(png_obj->obj, FIX2INT(nrows)); return Qnil; } #endif /* PNG_WRITE_FLUSH_SUPPORTED */ #if defined(PNG_READ_GAMMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED static VALUE libpng_writer_set_gamma(obj, screen_gamma, default_file_gamma) VALUE obj, screen_gamma, default_file_gamma; { png_object *png_obj; Check_Type(screen_gamma, T_FLOAT); Check_Type(default_file_gamma, T_FLOAT); GET_PNG_VAL(obj, png_obj); png_set_gamma(png_obj->obj, RFLOAT(screen_gamma)->value, RFLOAT(default_file_gamma)->value); return Qnil; } #endif /* PNG_FLOATING_POINT_SUPPORTED */ #endif /* PNG_READ_GAMMA_SUPPORTED */ #if defined(PNG_gAMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED static VALUE libpng_writer_set_gAMA(obj, file_gamma) VALUE obj, file_gamma; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); switch (TYPE(file_gamma)){ case T_FIXNUM: png_set_gAMA_fixed(png_obj->obj, png_obj->info, NUM2LONG(file_gamma)); break; case T_FLOAT: png_set_gAMA(png_obj->obj, png_obj->info, RFLOAT(file_gamma)->value); break; default: rb_raise(rb_eTypeError, "wrong argument type %s (expected FIXNUM/FLOAT)", rb_class2name(CLASS_OF(file_gamma))); break; } return Qnil; } #endif /* PNG_FLOATING_POINT_SUPPORTED */ static VALUE libpng_writer_set_gAMA_fixed(obj, file_gamma) VALUE obj, file_gamma; { png_object *png_obj; FIXNUM_P(file_gamma); GET_PNG_VAL(obj, png_obj); png_set_gAMA_fixed(png_obj->obj, png_obj->info, NUM2LONG(file_gamma)); return Qnil; } #endif /* PNG_gAMA_SUPPORTED */ #if defined(PNG_hIST_SUPPORTED) static VALUE libpng_writer_set_hIST(obj, hist) VALUE obj, hist; { png_object *png_obj; png_colorp palette; int i, num_palette; png_uint_16p histogram; VALUE tmp; Check_Type(hist, T_ARRAY); GET_PNG_VAL(obj, png_obj); if (png_get_PLTE(png_obj->obj, png_obj->info, &palette, &num_palette)){ histogram = ALLOCA_N(png_uint_16, num_palette); for (i = 0; i < num_palette; i++){ tmp = rb_ary_shift(hist); FIXNUM_P(tmp); histogram[i] = FIX2INT(tmp); } png_set_hIST(png_obj->obj, png_obj->info, histogram); } return Qnil; } #endif /* PNG_hIST_SUPPORTED */ #if defined(PNG_iCCP_SUPPORTED) static VALUE libpng_writer_set_iCCP(obj, name, compression_type, profile) VALUE obj, name, compression_type, profile; { png_object *png_obj; int com_type; VALUE profile_name; int name_size; Check_Type(name, T_STRING); Check_Type(profile, T_STRING); GET_PNG_VAL(obj, png_obj); name_size = RSTRING(name)->len; if (name_size > 80) name_size = 80; profile_name = rb_str_new(STR2CSTR(name), name_size); if (TYPE(compression_type) == T_FIXNUM){ com_type = FIX2INT(compression_type); if (com_type != PNG_COMPRESSION_TYPE_BASE){ rb_raise(ePngError, "wrong compression type %d", com_type); return Qnil; } png_set_iCCP(png_obj->obj, png_obj->info, STR2CSTR(profile_name), com_type, STR2CSTR(profile), RSTRING(profile)->len); } else if (TYPE(compression_type) == T_NIL){ png_set_iCCP(png_obj->obj, png_obj->info, STR2CSTR(profile_name), (int)NULL, STR2CSTR(profile), RSTRING(profile)->len); } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected STRING/NIL)", rb_class2name(CLASS_OF(compression_type))); } png_read_update_info(png_obj->obj, png_obj->info); return Qnil; } #endif /* PNG_iCCP_SUPPORTED */ #if defined(PNG_WRITE_INTERLACING_SUPPORTED) static VALUE libpng_writer_set_interlace_handling(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_interlace_handling(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_INTERLACING_SUPPORTED */ #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) static VALUE libpng_writer_set_invert_alpha(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_invert_alpha(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_INVERT_ALPHA_SUPPORTED */ #if defined(PNG_WRITE_INVERT_SUPPORTED) static VALUE libpng_writer_set_invert_mono(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_invert_mono(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_INVERT_SUPPORTED */ static VALUE libpng_writer_set_IHDR(obj, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type) VALUE obj, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type; { png_object *png_obj; FIXNUM_P(width); FIXNUM_P(height); FIXNUM_P(bit_depth); FIXNUM_P(color_type); FIXNUM_P(interlace_type); FIXNUM_P(compression_type); FIXNUM_P(filter_type); GET_PNG_VAL(obj, png_obj); png_set_IHDR(png_obj->obj, png_obj->info, NUM2INT(width), NUM2INT(height), FIX2INT(bit_depth), FIX2INT(color_type), FIX2INT(interlace_type), FIX2INT(compression_type), FIX2INT(filter_type)); return Qnil; } #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) static VALUE libpng_writer_set_keep_unknown_chunks(obj, keep, chunk_list) VALUE obj, keep, chunk_list; { png_object *png_obj; int keep_condition, num_chunks, i; png_bytep affect_chunk_list; FIXNUM_P(keep); keep_condition = FIX2INT(keep); if (keep_condition < HANDLE_CHUNK_AS_DEFAULT || keep_condition > HANDLE_CHUNK_ALWAYS) rb_raise(ePngError, "invalid \"keep\" directive for unknown chunks: %d", keep_condition); GET_PNG_VAL(obj, png_obj); switch(TYPE(chunk_list)){ case T_NIL: png_set_keep_unknown_chunks(png_obj->obj, keep_condition, NULL, 0); break; case T_ARRAY: num_chunks = RARRAY(chunk_list)->len; affect_chunk_list = ALLOCA_N(char, 5 * num_chunks); for (i=0; iptr[i], T_STRING); memcpy(affect_chunk_list, STR2CSTR(RARRAY(chunk_list)->ptr[i]), 4); memcpy(affect_chunk_list, '\0', 1); } png_set_keep_unknown_chunks(png_obj->obj, keep_condition, affect_chunk_list, num_chunks); break; default: rb_raise(rb_eTypeError, "wrong argument type %s (expected Array/nil)", rb_class2name(CLASS_OF(chunk_list))); } return Qnil; } #endif /* PNG_UNKNOWN_CHUNKS_SUPPORTED */ #if defined(PNG_oFFs_SUPPORTED) static VALUE libpng_writer_set_oFFs(obj, offset_x, offset_y, unit_type) VALUE obj, offset_x, offset_y, unit_type; { png_object *png_obj; FIXNUM_P(offset_x); FIXNUM_P(offset_y); FIXNUM_P(unit_type); GET_PNG_VAL(obj, png_obj); png_set_oFFs(png_obj->obj, png_obj->info, NUM2LONG(offset_x), NUM2LONG(offset_y), FIX2INT(unit_type)); return Qnil; } #endif /* PNG_oFFs_SUPPORTED */ #if defined(PNG_WRITE_PACK_SUPPORTED) static VALUE libpng_writer_set_packing(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_packing(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_PACK_SUPPORTED */ #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) static VALUE libpng_writer_set_packswap(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_packswap(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_PACKSWAP_SUPPORTED */ #if defined(PNG_pCAL_SUPPORTED) static VALUE libpng_writer_set_pCAL(obj, purpose, X0, X1, type, unit, params) VALUE obj, purpose, X0, X1, type, unit, params; { png_object *png_obj; png_charpp pcal_params; int nparams, i; VALUE str; Check_Type(purpose, T_STRING); FIXNUM_P(X0); FIXNUM_P(X1); FIXNUM_P(type); Check_Type(unit, T_STRING); Check_Type(params, T_ARRAY); GET_PNG_VAL(obj, png_obj); nparams = RARRAY(params)->len; pcal_params = ALLOCA_N(png_charp, RARRAY(params)->len); for (i=0; ilen; i++){ Check_Type(RARRAY(params)->ptr[i], T_STRING); pcal_params[i] = ALLOCA_N(char, nparams); strcpy(pcal_params[i], STR2CSTR(RARRAY(params)->ptr[i])); } png_set_pCAL(png_obj->obj, png_obj->info, STR2CSTR(purpose), NUM2LONG(X0), NUM2LONG(X1), FIX2INT(type), nparams, STR2CSTR(unit), pcal_params); return Qnil; } #endif /* PNG_pCAL_SUPPORTED */ #if defined(PNG_pHYs_SUPPORTED) static VALUE libpng_writer_set_pHYs(obj, res_x, res_y, unit_type) VALUE obj, res_x, res_y, unit_type; { png_object *png_obj; FIXNUM_P(res_x); FIXNUM_P(res_y); FIXNUM_P(unit_type); GET_PNG_VAL(obj, png_obj); png_set_pHYs(png_obj->obj, png_obj->info, NUM2LONG(res_x), NUM2LONG(res_y), FIX2INT(unit_type)); return Qnil; } #endif /* PNG_pHYs_SUPPORTED */ static VALUE libpng_writer_set_PLTE(obj, palettes) VALUE obj, palettes; { png_object *png_obj; png_colorp pal; png_color *color; int num_palette, i; Check_Type(palettes, T_ARRAY); GET_PNG_VAL(obj, png_obj); num_palette = RARRAY(palettes)->len; pal = ALLOC_N(png_color, num_palette); for (i=0; iptr[i]); Data_Get_Struct(RARRAY(palettes)->ptr[i], png_color, color); pal[i] = *color; /* print processing palette printf("RGB: %x %x %x\n", pal[i].red, pal[i].green, pal[i].blue); */ } png_set_PLTE(png_obj->obj, png_obj->info, pal, num_palette); return Qnil; } #if defined(PNG_sBIT_SUPPORTED) static VALUE libpng_writer_set_sBIT(obj, sig_bit) VALUE obj, sig_bit; { png_object *png_obj; png_color_8p color; IS_COLOR_8_P(sig_bit); GET_PNG_VAL(obj, png_obj); Data_Get_Struct(sig_bit, png_color_8, color); png_set_sBIT(png_obj->obj, png_obj->info, color); return Qnil; } #endif /* PNG_sBIT_SUPPORTED */ #if defined(PNG_sCAL_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED static VALUE libpng_writer_set_sCAL(obj, unit, width, height) VALUE obj, unit, width, height; { png_object *png_obj; FIXNUM_P(unit); Check_Type(width, T_FLOAT); Check_Type(height, T_FLOAT); GET_PNG_VAL(obj, png_obj); png_set_sCAL(png_obj->obj, png_obj->info, FIX2INT(unit), RFLOAT(width)->value, RFLOAT(height)->value); return Qnil; } #endif /* PNG_FLOATING_POINT_SUPPORTED */ #endif /* PNG_sCAL_SUPPORTED */ #if defined(PNG_WRITE_SHIFT_SUPPORTED) static VALUE libpng_writer_set_shift(obj, true_bits) VALUE obj, true_bits; { png_object *png_obj; png_color_8p sig_bit; VALUE cobj; int i; IS_COLOR_8_P(cobj); GET_PNG_VAL(obj, png_obj); Data_Get_Struct(cobj, png_color_8, sig_bit); png_set_shift(png_obj->obj, sig_bit); return Qnil; } #endif #if defined(PNG_sPLT_SUPPORTED) static VALUE libpng_writer_set_sPLT(obj, entries) VALUE obj, entries; { png_object *png_obj; png_sPLT_tp splt_ptr; png_sPLT_t *splt_entry; int nentries, i; Check_Type(entries, T_ARRAY); GET_PNG_VAL(obj, png_obj); nentries = RARRAY(entries)->len; splt_ptr = ALLOCA_N(png_sPLT_t, nentries); for (i=0; iptr[i]); Data_Get_Struct(RARRAY(entries)->ptr[i], png_sPLT_t, splt_entry); splt_ptr[i] = *splt_entry; } png_set_sPLT(png_obj->obj, png_obj->info, splt_ptr, entries); return Qnil; } #endif /* PNG_sPLT_SUPPORTED */ #if defined(PNG_sRGB_SUPPORTED) static VALUE libpng_writer_set_sRGB(obj, intent) VALUE obj, intent; { png_object *png_obj; int srgb_intent; FIXNUM_P(intent); GET_PNG_VAL(obj, png_obj); srgb_intent = FIX2INT(intent); if (srgb_intent < PNG_sRGB_INTENT_PERCEPTUAL || srgb_intent >= PNG_sRGB_INTENT_LAST) rb_raise(ePngError, "invalid value for sRGB rendering intent type: %d", srgb_intent); png_set_sRGB(png_obj->obj, png_obj->info, srgb_intent); return Qnil; } static VALUE libpng_writer_set_sRGB_gAMA_and_cHRM(obj, intent) VALUE obj, intent; { png_object *png_obj; int srgb_intent; FIXNUM_P(intent); GET_PNG_VAL(obj, png_obj); srgb_intent = FIX2INT(intent); if (srgb_intent < PNG_sRGB_INTENT_PERCEPTUAL || srgb_intent >= PNG_sRGB_INTENT_LAST) rb_raise(ePngError, "invalid value for sRGB rendering intent type: %d", srgb_intent); png_set_sRGB_gAMA_and_cHRM(png_obj->obj, png_obj->info, srgb_intent); return Qnil; } #endif /* PNG_sRGB_SUPPORTED */ #if defined(PNG_WRITE_SWAP_SUPPORTED) static VALUE libpng_writer_set_swap(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_swap(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_SWAP_SUPPORTED */ #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) static VALUE libpng_writer_set_swap_alpha(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_set_swap_alpha(png_obj->obj); return Qnil; } #endif /* PNG_WRITE_SWAP_ALPHA_SUPPORTED */ #if defined(PNG_TEXT_SUPPORTED) static VALUE libpng_writer_set_text(obj, texts) VALUE obj, texts; { png_object *png_obj; png_textp text_ptr; png_text *text; png_infop info_ptr; int num_text, i; Check_Type(texts, T_ARRAY); GET_PNG_VAL(obj, png_obj); num_text = RARRAY(texts)->len; text_ptr = ALLOC_N(png_text, num_text); for (i=0; iptr[i]); Data_Get_Struct(RARRAY(texts)->ptr[i], png_text, text); text_ptr[i] = *text; } if (png_obj->obj->mode & PNG_WROTE_INFO_BEFORE_PLTE) info_ptr = png_obj->end_info; else info_ptr = png_obj->info; png_set_text(png_obj->obj, info_ptr, text_ptr, num_text); free(text_ptr); return Qnil; } #endif /* PNG_TEXT_SUPPORTED */ #if defined(PNG_tIME_SUPPORTED) static VALUE libpng_writer_set_tIME(obj, mod_time) VALUE obj, mod_time; { png_object *png_obj; png_time time; png_infop info_ptr; VALUE ary; IS_TIME_P(mod_time); GET_PNG_VAL(obj, png_obj); ary = rb_funcall(mod_time, rb_intern("to_a"), 0); time.year = FIX2INT(RARRAY(ary)->ptr[5]); time.month = FIX2INT(RARRAY(ary)->ptr[4]); time.day = FIX2INT(RARRAY(ary)->ptr[3]); time.hour = FIX2INT(RARRAY(ary)->ptr[2]); time.minute = FIX2INT(RARRAY(ary)->ptr[1]); time.second = FIX2INT(RARRAY(ary)->ptr[0]); if (png_obj->obj->mode & PNG_WROTE_INFO_BEFORE_PLTE) info_ptr = png_obj->end_info; else info_ptr = png_obj->info; png_set_tIME(png_obj->obj, info_ptr, &time); return Qnil; } static VALUE libpng_writer_set_tIME_end(obj, mod_time) VALUE obj, mod_time; { png_object *png_obj; png_time time; VALUE ary; IS_TIME_P(mod_time); GET_PNG_VAL(obj, png_obj); ary = rb_funcall(mod_time, rb_intern("to_a"), 0); time.year = FIX2INT(RARRAY(ary)->ptr[5]); time.month = FIX2INT(RARRAY(ary)->ptr[4]); time.day = FIX2INT(RARRAY(ary)->ptr[3]); time.hour = FIX2INT(RARRAY(ary)->ptr[2]); time.minute = FIX2INT(RARRAY(ary)->ptr[1]); time.second = FIX2INT(RARRAY(ary)->ptr[0]); png_set_tIME(png_obj->obj, png_obj->end_info, &time); return Qnil; } #endif /* PNG_tIME_SUPPORTED */ #if defined(PNG_tRNS_SUPPORTED) static VALUE libpng_writer_set_tRNS(obj, trans) VALUE obj, trans; { png_object *png_obj; png_bytep trans_entry; png_color_16p trans_value; int i, num_trans; GET_PNG_VAL(obj, png_obj); if (TYPE(trans) == T_ARRAY){ /* palette image */ num_trans = RARRAY(trans)->len; trans_entry = ALLOC_N(png_byte, num_trans); for (i=0; iptr[i]); trans_entry[i] = FIX2INT(RARRAY(trans)->ptr[i]); } png_set_tRNS(png_obj->obj, png_obj->info, trans_entry, num_trans, NULL); } else if (rb_class_of(trans) == cPngColor16){ /* non-palette image */ Data_Get_Struct(trans, png_color_16, trans_value); png_set_tRNS(png_obj->obj, png_obj->info, NULL, 0, trans_value); } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected ARRAY/Graphics::PNG::COLOR16)", rb_class2name(CLASS_OF(trans))); } return Qnil; } #endif /* PNG_tRNS_SUPPORTED */ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) static VALUE libpng_writer_set_unknown_chunks(obj, unknowns) VALUE obj, unknowns; { png_object *png_obj; png_unknown_chunkp unknown_chunks; png_unknown_chunk *unknown; int num_unknowns, i; Check_Type(unknowns, T_ARRAY); GET_PNG_VAL(obj, png_obj); num_unknowns = RARRAY(unknowns)->len; unknown_chunks = ALLOC_N(png_unknown_chunk, num_unknowns); for (i=0; iptr[i]); Data_Get_Struct(RARRAY(unknowns)->ptr[i], png_unknown_chunk, unknown); unknown_chunks[i] = *unknown; } png_set_unknown_chunks(png_obj->obj, png_obj->end_info, unknown_chunks, num_unknowns); free(unknown_chunks); return Qnil; } #endif static VALUE libpng_writer_set_write_status_fn(obj, proc) VALUE obj, proc; { if (!rb_respond_to(proc, rb_intern("call"))) rb_raise(rb_eArgError, "argument have to respond to `call'"); return rb_iv_set(cWriter, WRITE_STATUS_FN, proc); } static VALUE libpng_writer_write_end(obj) VALUE obj; { png_object *png_obj; GET_PNG_VAL(obj, png_obj); png_write_end(png_obj->obj, png_obj->end_info); return Qnil; } static VALUE libpng_writer_write_image(obj, image) VALUE obj, image; { png_object *png_obj; png_bytepp image_data; int height, row; int num_passes, pass; int i; Check_Type(image, T_ARRAY); GET_PNG_VAL(obj, png_obj); image_data = ALLOC_N(png_bytep, RARRAY(image)->len); height = RARRAY(image)->len; for (row=0; rowptr[row])->len); png_memcpy(image_data[row], STR2CSTR(RARRAY(image)->ptr[row]), RSTRING(RARRAY(image)->ptr[row])->len); /* for (i=0;iptr[row])->len;i++) printf("%2x ", image_data[row][i]); printf("\n"); */ } /* png_write_image(png_obj->obj, image_data); */ num_passes =png_set_interlace_handling(png_obj->obj); for (pass=0; passobj, &image_data[row], 1); } } for (row=0; rowobj, png_obj->info); return Qnil; } void Init_writer() { /* * --------------------- * Graphics::PNG::Writer * --------------------- */ cWriter = rb_define_class_under(mPng, "Writer", rb_cObject); rb_define_singleton_method(cWriter, "new", writer_new, 1); rb_define_method(cWriter, "initialize", writer_initialize, -1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED rb_define_method(cWriter, "set_background", libpng_writer_set_background, 4); #endif #endif #if defined(PNG_WRITE_BGR_SUPPORTED) rb_define_method(cWriter, "set_bgr", libpng_writer_set_bgr, 0); #endif #if defined(PNG_bKGD_SUPPORTED) rb_define_method(cWriter, "set_bKGD", libpng_writer_set_bKGD, 1); #endif #if defined(PNG_cHRM_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED rb_define_method(cWriter, "set_cHRM", libpng_writer_set_cHRM, 8); #endif #ifdef PNG_FIXED_POINT_SUPPORTED rb_define_method(cWriter, "set_cHRM_fixed", libpng_writer_set_cHRM_fixed, 8); #endif #endif rb_define_method(cWriter, "set_compression_level", libpng_writer_set_compression_level, 1); rb_define_method(cWriter, "set_compression_mem_level", libpng_writer_set_compression_mem_level, 1); rb_define_method(cWriter, "set_compression_method", libpng_writer_set_compression_method, 1); rb_define_method(cWriter, "set_compression_strategy", libpng_writer_set_compression_strategy, 1); rb_define_method(cWriter, "set_compression_windows_bits", libpng_writer_set_compression_window_bits, 1); rb_define_method(cWriter, "set_crc_action", libpng_writer_set_crc_action, 2); #if defined(PNG_READ_DITHER_SUPPORTED) rb_define_method(cWriter, "set_dither", libpng_writer_set_dither, 5); #endif #if defined(PNG_WRITE_FILLER_SUPPORTED) rb_define_method(cWriter, "set_filler", libpng_writer_set_filler, 2); #endif rb_define_method(cWriter, "set_filter", libpng_writer_set_filter, 2); #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED rb_define_method(cWriter, "set_filter_heuristics", libpng_writer_set_filter_heuristics, 4); #endif #endif #if defined(PNG_WRITE_FLUSH_SUPPORTED) rb_define_method(cWriter, "set_flush", libpng_writer_set_flush, 1); #endif #if defined(PNG_READ_GAMMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED rb_define_method(cWriter, "set_gamma", libpng_writer_set_gamma, 2); #endif #endif #if defined(PNG_gAMA_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED rb_define_method(cWriter, "set_gAMA", libpng_writer_set_gAMA, 1); #endif rb_define_method(cWriter, "set_gAMA_fixed", libpng_writer_set_gAMA_fixed, 1); #endif #if defined(PNG_hIST_SUPPORTED) rb_define_method(cWriter, "set_hIST", libpng_writer_set_hIST, 1); #endif #if defined(PNG_iCCP_SUPPORTED) rb_define_method(cWriter, "set_iCCP", libpng_writer_set_iCCP, 3); #endif #if defined(PNG_WRITE_INTERLACING_SUPPORTED) rb_define_method(cWriter, "set_interlace_handling", libpng_writer_set_interlace_handling, 0); #endif #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) rb_define_method(cWriter, "set_invert_alpha", libpng_writer_set_invert_alpha, 0); #endif #if defined(PNG_WRITE_INVERT_SUPPORTED) rb_define_method(cWriter, "set_invert_mono", libpng_writer_set_invert_mono, 0); #endif rb_define_method(cWriter, "set_IHDR", libpng_writer_set_IHDR, 7); #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) rb_define_method(cWriter, "set_keep_unknown_chunks", libpng_writer_set_keep_unknown_chunks, 2); #endif #if defined(PNG_oFFs_SUPPORTED) rb_define_method(cWriter, "set_oFFs", libpng_writer_set_oFFs, 3); #endif #if defined(PNG_WRITE_PACK_SUPPORTED) rb_define_method(cWriter, "set_packing", libpng_writer_set_packing, 0); #endif #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) rb_define_method(cWriter, "set_packswap", libpng_writer_set_packswap, 0); #endif #if defined(PNG_pCAL_SUPPORTED) rb_define_method(cWriter, "set_pCAL", libpng_writer_set_pCAL, 6); #endif #if defined(PNG_pHYs_SUPPORTED) rb_define_method(cWriter, "set_pHYs", libpng_writer_set_pHYs, 3); #endif rb_define_method(cWriter, "set_PLTE", libpng_writer_set_PLTE, 1); /* rb_define_method(cWriter, "set_rows", libpng_writer_set_rows, 1); */ #if defined(PNG_sBIT_SUPPORTED) rb_define_method(cWriter, "set_sBIT", libpng_writer_set_sBIT, 1); #endif #if defined(PNG_sCAL_SUPPORTED) #ifdef PNG_FLOATING_POINT_SUPPORTED rb_define_method(cWriter, "set_sCAL", libpng_writer_set_sCAL, 3); #endif /* #ifdef PNG_FIXED_POINT_SUPPORTED rb_define_method(cWriter, "set_sCAL_s", libpng_writer_set_sCAL_s, 3); #endif */ #endif #if defined(PNG_WRITE_SHIFT_SUPPORTED) rb_define_method(cWriter, "set_shift", libpng_writer_set_shift, 1); #endif #if defined(PNG_sPLT_SUPPORTED) rb_define_method(cWriter, "set_sPLT", libpng_writer_set_sPLT, 1); #endif #if defined(PNG_sRGB_SUPPORTED) rb_define_method(cWriter, "set_sRGB", libpng_writer_set_sRGB, 1); rb_define_method(cWriter, "set_sRGB_gAMA_and_cHRM", libpng_writer_set_sRGB_gAMA_and_cHRM, 1); #endif /* maybe for Reader only rb_define_method(cWriter, "set_strip_16", libpng_writer_set_strip_16, 0); */ #if defined(PNG_WRITE_SWAP_SUPPORTED) rb_define_method(cWriter, "set_swap", libpng_writer_set_swap, 0); #endif #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) rb_define_method(cWriter, "set_swap_alpha", libpng_writer_set_swap_alpha, 0); #endif #if defined(PNG_TEXT_SUPPORTED) rb_define_method(cWriter, "set_text", libpng_writer_set_text, 1); #endif #if defined(PNG_tIME_SUPPORTED) rb_define_method(cWriter, "set_tIME", libpng_writer_set_tIME, 1); #endif #if defined(PNG_tRNS_SUPPORTED) rb_define_method(cWriter, "set_tRNS", libpng_writer_set_tRNS, 1); #endif /* maybe for Reader only rb_define_method(cWriter, "set_tRNS_to_alpha", libpng_writer_set_tRNS_to_alpha, 0); */ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) rb_define_method(cWriter, "set_unknown_chunks", libpng_writer_set_unknown_chunks, 1); #endif /* #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) rb_define_method(cWriter, "set_user_transform_info", libpng_writer_set_user_transform_info, 3); #endif rb_define_method(cWriter, "write_chunk", libpng_writer_write_chunk, 3); rb_define_method(cWriter, "write_chunk_start", libpng_writer_write_chunk_start, 2); rb_define_method(cWriter, "write_chunk_data", libpng_writer_write_chunk_data, 2); rb_define_method(cWriter, "write_chunk_end", libpng_writer_write_chunk_end, 0); */ rb_define_method(cWriter, "set_write_status_fn", libpng_writer_set_write_status_fn, 1); rb_define_method(cWriter, "write_end", libpng_writer_write_end, 0); rb_define_method(cWriter, "write_image", libpng_writer_write_image, 1); rb_define_method(cWriter, "write_info", libpng_writer_write_info, 0); /* #if defined(PNG_INFO_IMAGE_SUPPORTED) rb_define_method(cWriter, "write_png", libpng_writer_write_png, 2); #endif */ }