This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/imbuf/intern/jp2.c
Matt Ebb e3587f9e9f Fix [#22304] Tiff 16bit gives darker images
Also fixed similar issue for jpeg2000
2010-05-18 07:28:44 +00:00

747 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifdef WITH_OPENJPEG
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "openjpeg.h"
#define JP2_FILEHEADER_SIZE 14
static char JP2_HEAD[]= {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A};
/* We only need this because of how the presets are set */
typedef struct img_folder{
/** The directory path of the folder containing input images*/
char *imgdirpath;
/** Output format*/
char *out_format;
/** Enable option*/
char set_imgdir;
/** Enable Cod Format for output*/
char set_out_format;
/** User specified rate stored in case of cinema option*/
float *rates;
}img_fol_t;
static int checkj2p(unsigned char *mem) /* J2K_CFMT */
{
return memcmp(JP2_HEAD, mem, 12) ? 0 : 1;
}
int imb_is_a_jp2(unsigned char *buf)
{
return checkj2p(buf);
}
/**
sample error callback expecting a FILE* client object
*/
void error_callback(const char *msg, void *client_data) {
FILE *stream = (FILE*)client_data;
fprintf(stream, "[ERROR] %s", msg);
}
/**
sample warning callback expecting a FILE* client object
*/
void warning_callback(const char *msg, void *client_data) {
FILE *stream = (FILE*)client_data;
fprintf(stream, "[WARNING] %s", msg);
}
/**
sample debug callback expecting no client object
*/
void info_callback(const char *msg, void *client_data) {
(void)client_data;
fprintf(stdout, "[INFO] %s", msg);
}
struct ImBuf *imb_jp2_decode(unsigned char *mem, int size, int flags)
{
struct ImBuf *ibuf = 0;
int use_float = 0; /* for precision higher then 8 use float */
long signed_offsets[4] = {0,0,0,0};
int float_divs[4];
int index;
int w, h, depth;
opj_dparameters_t parameters; /* decompression parameters */
opj_event_mgr_t event_mgr; /* event manager */
opj_image_t *image = NULL;
int i;
opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
opj_cio_t *cio = NULL;
if (checkj2p(mem) == 0) return(0);
/* configure the event callbacks (not required) */
memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
event_mgr.error_handler = error_callback;
event_mgr.warning_handler = warning_callback;
event_mgr.info_handler = info_callback;
/* set decoding parameters to default values */
opj_set_default_decoder_parameters(&parameters);
/* JPEG 2000 compressed image data */
/* get a decoder handle */
dinfo = opj_create_decompress(CODEC_JP2);
/* catch events using our callbacks and give a local context */
opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
/* setup the decoder decoding parameters using the current image and user parameters */
opj_setup_decoder(dinfo, &parameters);
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)dinfo, mem, size);
/* decode the stream and fill the image structure */
image = opj_decode(dinfo, cio);
if(!image) {
fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
opj_destroy_decompress(dinfo);
opj_cio_close(cio);
return NULL;
}
/* close the byte stream */
opj_cio_close(cio);
if((image->numcomps * image->x1 * image->y1) == 0)
{
fprintf(stderr,"\nError: invalid raw image parameters\n");
return NULL;
}
w = image->comps[0].w;
h = image->comps[0].h;
switch (image->numcomps) {
case 1: /* Greyscale */
case 3: /* Color */
depth= 24;
break;
default: /* 2 or 4 - Greyscale or Color + alpha */
depth= 32; /* greyscale + alpha */
break;
}
i = image->numcomps;
if (i>4) i= 4;
while (i) {
i--;
if (image->comps[i].prec > 8)
use_float = 1;
if (image->comps[i].sgnd)
signed_offsets[i]= 1 << (image->comps[i].prec - 1);
/* only needed for float images but dosnt hurt to calc this */
float_divs[i]= (1<<image->comps[i].prec)-1;
}
ibuf= IMB_allocImBuf(w, h, depth, use_float ? IB_rectfloat : IB_rect, 0);
if (ibuf==NULL) {
if(dinfo)
opj_destroy_decompress(dinfo);
return NULL;
}
ibuf->ftype = JP2;
if (use_float) {
float *rect_float= ibuf->rect_float;
if (image->numcomps < 3) {
/* greyscale 12bits+ */
for (i = 0; i < w * h; i++, rect_float+=4) {
index = w * h - ((i) / (w) + 1) * w + (i) % (w);
rect_float[0]= rect_float[1]= rect_float[2]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0];
if (image->numcomps == 2)
rect_float[3]= (image->comps[1].data[index] + signed_offsets[1]) / float_divs[1];
else
rect_float[3]= 1.0f;
}
} else {
/* rgb or rgba 12bits+ */
for (i = 0; i < w * h; i++, rect_float+=4) {
index = w * h - ((i) / (w) + 1) * w + (i) % (w);
rect_float[0]= (float)(image->comps[0].data[index] + signed_offsets[0]) / float_divs[0];
rect_float[1]= (float)(image->comps[1].data[index] + signed_offsets[1]) / float_divs[1];
rect_float[2]= (float)(image->comps[2].data[index] + signed_offsets[2]) / float_divs[2];
if (image->numcomps >= 4)
rect_float[3]= (float)(image->comps[3].data[index] + signed_offsets[3]) / float_divs[3];
else
rect_float[3]= 1.0f;
}
}
} else {
unsigned char *rect= (unsigned char *)ibuf->rect;
if (image->numcomps < 3) {
/* greyscale */
for (i = 0; i < w * h; i++, rect+=4) {
index = w * h - ((i) / (w) + 1) * w + (i) % (w);
rect[0]= rect[1]= rect[2]= (image->comps[0].data[index] + signed_offsets[0]);
if (image->numcomps == 2)
rect[3]= image->comps[1].data[index] + signed_offsets[1];
else
rect[3]= 255;
}
} else {
/* 8bit rgb or rgba */
for (i = 0; i < w * h; i++, rect+=4) {
int index = w * h - ((i) / (w) + 1) * w + (i) % (w);
rect[0]= image->comps[0].data[index] + signed_offsets[0];
rect[1]= image->comps[1].data[index] + signed_offsets[1];
rect[2]= image->comps[2].data[index] + signed_offsets[2];
if (image->numcomps >= 4)
rect[3]= image->comps[3].data[index] + signed_offsets[3];
else
rect[3]= 255;
}
}
}
/* free remaining structures */
if(dinfo) {
opj_destroy_decompress(dinfo);
}
/* free image data structure */
opj_image_destroy(image);
if (flags & IB_rect) {
IMB_rect_from_float(ibuf);
}
return(ibuf);
}
//static opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) {
/* prec can be 8, 12, 16 */
#define UPSAMPLE_8_TO_12(_val) ((_val<<4) | (_val & ((1<<4)-1)))
#define UPSAMPLE_8_TO_16(_val) ((_val<<8)+_val)
#define DOWNSAMPLE_FLOAT_TO_8BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?255: (int)(255.0f*(_val)))
#define DOWNSAMPLE_FLOAT_TO_12BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?4095: (int)(4095.0f*(_val)))
#define DOWNSAMPLE_FLOAT_TO_16BIT(_val) (_val)<=0.0f?0: ((_val)>=1.0f?65535: (int)(65535.0f*(_val)))
/*
2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3×12 bits per pixel, XYZ color space
* In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the imager is used
* In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the imager is used
*/
/* ****************************** COPIED FROM image_to_j2k.c */
/* ----------------------------------------------------------------------- */
#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/
#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/
#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/
static int initialise_4K_poc(opj_poc_t *POC, int numres){
POC[0].tile = 1;
POC[0].resno0 = 0;
POC[0].compno0 = 0;
POC[0].layno1 = 1;
POC[0].resno1 = numres-1;
POC[0].compno1 = 3;
POC[0].prg1 = CPRL;
POC[1].tile = 1;
POC[1].resno0 = numres-1;
POC[1].compno0 = 0;
POC[1].layno1 = 1;
POC[1].resno1 = numres;
POC[1].compno1 = 3;
POC[1].prg1 = CPRL;
return 2;
}
void cinema_parameters(opj_cparameters_t *parameters){
parameters->tile_size_on = false;
parameters->cp_tdx=1;
parameters->cp_tdy=1;
/*Tile part*/
parameters->tp_flag = 'C';
parameters->tp_on = 1;
/*Tile and Image shall be at (0,0)*/
parameters->cp_tx0 = 0;
parameters->cp_ty0 = 0;
parameters->image_offset_x0 = 0;
parameters->image_offset_y0 = 0;
/*Codeblock size= 32*32*/
parameters->cblockw_init = 32;
parameters->cblockh_init = 32;
parameters->csty |= 0x01;
/*The progression order shall be CPRL*/
parameters->prog_order = CPRL;
/* No ROI */
parameters->roi_compno = -1;
parameters->subsampling_dx = 1; parameters->subsampling_dy = 1;
/* 9-7 transform */
parameters->irreversible = 1;
}
void cinema_setup_encoder(opj_cparameters_t *parameters,opj_image_t *image, img_fol_t *img_fol){
int i;
float temp_rate;
switch (parameters->cp_cinema){
case CINEMA2K_24:
case CINEMA2K_48:
if(parameters->numresolution > 6){
parameters->numresolution = 6;
}
if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))){
fprintf(stdout,"Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 "
"(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n",
image->comps[0].w,image->comps[0].h);
parameters->cp_rsiz = STD_RSIZ;
}
break;
case CINEMA4K_24:
if(parameters->numresolution < 1){
parameters->numresolution = 1;
}else if(parameters->numresolution > 7){
parameters->numresolution = 7;
}
if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))){
fprintf(stdout,"Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4"
"(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n",
image->comps[0].w,image->comps[0].h);
parameters->cp_rsiz = STD_RSIZ;
}
parameters->numpocs = initialise_4K_poc(parameters->POC,parameters->numresolution);
break;
case OFF:
/* do nothing */
break;
}
switch (parameters->cp_cinema){
case CINEMA2K_24:
case CINEMA4K_24:
for(i=0 ; i<parameters->tcp_numlayers ; i++){
temp_rate = 0 ;
if (img_fol->rates[i]== 0){
parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
(CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
}else{
temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
(img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
if (temp_rate > CINEMA_24_CS ){
parameters->tcp_rates[i]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
(CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
}else{
parameters->tcp_rates[i]= img_fol->rates[i];
}
}
}
parameters->max_comp_size = COMP_24_CS;
break;
case CINEMA2K_48:
for(i=0 ; i<parameters->tcp_numlayers ; i++){
temp_rate = 0 ;
if (img_fol->rates[i]== 0){
parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
(CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
}else{
temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
(img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
if (temp_rate > CINEMA_48_CS ){
parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
(CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
}else{
parameters->tcp_rates[i]= img_fol->rates[i];
}
}
}
parameters->max_comp_size = COMP_48_CS;
break;
case OFF:
/* do nothing */
break;
}
parameters->cp_disto_alloc = 1;
}
static opj_image_t* ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) {
unsigned char *rect;
float *rect_float;
int subsampling_dx = parameters->subsampling_dx;
int subsampling_dy = parameters->subsampling_dy;
int i, numcomps, w, h, prec;
int x,y, y_row;
OPJ_COLOR_SPACE color_space;
opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */
opj_image_t * image = NULL;
img_fol_t img_fol; /* only needed for cinema presets */
memset(&img_fol,0,sizeof(img_fol_t));
if (ibuf->ftype & JP2_CINE) {
if (ibuf->x==4096 || ibuf->y==2160)
parameters->cp_cinema= CINEMA4K_24;
else {
if (ibuf->ftype & JP2_CINE_48FPS) {
parameters->cp_cinema= CINEMA2K_48;
}
else {
parameters->cp_cinema= CINEMA2K_24;
}
}
if (parameters->cp_cinema){
img_fol.rates = (float*)MEM_mallocN(parameters->tcp_numlayers * sizeof(float), "jp2_rates");
for(i=0; i< parameters->tcp_numlayers; i++){
img_fol.rates[i] = parameters->tcp_rates[i];
}
cinema_parameters(parameters);
}
color_space= CLRSPC_SYCC;
prec= 12;
numcomps= 3;
}
else {
/* Get settings from the imbuf */
color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB;
if (ibuf->ftype & JP2_16BIT) prec= 16;
else if (ibuf->ftype & JP2_12BIT) prec= 12;
else prec= 8;
/* 32bit images == alpha channel */
/* grayscale not supported yet */
numcomps= (ibuf->depth==32) ? 4 : 3;
}
w= ibuf->x;
h= ibuf->y;
/* initialize image components */
memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
for(i = 0; i < numcomps; i++) {
cmptparm[i].prec = prec;
cmptparm[i].bpp = prec;
cmptparm[i].sgnd = 0;
cmptparm[i].dx = subsampling_dx;
cmptparm[i].dy = subsampling_dy;
cmptparm[i].w = w;
cmptparm[i].h = h;
}
/* create the image */
image = opj_image_create(numcomps, &cmptparm[0], color_space);
if(!image) {
printf("Error: opj_image_create() failed\n");
return NULL;
}
/* set image offset and reference grid */
image->x0 = parameters->image_offset_x0;
image->y0 = parameters->image_offset_y0;
image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1;
image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1;
/* set image data */
rect = (unsigned char*) ibuf->rect;
rect_float= ibuf->rect_float;
if (rect_float && rect && prec==8) {
/* No need to use the floating point buffer, just write the 8 bits from the char buffer */
rect_float= NULL;
}
if (rect_float) {
float rgb[3];
switch (prec) {
case 8: /* Convert blenders float color channels to 8,12 or 16bit ints */
for(y=h-1; y>=0; y--) {
y_row = y*w;
for(x=0; x<w; x++, rect_float+=4) {
i = y_row + x;
if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
linearrgb_to_srgb_v3_v3(rgb, rect_float);
else
copy_v3_v3(rgb, rect_float);
image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rgb[0]);
image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rgb[1]);
image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rgb[2]);
if (numcomps>3)
image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]);
}
}
break;
case 12:
for(y=h-1; y>=0; y--) {
y_row = y*w;
for(x=0; x<w; x++, rect_float+=4) {
i = y_row + x;
if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
linearrgb_to_srgb_v3_v3(rgb, rect_float);
else
copy_v3_v3(rgb, rect_float);
image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rgb[0]);
image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rgb[1]);
image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rgb[2]);
if (numcomps>3)
image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]);
}
}
break;
case 16:
for(y=h-1; y>=0; y--) {
y_row = y*w;
for(x=0; x<w; x++, rect_float+=4) {
i = y_row + x;
if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
linearrgb_to_srgb_v3_v3(rgb, rect_float);
else
copy_v3_v3(rgb, rect_float);
image->comps[0].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rgb[0]);
image->comps[1].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rgb[1]);
image->comps[2].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rgb[2]);
if (numcomps>3)
image->comps[3].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]);
}
}
break;
}
} else {
/* just use rect*/
switch (prec) {
case 8:
for(y=h-1; y>=0; y--) {
y_row = y*w;
for(x=0; x<w; x++, rect+=4) {
i = y_row + x;
image->comps[0].data[i] = rect[0];
image->comps[1].data[i] = rect[1];
image->comps[2].data[i] = rect[2];
if (numcomps>3)
image->comps[3].data[i] = rect[3];
}
}
break;
case 12: /* Up Sampling, a bit pointless but best write the bit depth requested */
for(y=h-1; y>=0; y--) {
y_row = y*w;
for(x=0; x<w; x++, rect+=4) {
i = y_row + x;
image->comps[0].data[i]= UPSAMPLE_8_TO_12(rect[0]);
image->comps[1].data[i]= UPSAMPLE_8_TO_12(rect[1]);
image->comps[2].data[i]= UPSAMPLE_8_TO_12(rect[2]);
if (numcomps>3)
image->comps[3].data[i]= UPSAMPLE_8_TO_12(rect[3]);
}
}
break;
case 16:
for(y=h-1; y>=0; y--) {
y_row = y*w;
for(x=0; x<w; x++, rect+=4) {
i = y_row + x;
image->comps[0].data[i]= UPSAMPLE_8_TO_16(rect[0]);
image->comps[1].data[i]= UPSAMPLE_8_TO_16(rect[1]);
image->comps[2].data[i]= UPSAMPLE_8_TO_16(rect[2]);
if (numcomps>3)
image->comps[3].data[i]= UPSAMPLE_8_TO_16(rect[3]);
}
}
break;
}
}
/* Decide if MCT should be used */
parameters->tcp_mct = image->numcomps == 3 ? 1 : 0;
if(parameters->cp_cinema){
cinema_setup_encoder(parameters,image,&img_fol);
}
if (img_fol.rates)
MEM_freeN(img_fol.rates);
return image;
}
/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */
int imb_savejp2(struct ImBuf *ibuf, char *name, int flags) {
int quality = ibuf->ftype & 0xff;
int bSuccess;
opj_cparameters_t parameters; /* compression parameters */
opj_event_mgr_t event_mgr; /* event manager */
opj_image_t *image = NULL;
/*
configure the event callbacks (not required)
setting of each callback is optionnal
*/
memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
event_mgr.error_handler = error_callback;
event_mgr.warning_handler = warning_callback;
event_mgr.info_handler = info_callback;
/* set encoding parameters to default values */
opj_set_default_encoder_parameters(&parameters);
/* compression ratio */
/* invert range, from 10-100, 100-1
* where jpeg see's 1 and highest quality (lossless) and 100 is very low quality*/
parameters.tcp_rates[0]= ((100-quality)/90.0f*99.0f) + 1;
parameters.tcp_numlayers = 1; // only one resolution
parameters.cp_disto_alloc = 1;
image= ibuftoimage(ibuf, &parameters);
{ /* JP2 format output */
int codestream_length;
opj_cio_t *cio = NULL;
FILE *f = NULL;
/* get a JP2 compressor handle */
opj_cinfo_t* cinfo = opj_create_compress(CODEC_JP2);
/* catch events using our callbacks and give a local context */
opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
/* setup the encoder parameters using the current image and using user parameters */
opj_setup_encoder(cinfo, &parameters, image);
/* open a byte stream for writing */
/* allocate memory for all tiles */
cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
/* encode the image */
bSuccess = opj_encode(cinfo, cio, image, NULL); /* last arg used to be parameters.index but this deprecated */
if (!bSuccess) {
opj_cio_close(cio);
fprintf(stderr, "failed to encode image\n");
return 0;
}
codestream_length = cio_tell(cio);
/* write the buffer to disk */
f = fopen(name, "wb");
if (!f) {
fprintf(stderr, "failed to open %s for writing\n", name);
return 1;
}
fwrite(cio->buffer, 1, codestream_length, f);
fclose(f);
fprintf(stderr,"Generated outfile %s\n",name);
/* close and free the byte stream */
opj_cio_close(cio);
/* free remaining compression structures */
opj_destroy_compress(cinfo);
}
/* free image data */
opj_image_destroy(image);
return 1;
}
#endif /* WITH_OPENJPEG */