int xps_decode_jpegxr(xps_context_t *ctx, byte *buf, int len, xps_image_t *output) { FILE *file; char *name = xps_alloc(ctx, gp_file_name_sizeof); struct state state; jxr_container_t container; jxr_image_t image; int offset, alpha_offset; int rc; if (!name) { return gs_throw(gs_error_VMerror, "cannot allocate scratch file name buffer"); } memset(output, 0, sizeof(*output)); file = gp_open_scratch_file(ctx->memory, "jpegxr-scratch-", name, "wb+"); if (!file) { xps_free(ctx, name); return gs_throw(gs_error_invalidfileaccess, "cannot open scratch file"); } rc = fwrite(buf, 1, len, file); if (rc != len) { xps_free(ctx, name); return gs_throw(gs_error_invalidfileaccess, "cannot write to scratch file"); } fseek(file, 0, SEEK_SET); container = jxr_create_container(); rc = jxr_read_image_container(container, file); if (rc < 0) { xps_free(ctx, name); return gs_throw1(-1, "jxr_read_image_container: %s", jxr_error_string(rc)); } offset = jxrc_image_offset(container, 0); alpha_offset = jxrc_alpha_offset(container, 0); output->xres = jxrc_width_resolution(container, 0); output->yres = jxrc_height_resolution(container, 0); image = jxr_create_input(); jxr_set_PROFILE_IDC(image, 111); jxr_set_LEVEL_IDC(image, 255); jxr_set_pixel_format(image, jxrc_image_pixelformat(container, 0)); jxr_set_container_parameters(image, jxrc_image_pixelformat(container, 0), jxrc_image_width(container, 0), jxrc_image_height(container, 0), jxrc_alpha_offset(container, 0), jxrc_image_band_presence(container, 0), jxrc_alpha_band_presence(container, 0), 0); jxr_set_block_output(image, xps_decode_jpegxr_block); state.ctx = ctx; state.output = output; jxr_set_user_data(image, &state); fseek(file, offset, SEEK_SET); rc = jxr_read_image_bitstream(image, file); if (rc < 0) { xps_free(ctx, name); return gs_throw1(-1, "jxr_read_image_bitstream: %s", jxr_error_string(rc)); } jxr_destroy(image); if (alpha_offset > 0) { image = jxr_create_input(); jxr_set_PROFILE_IDC(image, 111); jxr_set_LEVEL_IDC(image, 255); jxr_set_pixel_format(image, jxrc_image_pixelformat(container, 0)); jxr_set_container_parameters(image, jxrc_image_pixelformat(container, 0), jxrc_image_width(container, 0), jxrc_image_height(container, 0), jxrc_alpha_offset(container, 0), jxrc_image_band_presence(container, 0), jxrc_alpha_band_presence(container, 0), 0); jxr_set_block_output(image, xps_decode_jpegxr_alpha_block); state.ctx = ctx; state.output = output; jxr_set_user_data(image, &state); fseek(file, alpha_offset, SEEK_SET); rc = jxr_read_image_bitstream(image, file); if (rc < 0) { xps_free(ctx, name); return gs_throw1(-1, "jxr_read_image_bitstream: %s", jxr_error_string(rc)); } jxr_destroy(image); } jxr_destroy_container(container); fclose(file); unlink(name); xps_free(ctx, name); return gs_okay; }
unsigned short jxrc_color_space(jxr_container_t container, int image) { assert(image < container->image_count); unsigned ifd_cnt = container->table_cnt[image]; struct ifd_table*ifd = container->table[image]; unsigned idx; for (idx = 0 ; idx < ifd_cnt ; idx += 1) { if (ifd[idx].tag == 0xa001) break; } if (idx >= ifd_cnt) return 0; if (ifd[idx].tag != 0xa001) return 0; assert(ifd[idx].cnt == 1); assert(ifd[idx].type == 3); unsigned short value = ifd[idx].value_.v_short[0]; if (value != 0x0001) value = 0xffff; if (value == 0x0001) { switch(jxrc_image_pixelformat(container, image)) { case JXRC_FMT_24bppRGB: case JXRC_FMT_24bppBGR: case JXRC_FMT_32bppBGR: case JXRC_FMT_48bppRGB: case JXRC_FMT_32bppBGRA: case JXRC_FMT_64bppRGBA: case JXRC_FMT_32bppPBGRA: case JXRC_FMT_64bppPRGBA: case JXRC_FMT_32bppCMYK: case JXRC_FMT_40bppCMYKAlpha: case JXRC_FMT_64bppCMYK: case JXRC_FMT_80bppCMYKAlpha: case JXRC_FMT_24bpp3Channels: case JXRC_FMT_32bpp4Channels: case JXRC_FMT_40bpp5Channels: case JXRC_FMT_48bpp6Channels: case JXRC_FMT_56bpp7Channels: case JXRC_FMT_64bpp8Channels: case JXRC_FMT_32bpp3ChannelsAlpha: case JXRC_FMT_40bpp4ChannelsAlpha: case JXRC_FMT_48bpp5ChannelsAlpha: case JXRC_FMT_56bpp6ChannelsAlpha: case JXRC_FMT_64bpp7ChannelsAlpha: case JXRC_FMT_72bpp8ChannelsAlpha: case JXRC_FMT_48bpp3Channels: case JXRC_FMT_64bpp4Channels: case JXRC_FMT_80bpp5Channels: case JXRC_FMT_96bpp6Channels: case JXRC_FMT_112bpp7Channels: case JXRC_FMT_128bpp8Channels: case JXRC_FMT_64bpp3ChannelsAlpha: case JXRC_FMT_80bpp4ChannelsAlpha: case JXRC_FMT_96bpp5ChannelsAlpha: case JXRC_FMT_112bpp6ChannelsAlpha: case JXRC_FMT_128bpp7ChannelsAlpha: case JXRC_FMT_144bpp8ChannelsAlpha: case JXRC_FMT_8bppGray: case JXRC_FMT_16bppGray: case JXRC_FMT_BlackWhite: case JXRC_FMT_16bppBGR555: case JXRC_FMT_16bppBGR565: case JXRC_FMT_32bppBGR101010: case JXRC_FMT_32bppCMYKDIRECT: case JXRC_FMT_64bppCMYKDIRECT: case JXRC_FMT_40bppCMYKDIRECTAlpha: case JXRC_FMT_80bppCMYKDIRECTAlpha: case JXRC_FMT_12bppYCC420: case JXRC_FMT_16bppYCC422: case JXRC_FMT_20bppYCC422: case JXRC_FMT_32bppYCC422: case JXRC_FMT_24bppYCC444: case JXRC_FMT_30bppYCC444: case JXRC_FMT_48bppYCC444: case JXRC_FMT_20bppYCC420Alpha: case JXRC_FMT_24bppYCC422Alpha: case JXRC_FMT_30bppYCC422Alpha: case JXRC_FMT_48bppYCC422Alpha: case JXRC_FMT_32bppYCC444Alpha: case JXRC_FMT_40bppYCC444Alpha: case JXRC_FMT_64bppYCC444Alpha: break; default: /* Color space tag can equal 1 only if format is UINT */ assert(0); break; } } return value; }
static void jxr_read_image(fz_context *ctx, unsigned char *data, int size, struct info *info, int only_metadata) { jxr_container_t container; jxr_image_t image = NULL; jxr_image_t alpha = NULL; int rc, i; fz_try(ctx) { container = jxr_create_container(); rc = jxr_read_image_container_memory(container, data, size); if (rc < 0) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read jxr image container: %s", jxr_error_string(rc)); info->xres = jxrc_width_resolution(container, 0); info->yres = jxrc_height_resolution(container, 0); info->width = jxrc_image_width(container, 0); info->height = jxrc_image_height(container, 0); info->format = jxrc_image_pixelformat(container, 0); for (i = 0; i < nelem(pixelformats); i++) if (pixelformats[i].format == info->format) { info->comps = pixelformats[i].comps; break; } if (i == nelem(pixelformats)) fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported pixel format: %u", info->format); if (info->comps == 1) info->cspace = fz_device_gray(ctx); else if (info->comps == 3) info->cspace = fz_device_rgb(ctx); else if (info->comps >= 4) info->cspace = fz_device_cmyk(ctx); info->stride = info->width * (fz_colorspace_n(ctx, info->cspace) + 1); if (!only_metadata) { unsigned long image_offset; unsigned char image_band; unsigned long alpha_offset; unsigned char alpha_band; info->ctx = ctx; info->samples = fz_malloc(ctx, info->stride * info->height); memset(info->samples, 0xff, info->stride * info->height); image_offset = jxrc_image_offset(container, 0); image_band = jxrc_image_band_presence(container, 0); alpha_offset = jxrc_alpha_offset(container, 0); alpha_band = jxrc_alpha_band_presence(container, 0); image = jxr_create_input(); jxr_set_PROFILE_IDC(image, 111); jxr_set_LEVEL_IDC(image, 255); jxr_set_pixel_format(image, info->format); jxr_set_container_parameters(image, info->format, info->width, info->height, alpha_offset, image_band, alpha_band, 0); jxr_set_user_data(image, info); jxr_set_block_output(image, jxr_decode_block); rc = jxr_read_image_bitstream_memory(image, data + image_offset, size - image_offset); if (rc < 0) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read jxr image: %s", jxr_error_string(rc)); if (info->format == JXRC_FMT_32bppPBGRA || info->format == JXRC_FMT_64bppPRGBA || info->format == JXRC_FMT_128bppPRGBAFloat) info->has_premul = 1; if (jxr_get_ALPHACHANNEL_FLAG(image)) info->has_alpha = 1; if (alpha_offset > 0) { info->has_alpha = 1; alpha = jxr_create_input(); jxr_set_PROFILE_IDC(alpha, 111); jxr_set_LEVEL_IDC(alpha, 255); jxr_set_pixel_format(alpha, info->format); jxr_set_container_parameters(alpha, info->format, info->width, info->height, alpha_offset, image_band, alpha_band, 1); jxr_set_user_data(alpha, info); jxr_set_block_output(alpha, jxr_decode_block_alpha); rc = jxr_read_image_bitstream_memory(alpha, data + alpha_offset, size - alpha_offset); if (rc < 0) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read jxr image: %s", jxr_error_string(rc)); } } } fz_always(ctx) { if (alpha) jxr_destroy(alpha); if (image) jxr_destroy(image); jxr_destroy_container(container); } fz_catch(ctx) { fz_rethrow(ctx); } }