SIXELSTATUS sixel_chunk_new( sixel_chunk_t /* out */ **ppchunk, char const /* in */ *filename, int /* in */ finsecure, int const /* in */ *cancel_flag, sixel_allocator_t /* in */ *allocator) { SIXELSTATUS status = SIXEL_FALSE; if (ppchunk == NULL) { sixel_helper_set_additional_message( "sixel_chunk_new: ppchunk is null."); status = SIXEL_BAD_ARGUMENT; goto end; } if (allocator == NULL) { sixel_helper_set_additional_message( "sixel_chunk_new: allocator is null."); status = SIXEL_BAD_ARGUMENT; goto end; } *ppchunk = (sixel_chunk_t *)sixel_allocator_malloc(allocator, sizeof(sixel_chunk_t)); if (*ppchunk == NULL) { sixel_helper_set_additional_message( "sixel_chunk_new: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } /* set allocator to chunk object */ (*ppchunk)->allocator = allocator; status = sixel_chunk_init(*ppchunk, 1024 * 32); if (SIXEL_FAILED(status)) { sixel_allocator_free(allocator, *ppchunk); *ppchunk = NULL; goto end; } sixel_allocator_ref(allocator); if (filename != NULL && strstr(filename, "://")) { status = sixel_chunk_from_url(filename, *ppchunk, finsecure); } else { status = sixel_chunk_from_file(filename, *ppchunk, cancel_flag); } if (SIXEL_FAILED(status)) { sixel_chunk_destroy(*ppchunk); *ppchunk = NULL; goto end; } status = SIXEL_OK; end: return status; }
/* create new output context object */ SIXELAPI SIXELSTATUS sixel_output_new( sixel_output_t /* out */ **output, sixel_write_function /* in */ fn_write, void /* in */ *priv, sixel_allocator_t /* in */ *allocator) { SIXELSTATUS status = SIXEL_FALSE; size_t size; if (allocator == NULL) { status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL); if (SIXEL_FAILED(status)) { goto end; } } else { sixel_allocator_ref(allocator); } size = sizeof(sixel_output_t) + SIXEL_OUTPUT_PACKET_SIZE * 2; *output = (sixel_output_t *)sixel_allocator_malloc(allocator, size); if (*output == NULL) { sixel_helper_set_additional_message( "sixel_output_new: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } (*output)->ref = 1; (*output)->has_8bit_control = 0; (*output)->has_sdm_glitch = 0; (*output)->has_gri_arg_limit = 1; (*output)->skip_dcs_envelope = 0; (*output)->palette_type = SIXEL_PALETTETYPE_AUTO; (*output)->fn_write = fn_write; (*output)->save_pixel = 0; (*output)->save_count = 0; (*output)->active_palette = (-1); (*output)->node_top = NULL; (*output)->node_free = NULL; (*output)->priv = priv; (*output)->pos = 0; (*output)->penetrate_multiplexer = 0; (*output)->encode_policy = SIXEL_ENCODEPOLICY_AUTO; (*output)->allocator = allocator; status = SIXEL_OK; end: return status; }
/* initialize chunk object with specified size */ static SIXELSTATUS sixel_chunk_init( sixel_chunk_t * const /* in */ pchunk, size_t /* in */ initial_size) { SIXELSTATUS status = SIXEL_FALSE; pchunk->max_size = initial_size; pchunk->size = 0; pchunk->buffer = (unsigned char *)sixel_allocator_malloc(pchunk->allocator, pchunk->max_size); if (pchunk->buffer == NULL) { sixel_helper_set_additional_message( "sixel_chunk_init: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } status = SIXEL_OK; end: return status; }
static SIXELSTATUS gif_init_frame( sixel_frame_t /* in */ *frame, gif_t /* in */ *pg, unsigned char /* in */ *bgcolor, int /* in */ reqcolors, int /* in */ fuse_palette) { SIXELSTATUS status = SIXEL_OK; int i; int ncolors; frame->delay = pg->delay; ncolors = 2 << (pg->flags & 7); if (frame->palette == NULL) { frame->palette = (unsigned char *)sixel_allocator_malloc(frame->allocator, ncolors * 3); } else if (frame->ncolors < ncolors) { sixel_allocator_free(frame->allocator, frame->palette); frame->palette = (unsigned char *)sixel_allocator_malloc(frame->allocator, ncolors * 3); } if (frame->palette == NULL) { sixel_helper_set_additional_message( "gif_init_frame: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } frame->ncolors = ncolors; if (frame->ncolors <= reqcolors && fuse_palette) { frame->pixelformat = SIXEL_PIXELFORMAT_PAL8; sixel_allocator_free(frame->allocator, frame->pixels); frame->pixels = (unsigned char *)sixel_allocator_malloc(frame->allocator, frame->width * frame->height); if (frame->pixels == NULL) { sixel_helper_set_additional_message( "sixel_allocator_malloc() failed in gif_init_frame()."); status = SIXEL_BAD_ALLOCATION; goto end; } memcpy(frame->pixels, pg->out, frame->width * frame->height); for (i = 0; i < frame->ncolors; ++i) { frame->palette[i * 3 + 0] = pg->color_table[i * 3 + 2]; frame->palette[i * 3 + 1] = pg->color_table[i * 3 + 1]; frame->palette[i * 3 + 2] = pg->color_table[i * 3 + 0]; } if (pg->lflags & 0x80) { if (pg->eflags & 0x01) { if (bgcolor) { frame->palette[pg->transparent * 3 + 0] = bgcolor[0]; frame->palette[pg->transparent * 3 + 1] = bgcolor[1]; frame->palette[pg->transparent * 3 + 2] = bgcolor[2]; } else { frame->transparent = pg->transparent; } } } else if (pg->flags & 0x80) { if (pg->eflags & 0x01) { if (bgcolor) { frame->palette[pg->transparent * 3 + 0] = bgcolor[0]; frame->palette[pg->transparent * 3 + 1] = bgcolor[1]; frame->palette[pg->transparent * 3 + 2] = bgcolor[2]; } else { frame->transparent = pg->transparent; } } } } else { frame->pixelformat = SIXEL_PIXELFORMAT_RGB888; frame->pixels = (unsigned char *)sixel_allocator_malloc(frame->allocator, pg->w * pg->h * 3); if (frame->pixels == NULL) { sixel_helper_set_additional_message( "sixel_allocator_malloc() failed in gif_init_frame()."); status = SIXEL_BAD_ALLOCATION; goto end; } for (i = 0; i < pg->w * pg->h; ++i) { frame->pixels[i * 3 + 0] = pg->color_table[pg->out[i] * 3 + 2]; frame->pixels[i * 3 + 1] = pg->color_table[pg->out[i] * 3 + 1]; frame->pixels[i * 3 + 2] = pg->color_table[pg->out[i] * 3 + 0]; } } frame->multiframe = (pg->loop_count != (-1)); status = SIXEL_OK; end: return status; }
SIXELAPI unsigned char * sixel_dither_apply_palette( sixel_dither_t /* in */ *dither, unsigned char /* in */ *pixels, int /* in */ width, int /* in */ height) { SIXELSTATUS status = SIXEL_FALSE; int bufsize; unsigned char *dest = NULL; int ncolors; unsigned char *normalized_pixels = NULL; unsigned char *input_pixels; if (dither == NULL) { sixel_helper_set_additional_message( "sixel_dither_apply_palette: dither is null."); status = SIXEL_BAD_ARGUMENT; goto end; } sixel_dither_ref(dither); bufsize = width * height * sizeof(unsigned char); dest = (unsigned char *)sixel_allocator_malloc(dither->allocator, bufsize); if (dest == NULL) { sixel_helper_set_additional_message( "sixel_dither_new: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } /* if quality_mode is full, do not use palette caching */ if (dither->quality_mode == SIXEL_QUALITY_FULL) { dither->optimized = 0; } if (dither->cachetable == NULL && dither->optimized) { if (dither->palette != pal_mono_dark && dither->palette != pal_mono_light) { dither->cachetable = (unsigned short *)sixel_allocator_calloc(dither->allocator, 1 << 3 * 5, sizeof(unsigned short)); if (dither->cachetable == NULL) { sixel_helper_set_additional_message( "sixel_dither_new: sixel_allocator_calloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } } } if (dither->pixelformat != SIXEL_PIXELFORMAT_RGB888) { /* normalize pixelformat */ normalized_pixels = (unsigned char *)sixel_allocator_malloc(dither->allocator, width * height * 3); if (normalized_pixels == NULL) { sixel_helper_set_additional_message( "sixel_dither_new: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } status = sixel_helper_normalize_pixelformat(normalized_pixels, &dither->pixelformat, pixels, dither->pixelformat, width, height); if (SIXEL_FAILED(status)) { goto end; } input_pixels = normalized_pixels; } else { input_pixels = pixels; } status = sixel_quant_apply_palette(dest, input_pixels, width, height, 3, dither->palette, dither->ncolors, dither->method_for_diffuse, dither->optimized, dither->optimize_palette, dither->complexion, dither->cachetable, &ncolors, dither->allocator); if (SIXEL_FAILED(status)) { free(dest); dest = NULL; goto end; } dither->ncolors = ncolors; end: free(normalized_pixels); sixel_dither_unref(dither); return dest; }
SIXELAPI SIXELSTATUS sixel_dither_initialize( sixel_dither_t /* in */ *dither, unsigned char /* in */ *data, int /* in */ width, int /* in */ height, int /* in */ pixelformat, int /* in */ method_for_largest, int /* in */ method_for_rep, int /* in */ quality_mode) { unsigned char *buf = NULL; unsigned char *normalized_pixels = NULL; unsigned char *input_pixels; SIXELSTATUS status = SIXEL_FALSE; if (dither == NULL) { sixel_helper_set_additional_message( "sixel_dither_new: dither is null."); status = SIXEL_BAD_ARGUMENT; goto end; } sixel_dither_ref(dither); sixel_dither_set_pixelformat(dither, pixelformat); if (pixelformat != SIXEL_PIXELFORMAT_RGB888) { /* normalize pixelformat */ normalized_pixels = (unsigned char *)sixel_allocator_malloc(dither->allocator, width * height * 3); if (normalized_pixels == NULL) { sixel_helper_set_additional_message( "sixel_dither_initialize: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } status = sixel_helper_normalize_pixelformat( normalized_pixels, &pixelformat, data, pixelformat, width, height); if (SIXEL_FAILED(status)) { goto end; } input_pixels = normalized_pixels; } else { input_pixels = data; } sixel_dither_set_method_for_largest(dither, method_for_largest); sixel_dither_set_method_for_rep(dither, method_for_rep); sixel_dither_set_quality_mode(dither, quality_mode); status = sixel_quant_make_palette(&buf, input_pixels, width * height * 3, SIXEL_PIXELFORMAT_RGB888, dither->reqcolors, &dither->ncolors, &dither->origcolors, dither->method_for_largest, dither->method_for_rep, dither->quality_mode, dither->allocator); if (SIXEL_FAILED(status)) { goto end; } memcpy(dither->palette, buf, dither->ncolors * 3); dither->optimized = 1; if (dither->origcolors <= dither->ncolors) { dither->method_for_diffuse = SIXEL_DIFFUSE_NONE; } sixel_quant_free_palette(buf, dither->allocator); status = SIXEL_OK; end: free(normalized_pixels); sixel_dither_unref(dither); return status; }
/* create dither context object */ SIXELAPI SIXELSTATUS sixel_dither_new( sixel_dither_t /* out */ **ppdither, /* dither object to be created */ int /* in */ ncolors, /* required colors */ sixel_allocator_t /* in */ *allocator) /* allocator, null if you use default allocator */ { SIXELSTATUS status = SIXEL_FALSE; int headsize; int datasize; int wholesize; int quality_mode; if (ppdither == NULL) { sixel_helper_set_additional_message( "sixel_dither_new: ppdither is null."); status = SIXEL_BAD_ARGUMENT; goto end; } if (allocator == NULL) { status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL); if (SIXEL_FAILED(status)) { *ppdither = NULL; goto end; } } else { sixel_allocator_ref(allocator); } if (ncolors == (-1)) { ncolors = 256; quality_mode = SIXEL_QUALITY_HIGHCOLOR; } else { if (ncolors > SIXEL_PALETTE_MAX) { ncolors = 256; } else if (ncolors < 2) { ncolors = 2; } quality_mode = SIXEL_QUALITY_LOW; } headsize = sizeof(sixel_dither_t); datasize = ncolors * 3; wholesize = headsize + datasize; *ppdither = (sixel_dither_t *)sixel_allocator_malloc(allocator, wholesize); if (*ppdither == NULL) { sixel_allocator_unref(allocator); sixel_helper_set_additional_message( "sixel_dither_new: sixel_allocator_malloc() failed."); status = SIXEL_BAD_ALLOCATION; goto end; } (*ppdither)->ref = 1; (*ppdither)->palette = (unsigned char*)(*ppdither + 1); (*ppdither)->cachetable = NULL; (*ppdither)->reqcolors = ncolors; (*ppdither)->ncolors = ncolors; (*ppdither)->origcolors = (-1); (*ppdither)->keycolor = (-1); (*ppdither)->optimized = 0; (*ppdither)->optimize_palette = 0; (*ppdither)->complexion = 1; (*ppdither)->bodyonly = 0; (*ppdither)->method_for_largest = SIXEL_LARGE_NORM; (*ppdither)->method_for_rep = SIXEL_REP_CENTER_BOX; (*ppdither)->method_for_diffuse = SIXEL_DIFFUSE_FS; (*ppdither)->quality_mode = quality_mode; (*ppdither)->pixelformat = SIXEL_PIXELFORMAT_RGB888; (*ppdither)->allocator = allocator; status = SIXEL_OK; end: return status; }