/* * Copyright (c) 2022, yzrh * * SPDX-License-Identifier: Apache-2.0 */ #include #include typedef struct _stream_user_data { OPJ_SIZE_T pos; OPJ_SIZE_T size; const unsigned char *data; } stream_user_data; static OPJ_SIZE_T _opj_stream_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { stream_user_data *d = (stream_user_data *) p_user_data; if (d->pos >= d->size) return (OPJ_SIZE_T) - 1; OPJ_SIZE_T ret_size = p_nb_bytes; if (d->pos + ret_size > d->size) ret_size = d->size - d->pos; memcpy(p_buffer, d->data + d->pos, ret_size); d->pos += ret_size; return ret_size; } static OPJ_OFF_T _opj_stream_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data) { stream_user_data *d = (stream_user_data *) p_user_data; if (d->pos + p_nb_bytes <= d->size) d->pos += p_nb_bytes; else d->pos = d->size; return d->pos; } static OPJ_BOOL _opj_stream_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data) { stream_user_data *d = (stream_user_data *) p_user_data; if (p_nb_bytes <= (OPJ_OFF_T) d->size) { d->pos = p_nb_bytes; return OPJ_TRUE; } return OPJ_FALSE; } int strinfo_jp2_dim(int *jp2_width, int *jp2_height, const char * restrict data, int data_size) { opj_codec_t *codec; opj_dparameters_t param; opj_stream_t *stream; opj_image_t *image; stream_user_data d; if (data_size < 2) return 1; opj_set_default_decoder_parameters(¶m); if ((unsigned char) data[0] == 0xff && (unsigned char) data[1] == 0x4f) codec = opj_create_decompress(OPJ_CODEC_J2K); else codec = opj_create_decompress(OPJ_CODEC_JP2); if (!opj_setup_decoder(codec, ¶m)) { opj_destroy_codec(codec); return 1; } stream = opj_stream_default_create(OPJ_TRUE); d.pos = 0; d.size = data_size; d.data = (unsigned char *) data; opj_stream_set_read_function(stream, _opj_stream_read); opj_stream_set_skip_function(stream, _opj_stream_skip); opj_stream_set_seek_function(stream, _opj_stream_seek); opj_stream_set_user_data(stream, &d, NULL); opj_stream_set_user_data_length(stream, data_size); if (!opj_read_header(stream, codec, &image)) { opj_destroy_codec(codec); opj_stream_destroy(stream); return 1; } opj_destroy_codec(codec); opj_stream_destroy(stream); *jp2_width = image->x1 - image->x0; *jp2_height = image->y1 - image->y0; opj_image_destroy(image); return 0; }