void *iw_realloc(const char *file, unsigned int line, void *ptr, size_t size) { if(!iw_memory_tracking) { return realloc(ptr, size); } void *new_chunk = NULL; // TODO: To simplify realloc we just allocate a new memory chunk and free the // old one. if(size != 0) { new_chunk = iw_malloc(file, line, size); if(new_chunk == NULL) { // Realloc does not free or move the old memory if allocation fails. return NULL; } } if(ptr != NULL) { if(new_chunk != NULL) { void *len_ptr = ptr - PRE_GUARD_SIZE - LEN_SIZE; unsigned int len = ntohl(*(unsigned int *)len_ptr); memcpy(new_chunk, ptr, len); } iw_free(ptr); } return new_chunk; }
// Allocate a large block of memory, presumably for image data. // Use this if integer overflow is a possibility when multiplying // two factors together. void *iw_malloc_large(struct iw_context *ctx, size_t n1, size_t n2) { if(n1 > ctx->max_malloc/n2) { iw_seterror(ctx,iwcore_get_string(ctx,iws_image_too_large)); return NULL; } return iw_malloc(ctx,n1*n2); }
char *iw_strdup(const char *file, unsigned int line, const char *ptr) { if(!iw_memory_tracking) { return strdup(ptr); } int len = strlen(ptr) + 1; void *chunk = iw_malloc(file, line, len); if(chunk == NULL) { return NULL; } memcpy(chunk, ptr, len + 1); return chunk; }
void *iw_calloc(const char *file, unsigned int line, int elems, size_t size) { if(!iw_memory_tracking) { return calloc(elems, size); } void *chunk = iw_malloc(file, line, elems * size); if(chunk == NULL) { return NULL; } memset(chunk, 0, size); return chunk; }
int iw_file_to_memory(struct iw_context *ctx, struct iw_iodescr *iodescr, void **pmem, size_t *psize) { int ret; size_t bytesread; *pmem=NULL; *psize=0; if(!iodescr->getfilesize_fn) return 0; ret = (*iodescr->getfilesize_fn)(ctx,iodescr,psize); if(!ret) return 0; *pmem = iw_malloc(ctx,*psize); ret = (*iodescr->read_fn)(ctx,iodescr,*pmem,*psize,&bytesread); if(!ret) return 0; if(bytesread != *psize) return 0; return 1; }
// Optimize to palette, or 1-, 2-, or 4-bpp grayscale. static void iwopt_try_pal_lowgray_optimization(struct iw_context *ctx, struct iw_opt_ctx *optctx) { int ret; int binary_trns; unsigned int trns_shade; if(!(ctx->output_profile&IW_PROFILE_PAL1) && !(ctx->output_profile&IW_PROFILE_PAL2) && !(ctx->output_profile&IW_PROFILE_PAL4) && !(ctx->output_profile&IW_PROFILE_PAL8) && !(ctx->output_profile&IW_PROFILE_GRAY1) && !(ctx->output_profile&IW_PROFILE_GRAY2) && !(ctx->output_profile&IW_PROFILE_GRAY4) ) { // Output format doesn't support anything that this optimization can provide. return; } if(optctx->bit_depth!=8) { // Palettes aren't supported with bitdepth>8. return; } optctx->palette = iw_malloc(ctx,sizeof(struct iw_palette)); if(!optctx->palette) return; optctx->palette->num_entries=0; ret = optctx_collect_palette_colors(ctx,optctx); if(!ret) { // Image can't be converted to a palette image. goto done; } // optctx->palette now contains a palette that can be used. // For images that have at most 256 (8-bit-compatible) colors, the order // of preference is gray1, pal1, gray2, pal2, gray4, pal4, gray8, pal8. if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAY1) && iwopt_palette_is_valid_gray(ctx,optctx,1,&binary_trns,&trns_shade)) { // Replace the palette with a fully-populated grayscale palette. // The palette might already be correct, but it might not be. // It will be missing any gray shade that wasn't in the image. iwopt_make_gray_palette(ctx,optctx,1); if(binary_trns) { optctx->has_colorkey_trns = 1; optctx->colorkey_r = optctx->colorkey_b = optctx->colorkey_g = trns_shade; } } else if(iwopt_palette_opt_ok(ctx,optctx,1)) { ; } else if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAY2) && iwopt_palette_is_valid_gray(ctx,optctx,2,&binary_trns,&trns_shade)) { iwopt_make_gray_palette(ctx,optctx,2); if(binary_trns) { optctx->has_colorkey_trns = 1; optctx->colorkey_r = optctx->colorkey_b = optctx->colorkey_g = trns_shade; } } else if(iwopt_palette_opt_ok(ctx,optctx,2)) { ; } else if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAY4) && iwopt_palette_is_valid_gray(ctx,optctx,4,&binary_trns,&trns_shade)) { iwopt_make_gray_palette(ctx,optctx,4); if(binary_trns) { optctx->has_colorkey_trns = 1; optctx->colorkey_r = optctx->colorkey_b = optctx->colorkey_g = trns_shade; } } else if(iwopt_palette_opt_ok(ctx,optctx,4)) { ; } else if(ctx->opt_grayscale && (ctx->output_profile&IW_PROFILE_GRAYSCALE) && iwopt_palette_is_valid_gray(ctx,optctx,8,&binary_trns,&trns_shade)) { // This image can best be encoded as 8-bit grayscale. We don't handle that here. goto done; } else if(iwopt_palette_opt_ok(ctx,optctx,8)) { ; } else { // Found no optimizations that we can perform. goto done; } if(!optctx->palette_is_grayscale) { // Sort the palette qsort((void*)optctx->palette->entry,optctx->palette->num_entries, sizeof(struct iw_rgba8color),iwopt_palsortfunc); } iwopt_convert_to_palette_image(ctx,optctx); done: if(optctx->imgtype!=IW_IMGTYPE_PALETTE) { iw_free(optctx->palette); optctx->palette = NULL; } }