int write_image (dt_imageio_j2k_t *j2k, const char *filename, const float *in, void *exif, int exif_len, int imgid) { opj_cparameters_t parameters; /* compression parameters */ float *rates = NULL; opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; int quality = CLAMP(j2k->quality, 1, 100); /* 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(¶meters); /* 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 + 1; parameters.tcp_numlayers = 1; /* only one resolution */ parameters.cp_disto_alloc = 1; parameters.cp_rsiz = STD_RSIZ; parameters.cod_format = j2k->format; parameters.cp_cinema = j2k->preset; if(parameters.cp_cinema) { rates = (float*)malloc(parameters.tcp_numlayers * sizeof(float)); for(int i=0; i< parameters.tcp_numlayers; i++) { rates[i] = parameters.tcp_rates[i]; } cinema_parameters(¶meters); } /* Create comment for codestream */ const char comment[] = "Created by "PACKAGE_STRING; parameters.cp_comment = g_strdup(comment); /*Converting the image to a format suitable for encoding*/ { int subsampling_dx = parameters.subsampling_dx; int subsampling_dy = parameters.subsampling_dy; int numcomps = 3; int prec = 12; //TODO: allow other bitdepths! int w = j2k->width, h = j2k->height; opj_image_cmptparm_t cmptparm[4]; /* RGBA: max. 4 components */ memset(&cmptparm[0], 0, numcomps * sizeof(opj_image_cmptparm_t)); for(int 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; } image = opj_image_create(numcomps, &cmptparm[0], CLRSPC_SRGB); if(!image) { fprintf(stderr, "Error: opj_image_create() failed\n"); return 1; } /* 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; switch(prec) { case 8: for(int i = 0; i < w * h; i++) { for(int k = 0; k < numcomps; k++) image->comps[k].data[i] = DOWNSAMPLE_FLOAT_TO_8BIT(in[i*4 + k]); } break; case 12: for(int i = 0; i < w * h; i++) { for(int k = 0; k < numcomps; k++) image->comps[k].data[i] = DOWNSAMPLE_FLOAT_TO_12BIT(in[i*4 + k]); } break; case 16: for(int i = 0; i < w * h; i++) { for(int k = 0; k < numcomps; k++) image->comps[k].data[i] = DOWNSAMPLE_FLOAT_TO_16BIT(in[i*4 + k]); } break; default: fprintf(stderr, "Error: this shouldn't happen, there is no bit depth of %d for jpeg 2000 images.\n", prec); return 1; } } /*Encoding image*/ /* Decide if MCT should be used */ parameters.tcp_mct = image->numcomps == 3 ? 1 : 0; if(parameters.cp_cinema) { cinema_setup_encoder(¶meters,image,rates); } /* encode the destination image */ /* ---------------------------- */ int rc = 1; OPJ_CODEC_FORMAT codec; if(parameters.cod_format == J2K_CFMT) /* J2K format output */ codec = CODEC_J2K; else codec = CODEC_JP2; int codestream_length; size_t res; opj_cio_t *cio = NULL; FILE *f = NULL; /* get a J2K/JP2 compressor handle */ opj_cinfo_t* cinfo = opj_create_compress(codec); /* 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 user parameters */ opj_setup_encoder(cinfo, ¶meters, 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 */ if(!opj_encode(cinfo, cio, image, NULL)) { opj_cio_close(cio); fprintf(stderr, "failed to encode image\n"); return 1; } codestream_length = cio_tell(cio); /* write the buffer to disk */ f = fopen(filename, "wb"); if(!f) { fprintf(stderr, "failed to open %s for writing\n", filename); return 1; } res = fwrite(cio->buffer, 1, codestream_length, f); if(res < (size_t)codestream_length) /* FIXME */ { fprintf(stderr, "failed to write %d (%s)\n", codestream_length, filename); fclose(f); return 1; } fclose(f); /* close and free the byte stream */ opj_cio_close(cio); /* free remaining compression structures */ opj_destroy_compress(cinfo); /* add exif data blob. seems to not work for j2k files :( */ if(exif && j2k->format == JP2_CFMT) rc = dt_exif_write_blob(exif,exif_len,filename); /* free image data */ opj_image_destroy(image); /* free user parameters structure */ g_free(parameters.cp_comment); if(parameters.cp_matrice) free(parameters.cp_matrice); return ((rc == 1) ? 0 : 1); }
static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { LibOpenJPEGContext *ctx = avctx->priv_data; opj_cinfo_t *compress = ctx->compress; opj_image_t *image = ctx->image; opj_cio_t *stream = ctx->stream; int cpyresult = 0; int ret, len; AVFrame *gbrframe; switch (avctx->pix_fmt) { case AV_PIX_FMT_RGB24: case AV_PIX_FMT_RGBA: case AV_PIX_FMT_YA8: cpyresult = libopenjpeg_copy_packed8(avctx, frame, image); break; case AV_PIX_FMT_XYZ12: cpyresult = libopenjpeg_copy_packed12(avctx, frame, image); break; case AV_PIX_FMT_RGB48: case AV_PIX_FMT_RGBA64: case AV_PIX_FMT_YA16: cpyresult = libopenjpeg_copy_packed16(avctx, frame, image); break; case AV_PIX_FMT_GBR24P: case AV_PIX_FMT_GBRP9: case AV_PIX_FMT_GBRP10: case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP14: case AV_PIX_FMT_GBRP16: gbrframe = av_frame_clone(frame); if (!gbrframe) return AVERROR(ENOMEM); gbrframe->data[0] = frame->data[2]; // swap to be rgb gbrframe->data[1] = frame->data[0]; gbrframe->data[2] = frame->data[1]; gbrframe->linesize[0] = frame->linesize[2]; gbrframe->linesize[1] = frame->linesize[0]; gbrframe->linesize[2] = frame->linesize[1]; if (avctx->pix_fmt == AV_PIX_FMT_GBR24P) { cpyresult = libopenjpeg_copy_unpacked8(avctx, gbrframe, image); } else { cpyresult = libopenjpeg_copy_unpacked16(avctx, gbrframe, image); } av_frame_free(&gbrframe); break; case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_YUV410P: case AV_PIX_FMT_YUV411P: case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV440P: case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUVA420P: case AV_PIX_FMT_YUVA422P: case AV_PIX_FMT_YUVA444P: cpyresult = libopenjpeg_copy_unpacked8(avctx, frame, image); break; case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YUV420P9: case AV_PIX_FMT_YUV422P9: case AV_PIX_FMT_YUV444P9: case AV_PIX_FMT_YUVA420P9: case AV_PIX_FMT_YUVA422P9: case AV_PIX_FMT_YUVA444P9: case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUVA444P10: case AV_PIX_FMT_YUVA422P10: case AV_PIX_FMT_YUVA420P10: case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV422P12: case AV_PIX_FMT_YUV444P12: case AV_PIX_FMT_YUV420P14: case AV_PIX_FMT_YUV422P14: case AV_PIX_FMT_YUV444P14: case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUV422P16: case AV_PIX_FMT_YUV420P16: case AV_PIX_FMT_YUVA444P16: case AV_PIX_FMT_YUVA422P16: case AV_PIX_FMT_YUVA420P16: cpyresult = libopenjpeg_copy_unpacked16(avctx, frame, image); break; default: av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR(EINVAL); break; } if (!cpyresult) { av_log(avctx, AV_LOG_ERROR, "Could not copy the frame data to the internal image buffer\n"); return -1; } opj_setup_encoder(compress, &ctx->enc_params, image); stream = opj_cio_open((opj_common_ptr) compress, NULL, 0); if (!stream) { av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); return AVERROR(ENOMEM); } if (!opj_encode(compress, stream, image, NULL)) { av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); return -1; } len = cio_tell(stream); if ((ret = ff_alloc_packet2(avctx, pkt, len)) < 0) { return ret; } memcpy(pkt->data, stream->buffer, len); pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; }
OFCondition DJCompressJP2K::encode( Uint16 columns, Uint16 rows, EP_Interpretation colorSpace, Uint16 samplesPerPixel, Uint16 * image_buffer, Uint16 * & to, Uint32 & length, Uint8 bitsAllocated, Uint8 pixelRepresentation, double minUsed, double maxUsed) { int bitsstored = bitsAllocated; if( samplesPerPixel > 1) bitsstored = bitsAllocated = 8; OFBool isSigned = pixelRepresentation; if( bitsAllocated >= 16) { int amplitude = maxUsed; if( minUsed < 0) amplitude -= minUsed; int bits = 1, value = 2; while( value < amplitude && bits <= 16) { value *= 2; bits++; } if( minUsed < 0) // K A10009536850 22.06.12 bits++; if( bits < 9) bits = 9; // avoid the artifacts... switch to lossless if( (maxUsed >= 32000 && minUsed <= -32000) || maxUsed >= 65000 || bits > 16) quality = 0; if( bits > 16) bits = 16; bitsstored = bits; } opj_cparameters_t parameters; opj_image_t *image = NULL; // printf( "JP2K OPJ-DCMTK-Encode "); opj_set_default_encoder_parameters(¶meters); parameters.tcp_numlayers = 1; parameters.cp_disto_alloc = 1; switch( quality) { case 0: // DCMLosslessQuality parameters.tcp_rates[0] = 0; break; case 1: // DCMHighQuality parameters.tcp_rates[0] = 4; break; case 2: // DCMMediumQuality if( columns <= 600 || rows <= 600) parameters.tcp_rates[0] = 6; else parameters.tcp_rates[0] = 8; break; case 3: // DCMLowQuality parameters.tcp_rates[0] = 16; break; default: //printf( "****** warning unknown compression rate -> MediumQuality : %d", quality); if( columns <= 600 || rows <= 600) parameters.tcp_rates[0] = 6; else parameters.tcp_rates[0] = 8; break; } int image_width = columns; int image_height = rows; int sample_pixel = samplesPerPixel; if (colorSpace == EPI_Monochrome1 || colorSpace == EPI_Monochrome2) { } else { if( sample_pixel != 3) printf( "*** RGB Photometric?, but... SamplesPerPixel != 3 ?"); sample_pixel = 3; } image = rawtoimage( (char *)image_buffer, ¶meters, static_cast<int>( columns*rows*samplesPerPixel*bitsAllocated/8), image_width, image_height, sample_pixel, bitsAllocated, bitsstored, isSigned, quality, 0); if(!image) { fprintf(stderr, "Unable to load buffer image\n"); return EC_Normal; } parameters.cod_format = 0; /* J2K format output */ int codestream_length; opj_codec_t *l_codec = 00; l_codec = opj_create_compress(OPJ_CODEC_J2K); opj_set_info_handler(l_codec, info_callback,00); opj_set_warning_handler(l_codec, warning_callback,00); opj_set_error_handler(l_codec, error_callback,00); /* setup the encoder parameters using the current image and using user parameters */ opj_setup_encoder(l_codec, ¶meters, image); char * l_out; size_t l_size; FILE * l_file = open_memstream(&l_out, &l_size); opj_stream_t * l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, OPJ_FALSE); if (! l_stream){ fprintf(stderr, "failed to create stream\n"); return EC_Normal; } opj_stream_set_user_data(l_stream, l_file, (opj_stream_free_user_data_fn)NULL); opj_stream_set_write_function(l_stream, (opj_stream_write_fn)_write); /* encode the image */ int bSuccess = opj_start_compress(l_codec, image, l_stream); if (!bSuccess) { fprintf(stderr, "failed to encode image\n"); return EC_Normal; } bSuccess = bSuccess && opj_encode(l_codec, l_stream); if (!bSuccess) { opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); fprintf(stderr, "failed to encode image 2\n"); remove(parameters.outfile); return EC_Normal; } bSuccess = bSuccess && opj_end_compress(l_codec, l_stream); if (!bSuccess) { fprintf(stderr, "failed to encode image: opj_end_compress\n"); return EC_Normal; } /* l_file memstream must be flushed to allow accessint to l_out and l_size values */ fflush(l_file); #ifdef _WIN32 get_buffer_and_size(l_file); #endif fclose(l_file); /* copy compressed stream to "to" UINT8* */ to = new Uint16[l_size]; memcpy( to, l_out, l_size); length = l_size; /* free remaining compression structures */ free(l_out); opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); // } return EC_Normal; }
static GstFlowReturn gst_openjpeg_enc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame) { GstOpenJPEGEnc *self = GST_OPENJPEG_ENC (encoder); GstFlowReturn ret = GST_FLOW_OK; #ifdef HAVE_OPENJPEG_1 opj_cinfo_t *enc; GstMapInfo map; guint length; opj_cio_t *io; #else opj_codec_t *enc; opj_stream_t *stream; MemStream mstream; #endif opj_image_t *image; GstVideoFrame vframe; GST_DEBUG_OBJECT (self, "Handling frame"); enc = opj_create_compress (self->codec_format); if (!enc) goto initialization_error; #ifdef HAVE_OPENJPEG_1 if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { opj_event_mgr_t callbacks; callbacks.error_handler = gst_openjpeg_enc_opj_error; callbacks.warning_handler = gst_openjpeg_enc_opj_warning; callbacks.info_handler = gst_openjpeg_enc_opj_info; opj_set_event_mgr ((opj_common_ptr) enc, &callbacks, self); } else { opj_set_event_mgr ((opj_common_ptr) enc, NULL, NULL); } #else if (G_UNLIKELY (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)) { opj_set_info_handler (enc, gst_openjpeg_enc_opj_info, self); opj_set_warning_handler (enc, gst_openjpeg_enc_opj_warning, self); opj_set_error_handler (enc, gst_openjpeg_enc_opj_error, self); } else { opj_set_info_handler (enc, NULL, NULL); opj_set_warning_handler (enc, NULL, NULL); opj_set_error_handler (enc, NULL, NULL); } #endif if (!gst_video_frame_map (&vframe, &self->input_state->info, frame->input_buffer, GST_MAP_READ)) goto map_read_error; image = gst_openjpeg_enc_fill_image (self, &vframe); if (!image) goto fill_image_error; gst_video_frame_unmap (&vframe); opj_setup_encoder (enc, &self->params, image); #ifdef HAVE_OPENJPEG_1 io = opj_cio_open ((opj_common_ptr) enc, NULL, 0); if (!io) goto open_error; if (!opj_encode (enc, io, image, NULL)) goto encode_error; opj_image_destroy (image); length = cio_tell (io); ret = gst_video_encoder_allocate_output_frame (encoder, frame, length + (self->is_jp2c ? 8 : 0)); if (ret != GST_FLOW_OK) goto allocate_error; gst_buffer_fill (frame->output_buffer, self->is_jp2c ? 8 : 0, io->buffer, length); if (self->is_jp2c) { gst_buffer_map (frame->output_buffer, &map, GST_MAP_WRITE); GST_WRITE_UINT32_BE (map.data, length + 8); GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); gst_buffer_unmap (frame->output_buffer, &map); } opj_cio_close (io); opj_destroy_compress (enc); #else stream = opj_stream_create (4096, OPJ_FALSE); if (!stream) goto open_error; mstream.allocsize = 4096; mstream.data = g_malloc (mstream.allocsize); mstream.offset = 0; mstream.size = 0; opj_stream_set_read_function (stream, read_fn); opj_stream_set_write_function (stream, write_fn); opj_stream_set_skip_function (stream, skip_fn); opj_stream_set_seek_function (stream, seek_fn); opj_stream_set_user_data (stream, &mstream); opj_stream_set_user_data_length (stream, mstream.size); if (!opj_start_compress (enc, image, stream)) goto encode_error; if (!opj_encode (enc, stream)) goto encode_error; if (!opj_end_compress (enc, stream)) goto encode_error; opj_image_destroy (image); opj_stream_destroy (stream); opj_destroy_codec (enc); frame->output_buffer = gst_buffer_new (); if (self->is_jp2c) { GstMapInfo map; GstMemory *mem; mem = gst_allocator_alloc (NULL, 8, NULL); gst_memory_map (mem, &map, GST_MAP_WRITE); GST_WRITE_UINT32_BE (map.data, mstream.size + 8); GST_WRITE_UINT32_BE (map.data + 4, GST_MAKE_FOURCC ('j', 'p', '2', 'c')); gst_memory_unmap (mem, &map); gst_buffer_append_memory (frame->output_buffer, mem); } gst_buffer_append_memory (frame->output_buffer, gst_memory_new_wrapped (0, mstream.data, mstream.allocsize, 0, mstream.size, NULL, (GDestroyNotify) g_free)); #endif ret = gst_video_encoder_finish_frame (encoder, frame); return ret; initialization_error: { gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to initialize OpenJPEG encoder"), (NULL)); return GST_FLOW_ERROR; } map_read_error: { #ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); #else opj_destroy_codec (enc); #endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to map input buffer"), (NULL)); return GST_FLOW_ERROR; } fill_image_error: { #ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); #else opj_destroy_codec (enc); #endif gst_video_frame_unmap (&vframe); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to fill OpenJPEG image"), (NULL)); return GST_FLOW_ERROR; } open_error: { opj_image_destroy (image); #ifdef HAVE_OPENJPEG_1 opj_destroy_compress (enc); #else opj_destroy_codec (enc); #endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to open OpenJPEG data"), (NULL)); return GST_FLOW_ERROR; } encode_error: { #ifdef HAVE_OPENJPEG_1 opj_cio_close (io); opj_image_destroy (image); opj_destroy_compress (enc); #else opj_stream_destroy (stream); g_free (mstream.data); opj_image_destroy (image); opj_destroy_codec (enc); #endif gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, STREAM, ENCODE, ("Failed to encode OpenJPEG stream"), (NULL)); return GST_FLOW_ERROR; } #ifdef HAVE_OPENJPEG_1 allocate_error: { opj_cio_close (io); opj_destroy_compress (enc); gst_video_codec_frame_unref (frame); GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to allocate output buffer"), (NULL)); return ret; } #endif }
char* J2kConverter::encode(int16_t* data, unsigned int imageWidth, unsigned int imageHeight, size_t& outSize, float distoRatio) { opj_cparameters_t params; opj_image_cmptparm_t compParams; opj_set_default_encoder_parameters(¶ms); params.tcp_numlayers = 1; params.cp_fixed_quality = 1; params.tcp_distoratio[0] = distoRatio; params.cp_tx0 = 0; params.cp_ty0 = 0; params.tile_size_on = OPJ_FALSE; params.irreversible = true; params.numresolution = 1; params.prog_order = OPJ_LRCP; compParams.w = imageWidth; compParams.h = imageHeight; compParams.sgnd = 0; compParams.prec = 16; compParams.bpp = 16; compParams.x0 = 0; compParams.y0 = 0; compParams.dx = 1; compParams.dy = 1; opj_codec_t *codec = opj_create_compress(OPJ_CODEC_J2K); opj_set_info_handler(codec, infoCallback, nullptr); opj_set_warning_handler(codec, warningCallback, nullptr); opj_set_error_handler(codec, errorCallback, nullptr); opj_image_t *image = opj_image_create(1, &compParams, OPJ_CLRSPC_GRAY); if (!image) { opj_destroy_codec(codec); return nullptr; } unsigned int nPixels = imageWidth * imageHeight; for (unsigned int i = 0; i < nPixels; ++i) { image->comps[0].data[i] = data[i]; } image->x0 = 0; image->y0 = 0; image->x1 = static_cast<OPJ_UINT32>(imageWidth); image->y1 = static_cast<OPJ_UINT32>(imageHeight); image->color_space = OPJ_CLRSPC_GRAY; if (!opj_setup_encoder(codec, ¶ms, image)) { std::cout << "Could not set up encoder." << std::endl; opj_destroy_codec(codec); opj_image_destroy(image); return nullptr; } MemoryStream* ms = new MemoryStream; opj_stream_t *stream = createOpjMemoryStream(OPJ_FALSE, ms); if (!stream) { std::cout << "Could not set up stream" << std::endl; opj_destroy_codec(codec); opj_image_destroy(image); return nullptr; } if (!opj_start_compress(codec, image, stream)) { std::cout << "Could not start compression." << std::endl; opj_stream_destroy(stream); opj_destroy_codec(codec); opj_image_destroy(image); return nullptr; } if (!opj_encode(codec, stream)) { std::cout << "Could not encode data." << std::endl; opj_stream_destroy(stream); opj_destroy_codec(codec); opj_image_destroy(image); return nullptr; } if (!opj_end_compress(codec, stream)) { std::cout << "Could not end compression." << std::endl; opj_stream_destroy(stream); opj_destroy_codec(codec); opj_image_destroy(image); return nullptr; } outSize = ms->data.size(); char* outData = new char[outSize]; memcpy(outData, ms->data.data(), outSize); opj_stream_destroy(stream); opj_destroy_codec(codec); opj_image_destroy(image); delete ms; return outData; }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { J2KFIO_t *fio = (J2KFIO_t*)data; if (dib && handle && fio) { BOOL bSuccess; opj_codec_t *c_codec = NULL; // handle to a compressor opj_cparameters_t parameters; // compression parameters opj_image_t *image = NULL; // image to encode // get the OpenJPEG stream opj_stream_t *c_stream = fio->stream; // set encoding parameters to default values opj_set_default_encoder_parameters(¶meters); try { parameters.tcp_numlayers = 0; // if no rate entered, apply a 16:1 rate by default if(flags == J2K_DEFAULT) { parameters.tcp_rates[0] = (float)16; } else { // for now, the flags parameter is only used to specify the rate parameters.tcp_rates[0] = (float)(flags & 0x3FF); } parameters.tcp_numlayers++; parameters.cp_disto_alloc = 1; // convert the dib to a OpenJPEG image image = FIBITMAPToJ2KImage(s_format_id, dib, ¶meters); if(!image) { return FALSE; } // decide if MCT should be used parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; // encode the destination image // get a J2K compressor handle c_codec = opj_create_compress(OPJ_CODEC_J2K); // configure the event callbacks // catch events using our callbacks (no local context needed here) opj_set_info_handler(c_codec, NULL, NULL); opj_set_warning_handler(c_codec, j2k_warning_callback, NULL); opj_set_error_handler(c_codec, j2k_error_callback, NULL); // setup the encoder parameters using the current image and using user parameters opj_setup_encoder(c_codec, ¶meters, image); // encode the image bSuccess = opj_start_compress(c_codec, image, c_stream); if(bSuccess) { bSuccess = bSuccess && opj_encode(c_codec, c_stream); if(bSuccess) { bSuccess = bSuccess && opj_end_compress(c_codec, c_stream); } } if (!bSuccess) { throw "Failed to encode image"; } // free remaining compression structures opj_destroy_codec(c_codec); // free image data opj_image_destroy(image); return TRUE; } catch (const char *text) { if(c_codec) opj_destroy_codec(c_codec); if(image) opj_image_destroy(image); FreeImage_OutputMessageProc(s_format_id, text); return FALSE; } } return FALSE; }
/* Add a frame to the end of an IPX file */ int IPX_write_frame(TFrame *frame, IPX_status *status) { opj_image_t *image = NULL; uint codestream_length, datasize; opj_cio_t *cio = NULL; opj_image_cmptparm_t cmptparm; int i, j, p; float factor; static int jp2_init = 1; static opj_event_mgr_t event_mgr; /* event manager */ static opj_cparameters_t parameters; /* compression parameters */ static opj_cinfo_t* cinfo; if((status->header.height == 0) || (status->header.width == 0)) { /* Width and height not set yet */ status->header.height = frame->height; status->header.width = frame->width; } if((status->header.height != frame->height) || (status->header.width != frame->width)) { /* Frame is wrong size */ return(IO_ERROR_SIZE); } if(jp2_init) { jp2_init = 0; /* Setup callbacks */ 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 default compression parameters */ opj_set_default_encoder_parameters(¶meters); /* Get a compressor handle */ 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); } /* Create an image structure */ memset(&cmptparm, 0, sizeof(opj_image_cmptparm_t)); /* Set image parameters */ cmptparm.prec = status->header.depth; cmptparm.bpp = cmptparm.prec; cmptparm.sgnd = 0; cmptparm.dx = parameters.subsampling_dx; cmptparm.dy = parameters.subsampling_dy; cmptparm.w = frame->width; cmptparm.h = frame->height; /* Create image */ image = opj_image_create(1, &cmptparm, CLRSPC_GRAY); if(!image) { printf("Error: Cannot create image\n"); exit(0); } /* set image offset and reference grid */ image->x0 = parameters.image_offset_x0; image->y0 = parameters.image_offset_y0; image->x1 = parameters.image_offset_x0 + (cmptparm.w - 1) * parameters.subsampling_dx + 1; image->y1 = parameters.image_offset_y0 + (cmptparm.h - 1) * parameters.subsampling_dy + 1; factor = (float) ((1 << cmptparm.prec) - 1); p = 0; for(j=0;j<status->header.height;j++) { for(i=0;i<status->header.width;i++) { image->comps[0].data[p] = (int) (factor * frame->data[i][j]); p++; } } image->comps[0].bpp = cmptparm.bpp; /* if no rate entered, lossless by default */ if(parameters.tcp_numlayers == 0) { parameters.tcp_rates[0] = 0; parameters.tcp_numlayers++; parameters.cp_disto_alloc = 1; } /* setup the encoder parameters using the current image and using user parameters */ opj_setup_encoder(cinfo, ¶meters, image); /* open a byte stream for writing */ /* allocate memory for all tiles */ if((cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0)) == NULL) { printf("Error: could not open CIO buffer\n"); exit(0); } /* encode the image */ if(!opj_encode(cinfo, cio, image, NULL)) { opj_cio_close(cio); return(IO_ERROR_OTHER); } /* Length of JP2 code stream */ codestream_length = cio_tell(cio); /* Length of header + JP2 data */ datasize = codestream_length + IPX_UINT + IPX_DOUBLE; //sizeof(uint) + sizeof(double); /* printf("Writing frame %d at position %ld, size %d\n", status->header.numFrames, ftell(status->fd), codestream_length); */ /* Write frame header */ //printf("Writing header: %ld, %d ->", ftell(status->fd), sizeof(uint)+sizeof(double)); fwrite(&datasize, IPX_UINT, 1, status->fd); fwrite(&(frame->time), IPX_DOUBLE, 1, status->fd); //printf(" %ld\n", ftell(status->fd)); /* write the frame data */ fwrite(cio->buffer, 1, codestream_length, status->fd); /* Update header */ status->header.numFrames++; /* Free memory */ opj_cio_close(cio); opj_image_destroy(image); return(0); }
static int libopenjpeg_encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data) { AVFrame *frame = data; LibOpenJPEGContext *ctx = avctx->priv_data; opj_cinfo_t *compress = ctx->compress; opj_image_t *image = ctx->image; opj_cio_t *stream; int cpyresult = 0; int len = 0; // x0, y0 is the top left corner of the image // x1, y1 is the width, height of the reference grid image->x0 = 0; image->y0 = 0; image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1; image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1; switch (avctx->pix_fmt) { case PIX_FMT_GRAY8: cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 1); break; case PIX_FMT_RGB24: cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 3); break; case PIX_FMT_RGBA: cpyresult = libopenjpeg_copy_rgba(avctx, frame, image, 4); break; case PIX_FMT_RGB48: cpyresult = libopenjpeg_copy_rgb16(avctx, frame, image, 3); break; case PIX_FMT_YUV420P: case PIX_FMT_YUV422P: case PIX_FMT_YUV440P: case PIX_FMT_YUV444P: case PIX_FMT_YUVA420P: cpyresult = libopenjpeg_copy_yuv8(avctx, frame, image); break; case PIX_FMT_YUV420P9: case PIX_FMT_YUV420P10: case PIX_FMT_YUV420P16: case PIX_FMT_YUV422P9: case PIX_FMT_YUV422P10: case PIX_FMT_YUV422P16: case PIX_FMT_YUV444P9: case PIX_FMT_YUV444P10: case PIX_FMT_YUV444P16: cpyresult = libopenjpeg_copy_yuv16(avctx, frame, image); break; default: av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR(EINVAL); break; } if (!cpyresult) { av_log(avctx, AV_LOG_ERROR, "Could not copy the frame data to the internal image buffer\n"); return -1; } opj_setup_encoder(compress, &ctx->enc_params, image); stream = opj_cio_open((opj_common_ptr)compress, NULL, 0); if (!stream) { av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); return AVERROR(ENOMEM); } if (!opj_encode(compress, stream, image, NULL)) { opj_cio_close(stream); av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); return -1; } len = cio_tell(stream); if (len > buf_size) { opj_cio_close(stream); av_log(avctx, AV_LOG_ERROR, "Error with buf_size, not large enough to hold the frame\n"); return -1; } memcpy(buf, stream->buffer, len); opj_cio_close(stream); return len; }
unsigned char * OPJSupport::compressJPEG2K(void *data, int samplesPerPixel, int rows, int columns, int bitsstored, //precision, unsigned char bitsAllocated, bool sign, int rate, long *compressedDataSize) { //enconderMutex.lock(); opj_cparameters_t parameters; opj_stream_t *l_stream = 00; opj_codec_t* l_codec = 00; opj_image_t *image = NULL; OPJ_BOOL bSuccess; OPJ_BOOL bUseTiles = OPJ_FALSE; /* OPJ_TRUE */ OPJ_UINT32 l_nb_tiles = 4; OPJ_BOOL fails = OPJ_FALSE; OPJ_CODEC_FORMAT codec_format; memset(¶meters, 0, sizeof(parameters)); opj_set_default_encoder_parameters(¶meters); parameters.outfile[0] = '\0'; parameters.tcp_numlayers = 1; parameters.cp_disto_alloc = 1; parameters.tcp_rates[0] = rate; parameters.cod_format = JP2_CFMT; //JP2_CFMT; //J2K_CFMT; OPJ_BOOL forceJ2K = (parameters.cod_format == J2K_CFMT ? OPJ_FALSE:(((OPJ_TRUE /*force here*/)))); #ifdef WITH_OPJ_FILE_STREAM tmpnam(parameters.outfile); #endif image = rawtoimage( (char*) data, ¶meters, static_cast<int>( columns*rows*samplesPerPixel*bitsAllocated/8), // [data length], fragment_size columns, rows, samplesPerPixel, bitsAllocated, bitsstored, sign, /*quality,*/ 0); if (image == NULL) { /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } /*-----------------------------------------------*/ switch (parameters.cod_format) { case J2K_CFMT: /* JPEG-2000 codestream */ codec_format = OPJ_CODEC_J2K; break; case JP2_CFMT: /* JPEG 2000 compressed image data */ codec_format = OPJ_CODEC_JP2; break; case JPT_CFMT: /* JPEG 2000, JPIP */ codec_format = OPJ_CODEC_JPT; break; case -1: default: fprintf(stderr,"%s:%d: encode format missing\n",__FILE__,__LINE__); /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } /* see test_tile_encoder.c:232 and opj_compress.c:1746 */ l_codec = opj_create_compress(codec_format); if (!l_codec) { fprintf(stderr,"%s:%d:\n\tNO codec\n",__FILE__,__LINE__); /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } #ifdef OPJ_VERBOSE opj_set_info_handler(l_codec, info_callback, this); opj_set_warning_handler(l_codec, warning_callback, this); #endif opj_set_error_handler(l_codec, error_callback, this); if ( !opj_setup_encoder(l_codec, ¶meters, image)) { fprintf(stderr,"%s:%d:\n\topj_setup_encoder failed\n",__FILE__,__LINE__); /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } // Create the stream #ifdef WITH_OPJ_BUFFER_STREAM opj_buffer_info_t bufferInfo; bufferInfo.cur = bufferInfo.buf = (OPJ_BYTE *)data; bufferInfo.len = (OPJ_SIZE_T) rows * columns; l_stream = opj_stream_create_buffer_stream(&bufferInfo, OPJ_STREAM_WRITE); //printf("%p\n",bufferInfo.buf); //printf("%lu\n",bufferInfo.len); #endif #ifdef WITH_OPJ_FILE_STREAM l_stream = opj_stream_create_default_file_stream(parameters.outfile, OPJ_STREAM_WRITE); #endif if (!l_stream) { fprintf(stderr,"%s:%d:\n\tstream creation failed\n",__FILE__,__LINE__); /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } while(1) { // int tile_index=-1, user_changed_tile=0, user_changed_reduction=0; // int max_tiles=0, max_reduction=0; fails = OPJ_TRUE; /* encode the image */ bSuccess = opj_start_compress(l_codec, image, l_stream); if (!bSuccess) { fprintf(stderr,"%s:%d:\n\topj_start_compress failed\n",__FILE__,__LINE__); break; } if ( bSuccess && bUseTiles ) { OPJ_BYTE *l_data = NULL; OPJ_UINT32 l_data_size = 512*512*3; //FIXME l_data = (OPJ_BYTE*) malloc(l_data_size * sizeof(OPJ_BYTE)); memset(l_data, 0, l_data_size * sizeof(OPJ_BYTE)); //assert( l_data ); if (!l_data) { /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } for (int i=0;i<l_nb_tiles;++i) { if (! opj_write_tile(l_codec,i,l_data,l_data_size,l_stream)) { fprintf(stderr, "\nERROR -> test_tile_encoder: failed to write the tile %d!\n",i); /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); free(l_data); *compressedDataSize = 0; //enconderMutex.unlock(); return NULL; } } free(l_data); } else { if (!opj_encode(l_codec, l_stream)) { fprintf(stderr,"%s:%d:\n\topj_encode failed\n",__FILE__,__LINE__); break; } } if (!opj_end_compress(l_codec, l_stream)) { fprintf(stderr,"%s:%d:\n\topj_end_compress failed\n",__FILE__,__LINE__); break; } fails = OPJ_FALSE; break; } // while *compressedDataSize = 0; unsigned char *to = NULL; /* close and free the byte stream */ if (l_stream) opj_stream_destroy(l_stream); /* free remaining compression structures */ if (l_codec) opj_destroy_codec(l_codec); /* free image data */ if (image) opj_image_destroy(image); if (fails) { #ifdef WITH_OPJ_FILE_STREAM if (parameters.outfile[0] != '\0') remove(parameters.outfile); #endif } else { #ifdef WITH_OPJ_BUFFER_STREAM //printf("%p\n",bufferInfo.buf); //printf("%lu\n",bufferInfo.len); //to=(unsigned char *) malloc(bufferInfo.len); //memcpy(to,l_stream,bufferInfo.len); #endif #ifdef WITH_OPJ_FILE_STREAM // Open the temp file and get the encoded data into 'to' // and the length into 'length' FILE *f = NULL; if (parameters.outfile[0] != '\0') { f = fopen(parameters.outfile, "rb"); } long length = 0; if (f != NULL) { fseek(f, 0, SEEK_END); length = ftell(f); fseek(f, 0, SEEK_SET); if (forceJ2K) { length -= 85; fseek(f, 85, SEEK_SET); } if (length % 2) { length++; // ensure even length //fprintf(stdout,"Padded to %li\n", length); } to = (unsigned char *) malloc(length); fread(to, length, 1, f); //printf("%s %lu\n",parameters.outfile,length);; fclose(f); } *compressedDataSize = length; if (parameters.outfile[0] != '\0') { remove(parameters.outfile); } #endif } //enconderMutex.unlock(); return to; }
BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible) { const S32 MAX_COMPS = 5; opj_cparameters_t parameters; /* compression parameters */ opj_event_mgr_t event_mgr; /* event manager */ /* configure the event callbacks (not required) setting of each callback is optional */ 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(¶meters); parameters.cod_format = 0; parameters.cp_disto_alloc = 1; if (reversible) { parameters.tcp_numlayers = 1; parameters.tcp_rates[0] = 0.0f; } else { parameters.tcp_numlayers = 5; parameters.tcp_rates[0] = 1920.0f; parameters.tcp_rates[1] = 480.0f; parameters.tcp_rates[2] = 120.0f; parameters.tcp_rates[3] = 30.0f; parameters.tcp_rates[4] = 10.0f; parameters.irreversible = 1; if (raw_image.getComponents() >= 3) { parameters.tcp_mct = 1; } } std::string comment_metadata; if (!comment_text) { //Inserting owner id, upload time, and dimensions //See http://wiki.secondlife.com/wiki/Texture_meta-data for details. extern LLUUID gAgentID; time_t now = time(NULL); tm * ptime = gmtime(&now); //std::string color_avg(llformat("c=%02x%02x%02x%02x")); //Perhaps do this some day... std::string timestr(llformat("z=%04i%02i%02i%02i%02i%02i",ptime->tm_year+1900,ptime->tm_mon+1,ptime->tm_mday,ptime->tm_hour,ptime->tm_min,ptime->tm_sec)); comment_metadata=llformat("a=%s&%s&h=%u&w=%u",gAgentID.asString().c_str(),timestr.c_str(),(U32)raw_image.getHeight(),(U32)raw_image.getWidth()); parameters.cp_comment = (char *) comment_metadata.c_str(); } else { // Awful hacky cast, too lazy to copy right now. parameters.cp_comment = (char *) comment_text; } // // Fill in the source image from our raw image // OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; opj_image_cmptparm_t cmptparm[MAX_COMPS]; opj_image_t * image = NULL; S32 numcomps = llmin((S32)raw_image.getComponents(),(S32)MAX_COMPS); //Clamp avoid overrunning buffer -Shyotl S32 width = raw_image.getWidth(); S32 height = raw_image.getHeight(); memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t)); for(S32 c = 0; c < numcomps; c++) { cmptparm[c].prec = 8; cmptparm[c].bpp = 8; cmptparm[c].sgnd = 0; cmptparm[c].dx = parameters.subsampling_dx; cmptparm[c].dy = parameters.subsampling_dy; cmptparm[c].w = width; cmptparm[c].h = height; } /* create the image */ image = opj_image_create(numcomps, &cmptparm[0], color_space); image->x1 = width; image->y1 = height; S32 i = 0; const U8 *src_datap = raw_image.getData(); for (S32 y = height - 1; y >= 0; y--) { for (S32 x = 0; x < width; x++) { const U8 *pixel = src_datap + (y*width + x) * numcomps; for (S32 c = 0; c < numcomps; c++) { image->comps[c].data[i] = *pixel; pixel++; } i++; } } /* encode the destination image */ /* ---------------------------- */ int codestream_length; opj_cio_t *cio = NULL; /* get a J2K compressor handle */ opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K); /* 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, ¶meters, 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 */ bool bSuccess = opj_encode(cinfo, cio, image, NULL); if (!bSuccess) { opj_cio_close(cio); llinfos << "Failed to encode image." << llendl; return FALSE; } codestream_length = cio_tell(cio); base.copyData(cio->buffer, codestream_length); base.updateData(); // set width, height /* close and free the byte stream */ opj_cio_close(cio); /* free remaining compression structures */ opj_destroy_compress(cinfo); /* free user parameters structure */ if(parameters.cp_matrice) free(parameters.cp_matrice); /* free image data */ opj_image_destroy(image); return TRUE; }
int encode_openjpeg(opendcp_t *opendcp, opj_image_t *opj_image, char *out_file) { bool result; int codestream_length; int max_comp_size; int max_cs_len; opj_cparameters_t parameters; opj_cio_t *cio = NULL; opj_cinfo_t *cinfo = NULL; FILE *f = NULL; int bw; if (opendcp->j2k.bw) { bw = opendcp->j2k.bw; } else { bw = MAX_DCP_JPEG_BITRATE; } /* set the max image and component sizes based on frame_rate */ max_cs_len = ((float)bw)/8/opendcp->frame_rate; /* adjust cs for 3D */ if (opendcp->stereoscopic) { max_cs_len = max_cs_len/2; } max_comp_size = ((float)max_cs_len)/1.25; /* set encoding parameters to default values */ opj_set_default_encoder_parameters(¶meters); /* set default cinema parameters */ set_cinema_encoder_parameters(opendcp, ¶meters); parameters.cp_comment = (char*)malloc(strlen(OPENDCP_NAME)+1); sprintf(parameters.cp_comment,"%s", OPENDCP_NAME); /* adjust cinema enum type */ if (opendcp->cinema_profile == DCP_CINEMA4K) { parameters.cp_cinema = CINEMA4K_24; } else { parameters.cp_cinema = CINEMA2K_24; } /* Decide if MCT should be used */ parameters.tcp_mct = opj_image->numcomps == 3 ? 1 : 0; /* set max image */ parameters.max_comp_size = max_comp_size; parameters.tcp_rates[0]= ((float) (opj_image->numcomps * opj_image->comps[0].w * opj_image->comps[0].h * opj_image->comps[0].prec))/ (max_cs_len * 8 * opj_image->comps[0].dx * opj_image->comps[0].dy); /* get a J2K compressor handle */ dcp_log(LOG_DEBUG,"%-15.15s: creating compressor %s","encode_openjpeg",out_file); cinfo = opj_create_compress(CODEC_J2K); /* set event manager to null (openjpeg 1.3 bug) */ cinfo->event_mgr = NULL; /* setup the encoder parameters using the current image and user parameters */ dcp_log(LOG_DEBUG,"%-15.15s: setup J2k encoder %s","encode_openjpeg",out_file); opj_setup_encoder(cinfo, ¶meters, opj_image); /* open a byte stream for writing */ /* allocate memory for all tiles */ dcp_log(LOG_DEBUG,"%-15.15s: opening J2k output stream %s","encode_openjpeg",out_file); cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); dcp_log(LOG_INFO,"Encoding file %s",out_file); result = opj_encode(cinfo, cio, opj_image, NULL); dcp_log(LOG_DEBUG,"%-15.15s: encoding file %s complete","encode_openjepg",out_file); if (!result) { dcp_log(LOG_ERROR,"Unable to encode jpeg2000 file %s",out_file); opj_cio_close(cio); opj_destroy_compress(cinfo); return OPENDCP_ERROR; } codestream_length = cio_tell(cio); f = fopen(out_file, "wb"); if (!f) { dcp_log(LOG_ERROR,"Unable to write jpeg2000 file %s",out_file); opj_cio_close(cio); opj_destroy_compress(cinfo); return OPENDCP_ERROR; } fwrite(cio->buffer, 1, codestream_length, f); fclose(f); /* free openjpeg structure */ opj_cio_close(cio); opj_destroy_compress(cinfo); /* free user parameters structure */ if(parameters.cp_comment) free(parameters.cp_comment); if(parameters.cp_matrice) free(parameters.cp_matrice); return OPENDCP_NO_ERROR; }
bool DotNetEncode(MarshalledImage* image, bool lossless) { try { opj_cparameters cparameters; opj_set_default_encoder_parameters(&cparameters); cparameters.cp_disto_alloc = 1; if (lossless) { cparameters.tcp_numlayers = 1; cparameters.tcp_rates[0] = 0; } else { cparameters.tcp_numlayers = 5; cparameters.tcp_rates[0] = 1920; cparameters.tcp_rates[1] = 480; cparameters.tcp_rates[2] = 120; cparameters.tcp_rates[3] = 30; cparameters.tcp_rates[4] = 10; cparameters.irreversible = 1; if (image->components >= 3) { cparameters.tcp_mct = 1; } } cparameters.cp_comment = (char*)""; opj_image_comptparm comptparm[5]; for (int i = 0; i < image->components; i++) { comptparm[i].bpp = 8; comptparm[i].prec = 8; comptparm[i].sgnd = 0; comptparm[i].dx = 1; comptparm[i].dy = 1; comptparm[i].x0 = 0; comptparm[i].y0 = 0; comptparm[i].w = image->width; comptparm[i].h = image->height; } opj_image_t* jp2_image = opj_image_create(image->components, comptparm, CLRSPC_SRGB); if (jp2_image == NULL) throw "opj_image_create failed"; jp2_image->x0 = 0; jp2_image->y0 = 0; jp2_image->x1 = image->width; jp2_image->y1 = image->height; int n = image->width * image->height; for (int i = 0; i < image->components; i++) std::copy(image->decoded + i * n, image->decoded + (i + 1) * n, jp2_image->comps[i].data); opj_cinfo* cinfo = opj_create_compress(CODEC_J2K); opj_setup_encoder(cinfo, &cparameters, jp2_image); opj_cio* cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); if (cio == NULL) throw "opj_cio_open failed"; if (!opj_encode(cinfo, cio, jp2_image, cparameters.index)) return false; image->length = cio_tell(cio); image->encoded = new unsigned char[image->length]; std::copy(cio->buffer, cio->buffer + image->length, image->encoded); opj_image_destroy(jp2_image); opj_destroy_compress(cinfo); opj_cio_close(cio); return true; } catch (...) { return false; } }
/* Found write info at http://users.ece.gatech.edu/~slabaugh/personal/c/bitmapUnix.c */ int imb_savejp2(struct ImBuf *ibuf, const 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; (void)flags; /* unused */ /* 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(¶meters); /* 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, ¶meters); { /* 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, ¶meters, 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; }
BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible) { const S32 MAX_COMPS = 5; opj_cparameters_t parameters; /* compression parameters */ opj_event_mgr_t event_mgr; /* event manager */ /* configure the event callbacks (not required) setting of each callback is optional */ 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(¶meters); parameters.cod_format = 0; parameters.cp_disto_alloc = 1; if (reversible) { parameters.tcp_numlayers = 1; parameters.tcp_rates[0] = 0.0f; } else { parameters.tcp_numlayers = 5; parameters.tcp_rates[0] = 1920.0f; parameters.tcp_rates[1] = 480.0f; parameters.tcp_rates[2] = 120.0f; parameters.tcp_rates[3] = 30.0f; parameters.tcp_rates[4] = 10.0f; parameters.irreversible = 1; if (raw_image.getComponents() >= 3) { parameters.tcp_mct = 1; } } if (!comment_text) { parameters.cp_comment = (char *) ""; } else { // Awful hacky cast, too lazy to copy right now. parameters.cp_comment = (char *) comment_text; } // // Fill in the source image from our raw image // OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; opj_image_cmptparm_t cmptparm[MAX_COMPS]; opj_image_t * image = NULL; S32 numcomps = raw_image.getComponents(); S32 width = raw_image.getWidth(); S32 height = raw_image.getHeight(); memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t)); for(S32 c = 0; c < numcomps; c++) { cmptparm[c].prec = 8; cmptparm[c].bpp = 8; cmptparm[c].sgnd = 0; cmptparm[c].dx = parameters.subsampling_dx; cmptparm[c].dy = parameters.subsampling_dy; cmptparm[c].w = width; cmptparm[c].h = height; } /* create the image */ image = opj_image_create(numcomps, &cmptparm[0], color_space); image->x1 = width; image->y1 = height; S32 i = 0; const U8 *src_datap = raw_image.getData(); for (S32 y = height - 1; y >= 0; y--) { for (S32 x = 0; x < width; x++) { const U8 *pixel = src_datap + (y*width + x) * numcomps; for (S32 c = 0; c < numcomps; c++) { image->comps[c].data[i] = *pixel; pixel++; } i++; } } /* encode the destination image */ /* ---------------------------- */ int codestream_length; opj_cio_t *cio = NULL; /* get a J2K compressor handle */ opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K); /* 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, ¶meters, 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 */ bool bSuccess = opj_encode(cinfo, cio, image, NULL); if (!bSuccess) { opj_cio_close(cio); LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL; return FALSE; } codestream_length = cio_tell(cio); base.copyData(cio->buffer, codestream_length); base.updateData(); // set width, height /* close and free the byte stream */ opj_cio_close(cio); /* free remaining compression structures */ opj_destroy_compress(cinfo); /* free user parameters structure */ if(parameters.cp_matrice) free(parameters.cp_matrice); /* free image data */ opj_image_destroy(image); return TRUE; }
int main(int argc, char *argv[]) { const char * v = opj_version(); const OPJ_COLOR_SPACE color_space = OPJ_CLRSPC_GRAY; unsigned int numcomps = 1; unsigned int i; unsigned int image_width = 256; unsigned int image_height = 256; opj_cparameters_t parameters; unsigned int subsampling_dx; unsigned int subsampling_dy; const char outputfile[] = "testempty2.j2k"; opj_image_cmptparm_t cmptparm; opj_image_t *image; opj_codec_t* l_codec = 00; OPJ_BOOL bSuccess; opj_stream_t *l_stream = 00; (void)argc; (void)argv; opj_set_default_encoder_parameters(¶meters); parameters.cod_format = J2K_CFMT; puts(v); subsampling_dx = (unsigned int)parameters.subsampling_dx; subsampling_dy = (unsigned int)parameters.subsampling_dy; cmptparm.prec = 8; cmptparm.bpp = 8; cmptparm.sgnd = 0; cmptparm.dx = subsampling_dx; cmptparm.dy = subsampling_dy; cmptparm.w = image_width; cmptparm.h = image_height; strncpy(parameters.outfile, outputfile, sizeof(parameters.outfile)-1); image = opj_image_create(numcomps, &cmptparm, color_space); assert( image ); for (i = 0; i < image_width * image_height; i++) { unsigned int compno; for(compno = 0; compno < numcomps; compno++) { image->comps[compno].data[i] = 0; } } /* catch events using our callbacks and give a local context */ opj_set_info_handler(l_codec, info_callback,00); opj_set_warning_handler(l_codec, warning_callback,00); opj_set_error_handler(l_codec, error_callback,00); l_codec = opj_create_compress(OPJ_CODEC_J2K); opj_set_info_handler(l_codec, info_callback,00); opj_set_warning_handler(l_codec, warning_callback,00); opj_set_error_handler(l_codec, error_callback,00); opj_setup_encoder(l_codec, ¶meters, image); l_stream = opj_stream_create_default_file_stream_v3(parameters.outfile,OPJ_FALSE); if( !l_stream ) { fprintf( stderr, "Something went wrong during creation of stream\n" ); opj_destroy_codec(l_codec); opj_image_destroy(image); opj_stream_destroy_v3(l_stream); return 1; } assert(l_stream); bSuccess = opj_start_compress(l_codec,image,l_stream); if( !bSuccess ) { opj_stream_destroy_v3(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); return 0; } assert( bSuccess ); bSuccess = opj_encode(l_codec, l_stream); assert( bSuccess ); bSuccess = opj_end_compress(l_codec, l_stream); assert( bSuccess ); opj_stream_destroy_v3(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); /* read back the generated file */ { opj_codec_t* d_codec = 00; opj_dparameters_t dparameters; d_codec = opj_create_decompress(OPJ_CODEC_J2K); opj_set_info_handler(d_codec, info_callback,00); opj_set_warning_handler(d_codec, warning_callback,00); opj_set_error_handler(d_codec, error_callback,00); bSuccess = opj_setup_decoder(d_codec, &dparameters); assert( bSuccess ); l_stream = opj_stream_create_default_file_stream_v3(outputfile,1); assert( l_stream ); bSuccess = opj_read_header(l_stream, d_codec, &image); assert( bSuccess ); bSuccess = opj_decode(l_codec, l_stream, image); assert( bSuccess ); bSuccess = opj_end_decompress(l_codec, l_stream); assert( bSuccess ); opj_stream_destroy_v3(l_stream); opj_destroy_codec(d_codec); opj_image_destroy(image); } puts( "end" ); return 0; }
static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { LibOpenJPEGContext *ctx = avctx->priv_data; opj_cinfo_t *compress = ctx->compress; opj_image_t *image = ctx->image; opj_cio_t *stream; int ret, len; // x0, y0 is the top left corner of the image // x1, y1 is the width, height of the reference grid image->x0 = 0; image->y0 = 0; image->x1 = (avctx->width - 1) * ctx->enc_params.subsampling_dx + 1; image->y1 = (avctx->height - 1) * ctx->enc_params.subsampling_dy + 1; switch (avctx->pix_fmt) { case AV_PIX_FMT_RGB24: case AV_PIX_FMT_RGBA: case AV_PIX_FMT_Y400A: libopenjpeg_copy_packed8(avctx, frame, image); break; case AV_PIX_FMT_RGB48: libopenjpeg_copy_packed16(avctx, frame, image); break; case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_YUV410P: case AV_PIX_FMT_YUV411P: case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV440P: case AV_PIX_FMT_YUV444P: case AV_PIX_FMT_YUVA420P: libopenjpeg_copy_unpacked8(avctx, frame, image); break; case AV_PIX_FMT_GRAY16: case AV_PIX_FMT_YUV420P9: case AV_PIX_FMT_YUV422P9: case AV_PIX_FMT_YUV444P9: case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV444P16: case AV_PIX_FMT_YUV422P16: case AV_PIX_FMT_YUV420P16: libopenjpeg_copy_unpacked16(avctx, frame, image); break; default: av_log(avctx, AV_LOG_ERROR, "The frame's pixel format '%s' is not supported\n", av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR(EINVAL); break; } opj_setup_encoder(compress, &ctx->enc_params, image); stream = opj_cio_open((opj_common_ptr)compress, NULL, 0); if (!stream) { av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); return AVERROR(ENOMEM); } if (!opj_encode(compress, stream, image, NULL)) { opj_cio_close(stream); av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); return -1; } len = cio_tell(stream); if ((ret = ff_alloc_packet(pkt, len)) < 0) { opj_cio_close(stream); return ret; } memcpy(pkt->data, stream->buffer, len); pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; opj_cio_close(stream); return 0; }
int main(int argc, char **argv) { mj2_cparameters_t mj2_parameters; /* MJ2 compression parameters */ opj_cparameters_t *j2k_parameters; /* J2K compression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_cio_t *cio; int value; opj_mj2_t *movie; opj_image_t *img; int i, j; char *s, S1, S2, S3; unsigned char *buf; int x1, y1, len; long mdat_initpos, offset; FILE *mj2file; int sampleno; opj_cinfo_t* cinfo; opj_bool bSuccess; int numframes; int prec = 8;/* DEFAULT */ double total_time = 0; memset(&mj2_parameters, 0, sizeof(mj2_cparameters_t)); /* default value */ /* ------------- */ mj2_parameters.w = 352; /* CIF default value*/ mj2_parameters.h = 288; /* CIF default value*/ mj2_parameters.CbCr_subsampling_dx = 2; /* CIF default value*/ mj2_parameters.CbCr_subsampling_dy = 2; /* CIF default value*/ mj2_parameters.frame_rate = 25; mj2_parameters.prec = 8; /* DEFAULT */ mj2_parameters.enumcs = ENUMCS_SYCC; /* FIXME: ENUMCS_YUV420 */ mj2_parameters.meth = 1; /* enumerated color space */ /* 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 = NULL; /* set J2K encoding parameters to default values */ opj_set_default_encoder_parameters(&mj2_parameters.j2k_parameters); j2k_parameters = &mj2_parameters.j2k_parameters; /* Create comment for codestream */ if(j2k_parameters->cp_comment == NULL) { const char comment[] = "Created by OpenJPEG version "; const size_t clen = strlen(comment); const char *version = opj_version(); j2k_parameters->cp_comment = (char*)malloc(clen+strlen(version)+1); sprintf(j2k_parameters->cp_comment,"%s%s", comment, version); } while (1) { int c = opj_getopt(argc, argv, "i:o:r:q:f:t:n:c:b:p:s:d:P:S:E:M:R:T:C:I:W:F:D:h"); if (c == -1) break; switch (c) { case 'i': /* IN fill */ { char *infile = opj_optarg; s = opj_optarg; while (*s) { s++; } s--; S3 = *s; s--; S2 = *s; s--; S1 = *s; if ((S1 == 'y' && S2 == 'u' && S3 == 'v') || (S1 == 'Y' && S2 == 'U' && S3 == 'V')) { mj2_parameters.decod_format = YUV_DFMT; } else { fprintf(stderr, "!! Unrecognized format for infile : %c%c%c [accept only *.yuv] !!\n\n", S1, S2, S3); return 1; } strncpy(mj2_parameters.infile, infile, sizeof(mj2_parameters.infile)-1); } break; /* ----------------------------------------------------- */ case 'o': /* OUT fill */ { char *outfile = opj_optarg; while (*outfile) { outfile++; } outfile--; S3 = *outfile; outfile--; S2 = *outfile; outfile--; S1 = *outfile; outfile = opj_optarg; if ((S1 == 'm' && S2 == 'j' && S3 == '2') || (S1 == 'M' && S2 == 'J' && S3 == '2')) mj2_parameters.cod_format = MJ2_CFMT; else { fprintf(stderr, "Unknown output format image *.%c%c%c [only *.mj2]!! \n", S1, S2, S3); return 1; } strncpy(mj2_parameters.outfile, outfile, sizeof(mj2_parameters.outfile)-1); } break; /* ----------------------------------------------------- */ case 'r': /* rates rates/distorsion */ { float rate; s = opj_optarg; while (sscanf(s, "%f", &rate) == 1) { j2k_parameters->tcp_rates[j2k_parameters->tcp_numlayers] = rate * 2; j2k_parameters->tcp_numlayers++; while (*s && *s != ',') { s++; } if (!*s) break; s++; } j2k_parameters->cp_disto_alloc = 1; } break; /* ----------------------------------------------------- */ case 'q': /* add fixed_quality */ s = opj_optarg; while (sscanf(s, "%f", &j2k_parameters->tcp_distoratio[j2k_parameters->tcp_numlayers]) == 1) { j2k_parameters->tcp_numlayers++; while (*s && *s != ',') { s++; } if (!*s) break; s++; } j2k_parameters->cp_fixed_quality = 1; break; /* dda */ /* ----------------------------------------------------- */ case 'f': /* mod fixed_quality (before : -q) */ { int *row = NULL, *col = NULL; int numlayers = 0, numresolution = 0, matrix_width = 0; s = opj_optarg; sscanf(s, "%d", &numlayers); s++; if (numlayers > 9) s++; j2k_parameters->tcp_numlayers = numlayers; numresolution = j2k_parameters->numresolution; matrix_width = numresolution * 3; j2k_parameters->cp_matrice = (int *) malloc(numlayers * matrix_width * sizeof(int)); s = s + 2; for (i = 0; i < numlayers; i++) { row = &j2k_parameters->cp_matrice[i * matrix_width]; col = row; j2k_parameters->tcp_rates[i] = 1; sscanf(s, "%d,", &col[0]); s += 2; if (col[0] > 9) s++; col[1] = 0; col[2] = 0; for (j = 1; j < numresolution; j++) { col += 3; sscanf(s, "%d,%d,%d", &col[0], &col[1], &col[2]); s += 6; if (col[0] > 9) s++; if (col[1] > 9) s++; if (col[2] > 9) s++; } if (i < numlayers - 1) s++; } j2k_parameters->cp_fixed_alloc = 1; } break; /* ----------------------------------------------------- */ case 't': /* tiles */ sscanf(opj_optarg, "%d,%d", &j2k_parameters->cp_tdx, &j2k_parameters->cp_tdy); j2k_parameters->tile_size_on = OPJ_TRUE; break; /* ----------------------------------------------------- */ case 'n': /* resolution */ sscanf(opj_optarg, "%d", &j2k_parameters->numresolution); break; /* ----------------------------------------------------- */ case 'c': /* precinct dimension */ { char sep; int res_spec = 0; char *s = opj_optarg; do { sep = 0; sscanf(s, "[%d,%d]%c", &j2k_parameters->prcw_init[res_spec], &j2k_parameters->prch_init[res_spec], &sep); j2k_parameters->csty |= 0x01; res_spec++; s = strpbrk(s, "]") + 2; } while (sep == ','); j2k_parameters->res_spec = res_spec; } break; /* ----------------------------------------------------- */ case 'b': /* code-block dimension */ { int cblockw_init = 0, cblockh_init = 0; sscanf(opj_optarg, "%d,%d", &cblockw_init, &cblockh_init); if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) { fprintf(stderr, "!! Size of code_block error (option -b) !!\n\nRestriction :\n" " * width*height<=4096\n * 4<=width,height<= 1024\n\n"); return 1; } j2k_parameters->cblockw_init = cblockw_init; j2k_parameters->cblockh_init = cblockh_init; } break; /* ----------------------------------------------------- */ case 'p': /* progression order */ { char progression[5]; strncpy(progression, opj_optarg, 5); j2k_parameters->prog_order = give_progression(progression); if (j2k_parameters->prog_order == -1) { fprintf(stderr, "Unrecognized progression order " "[LRCP, RLCP, RPCL, PCRL, CPRL] !!\n"); return 1; } } break; /* ----------------------------------------------------- */ case 's': /* subsampling factor */ { if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->subsampling_dx, &j2k_parameters->subsampling_dy) != 2) { fprintf(stderr, "'-s' sub-sampling argument error ! [-s dx,dy]\n"); return 1; } } break; /* ----------------------------------------------------- */ case 'd': /* coordonnate of the reference grid */ { if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->image_offset_x0, &j2k_parameters->image_offset_y0) != 2) { fprintf(stderr, "-d 'coordonnate of the reference grid' argument " "error !! [-d x0,y0]\n"); return 1; } } break; /* ----------------------------------------------------- */ case 'h': /* Display an help description */ help_display(); return 0; break; /* ----------------------------------------------------- */ case 'P': /* POC */ { int numpocs = 0; /* number of progression order change (POC) default 0 */ opj_poc_t *POC = NULL; /* POC : used in case of Progression order change */ char *s = opj_optarg; POC = j2k_parameters->POC; while (sscanf(s, "T%d=%d,%d,%d,%d,%d,%4s", &POC[numpocs].tile, &POC[numpocs].resno0, &POC[numpocs].compno0, &POC[numpocs].layno1, &POC[numpocs].resno1, &POC[numpocs].compno1, POC[numpocs].progorder) == 7) { POC[numpocs].prg1 = give_progression(POC[numpocs].progorder); numpocs++; while (*s && *s != '/') { s++; } if (!*s) { break; } s++; } j2k_parameters->numpocs = numpocs; } break; /* ------------------------------------------------------ */ case 'S': /* SOP marker */ j2k_parameters->csty |= 0x02; break; /* ------------------------------------------------------ */ case 'E': /* EPH marker */ j2k_parameters->csty |= 0x04; break; /* ------------------------------------------------------ */ case 'M': /* Mode switch pas tous au point !! */ if (sscanf(opj_optarg, "%d", &value) == 1) { for (i = 0; i <= 5; i++) { int cache = value & (1 << i); if (cache) j2k_parameters->mode |= (1 << i); } } break; /* ------------------------------------------------------ */ case 'R': /* ROI */ { if (sscanf(opj_optarg, "OI:c=%d,U=%d", &j2k_parameters->roi_compno, &j2k_parameters->roi_shift) != 2) { fprintf(stderr, "ROI error !! [-ROI:c='compno',U='shift']\n"); return 1; } } break; /* ------------------------------------------------------ */ case 'T': /* Tile offset */ { if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->cp_tx0, &j2k_parameters->cp_ty0) != 2) { fprintf(stderr, "-T 'tile offset' argument error !! [-T X0,Y0]"); return 1; } } break; /* ------------------------------------------------------ */ case 'C': /* Add a comment */ { j2k_parameters->cp_comment = (char*)malloc(strlen(opj_optarg) + 1); if(j2k_parameters->cp_comment) { strcpy(j2k_parameters->cp_comment, opj_optarg); } } break; /* ------------------------------------------------------ */ case 'I': /* reversible or not */ { j2k_parameters->irreversible = 1; } break; /* ------------------------------------------------------ */ case 'W': /* Width and Height and Cb and Cr subsampling in case of YUV format files */ if (sscanf (opj_optarg, "%d,%d,%d,%d", &mj2_parameters.w, &mj2_parameters.h, &mj2_parameters.CbCr_subsampling_dx, &mj2_parameters.CbCr_subsampling_dy) != 4) { fprintf(stderr, "-W argument error"); return 1; } break; /* ------------------------------------------------------ */ case 'F': /* Video frame rate */ if (sscanf(opj_optarg, "%d", &mj2_parameters.frame_rate) != 1) { fprintf(stderr, "-F argument error"); return 1; } break; /* ------------------------------------------------------ */ case 'D': /* Depth: the precision */ if(sscanf(opj_optarg, "%d", &prec) != 1) prec = 0; break; default: return 1; } } /* Error messages */ /* -------------- */ if (!mj2_parameters.cod_format || !mj2_parameters.decod_format) { fprintf(stderr, "Usage: %s -i yuv-file -o mj2-file (+ options)\n",argv[0]); return 1; } if(prec < 1 || prec > 16) { fprintf(stderr, "Error: Depth %d must be in the range 8 .. 16\n",prec); return 1; } if ((j2k_parameters->cp_disto_alloc || j2k_parameters->cp_fixed_alloc || j2k_parameters->cp_fixed_quality) && (!(j2k_parameters->cp_disto_alloc ^ j2k_parameters->cp_fixed_alloc ^ j2k_parameters->cp_fixed_quality))) { fprintf(stderr, "Error: options -r -q and -f cannot be used together !!\n"); return 1; } /* mod fixed_quality */ /* if no rate entered, lossless by default */ if (j2k_parameters->tcp_numlayers == 0) { j2k_parameters->tcp_rates[0] = 0; /* MOD antonin : losslessbug */ j2k_parameters->tcp_numlayers++; j2k_parameters->cp_disto_alloc = 1; } if((j2k_parameters->cp_tx0 > j2k_parameters->image_offset_x0) || (j2k_parameters->cp_ty0 > j2k_parameters->image_offset_y0)) { fprintf(stderr, "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n", j2k_parameters->cp_tx0, j2k_parameters->image_offset_x0, j2k_parameters->cp_ty0, j2k_parameters->image_offset_y0); return 1; } for (i = 0; i < j2k_parameters->numpocs; i++) { if (j2k_parameters->POC[i].prg == -1) { fprintf(stderr, "Unrecognized progression order in option -P (POC n %d) [LRCP, RLCP, RPCL, PCRL, CPRL] !!\n", i + 1); } } if (j2k_parameters->cp_tdx > mj2_parameters.Dim[0] || j2k_parameters->cp_tdy > mj2_parameters.Dim[1]) { fprintf(stderr, "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n", j2k_parameters->cp_tdx, mj2_parameters.Dim[0], j2k_parameters->cp_tdy, mj2_parameters.Dim[1]); return 1; } /* to respect profile - 0 */ /* ---------------------- */ x1 = !mj2_parameters.Dim[0] ? (mj2_parameters.w - 1) * j2k_parameters->subsampling_dx + 1 : mj2_parameters.Dim[0] + (mj2_parameters.w - 1) * j2k_parameters->subsampling_dx + 1; y1 = !mj2_parameters.Dim[1] ? (mj2_parameters.h - 1) * j2k_parameters->subsampling_dy + 1 : mj2_parameters.Dim[1] + (mj2_parameters.h - 1) * j2k_parameters->subsampling_dy + 1; mj2_parameters.numcomps = 3; /* YUV files only have 3 components */ mj2_parameters.prec = prec; j2k_parameters->tcp_mct = 0; mj2file = fopen(mj2_parameters.outfile, "wb"); if (!mj2file) { fprintf(stderr, "failed to open %s for writing\n", argv[2]); return 1; } /* get a MJ2 decompressor handle */ cinfo = mj2_create_compress(); movie = (opj_mj2_t*)cinfo->mj2_handle; /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); /* setup encoder parameters */ mj2_setup_encoder(movie, &mj2_parameters); movie->tk[0].num_samples = yuv_num_frames(&movie->tk[0],mj2_parameters.infile); if (movie->tk[0].num_samples == 0) { return 1; } /* One sample per chunk*/ movie->tk[0].chunk = (mj2_chunk_t*) malloc(movie->tk[0].num_samples * sizeof(mj2_chunk_t)); movie->tk[0].sample = (mj2_sample_t*) malloc(movie->tk[0].num_samples * sizeof(mj2_sample_t)); if (mj2_init_stdmovie(movie)) { fprintf(stderr, "Error with movie initialization"); return 1; } /* Writing JP, FTYP and MDAT boxes */ /* Assuming that the JP and FTYP boxes won't be longer than 300 bytes:*/ buf = (unsigned char*) malloc (300 * sizeof(unsigned char)); cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, 300); mj2_write_jp(cio); mj2_write_ftyp(movie, cio); mdat_initpos = cio_tell(cio); cio_skip(cio, 4); cio_write(cio, MJ2_MDAT, 4); fwrite(buf,cio_tell(cio),1,mj2file); offset = cio_tell(cio); opj_cio_close(cio); free(buf); for(i = 0; i < movie->num_stk + movie->num_htk + movie->num_vtk; i++) { if(movie->tk[i].track_type != 0) { fprintf(stderr, "Unable to write sound or hint tracks\n"); } else { mj2_tk_t *tk; int buflen = 0; tk = &movie->tk[i]; tk->num_chunks = tk->num_samples; numframes = tk->num_samples; tk->depth = prec; fprintf(stderr, "Video Track number %d\n", i); img = mj2_image_create(tk, j2k_parameters); buflen = 2 * (tk->w * tk->h * 8); buf = (unsigned char *) malloc(buflen*sizeof(unsigned char)); for(sampleno = 0; sampleno < numframes; sampleno++) { double init_time = opj_clock(); double elapsed_time; if(yuvtoimage(tk, img, sampleno, j2k_parameters, mj2_parameters.infile)) { fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno); return 1; } /* setup the encoder parameters using the current image and user parameters */ opj_setup_encoder(cinfo, j2k_parameters, img); cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, buflen); cio_skip(cio, 4); cio_write(cio, JP2_JP2C, 4); /* JP2C*/ /* encode the image */ bSuccess = opj_encode(cinfo, cio, img, NULL); if (!bSuccess) { opj_cio_close(cio); fprintf(stderr, "failed to encode image\n"); return 1; } len = cio_tell(cio) - 8; cio_seek(cio, 0); cio_write(cio, len+8,4); opj_cio_close(cio); tk->sample[sampleno].sample_size = len+8; tk->sample[sampleno].offset = offset; tk->chunk[sampleno].offset = offset; /* There is one sample per chunk */ fwrite(buf, 1, len+8, mj2file); offset += len+8; elapsed_time = opj_clock()-init_time; fprintf(stderr, "Frame number %d/%d encoded in %.2f mseconds\n", sampleno + 1, numframes, elapsed_time*1000); total_time += elapsed_time; } /* for(sampleno */ free(buf); opj_image_destroy(img); } }/* for(i */ fseek(mj2file, mdat_initpos, SEEK_SET); buf = (unsigned char*) malloc(4*sizeof(unsigned char)); /* Init a cio to write box length variable in a little endian way */ cio = opj_cio_open(NULL, buf, 4); cio_write(cio, offset - mdat_initpos, 4); fwrite(buf, 4, 1, mj2file); fseek(mj2file,0,SEEK_END); free(buf); /* Writing MOOV box */ buf = (unsigned char*) malloc ((TEMP_BUF+numframes*20) * sizeof(unsigned char)); cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+numframes*20)); mj2_write_moov(movie, cio); fwrite(buf,cio_tell(cio),1,mj2file); free(buf); fprintf(stdout,"Total encoding time: %.2f s for %d frames (%.1f fps)\n", total_time, numframes, (float)numframes/total_time); /* Ending program */ fclose(mj2file); /* free remaining compression structures */ mj2_destroy_compress(movie); free(cinfo); if(j2k_parameters->cp_comment) free(j2k_parameters->cp_comment); if(j2k_parameters->cp_matrice) free(j2k_parameters->cp_matrice); opj_cio_close(cio); return 0; }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { if ((dib) && (handle)) { BOOL bSuccess; opj_cparameters_t parameters; // compression parameters opj_event_mgr_t event_mgr; // event manager opj_image_t *image = NULL; // image to encode opj_cinfo_t* cinfo = NULL; // codec context opj_cio_t *cio = NULL; // memory byte stream // configure the event callbacks memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = jp2_error_callback; event_mgr.warning_handler = jp2_warning_callback; event_mgr.info_handler = NULL; // set encoding parameters to default values opj_set_default_encoder_parameters(¶meters); parameters.tcp_numlayers = 0; // if no rate entered, apply a 16:1 rate by default if(flags == JP2_DEFAULT) { parameters.tcp_rates[0] = (float)16; } else { // for now, the flags parameter is only used to specify the rate parameters.tcp_rates[0] = (float)flags; } parameters.tcp_numlayers++; parameters.cp_disto_alloc = 1; try { // convert the dib to a OpenJPEG image image = FIBITMAPToJ2KImage(s_format_id, dib, ¶meters); if(!image) return FALSE; // encode the destination image // get a J2K compressor handle cinfo = opj_create_compress(CODEC_JP2); // catch events using our callbacks opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, NULL); // setup the encoder parameters using the current image and using user parameters opj_setup_encoder(cinfo, ¶meters, 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/*parameters.index*/); if (!bSuccess) { throw "Failed to encode image"; } int codestream_length = cio_tell(cio); // write the buffer to user's IO handle io->write_proc(cio->buffer, 1, codestream_length, handle); // 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 TRUE; } catch (const char *text) { if(cio) opj_cio_close(cio); if(cinfo) opj_destroy_compress(cinfo); if(image) opj_image_destroy(image); FreeImage_OutputMessageProc(s_format_id, text); return FALSE; } } return FALSE; }
/*! * pixWriteStreamJp2k() * * Input: stream * pix (any depth, cmap is OK) * quality (SNR > 0; default ~34; 0 for lossless encoding) * nlevels (<= 10) * hint (a bitwise OR of L_JP2K_* values; 0 for default) * debug (output callback messages, etc) * Return: 0 if OK, 1 on error * Notes: * (1) See pixWriteJp2k() for usage. * (2) For an encoder with more encoding options, see, e.g., * https://github.com/OpenJPEG/openjpeg/blob/master/tests/test_tile_encoder.c */ l_int32 pixWriteStreamJp2k(FILE *fp, PIX *pix, l_int32 quality, l_int32 nlevels, l_int32 hint, l_int32 debug) { l_int32 w, h, d, success, snr; const char *opjVersion; PIX *pixs; opj_cparameters_t parameters; /* compression parameters */ opj_stream_t *l_stream = NULL; opj_codec_t* l_codec = NULL;; opj_image_t *image = NULL; PROCNAME("pixWriteStreamJp2k"); if (!fp) return ERROR_INT("stream not open", procName, 1); if (!pix) return ERROR_INT("pix not defined", procName, 1); if (quality < 0) return ERROR_INT("quality must be >= 0", procName, 1); if (quality > 0 && quality < 27) L_WARNING("SNR = %d < 27; very low\n", procName, quality); if (quality > 45) L_WARNING("SNR = %d > 45; nearly lossless\n", procName, quality); snr = (l_float32)quality; if (nlevels <= 0) nlevels = 5; /* default */ if (nlevels > 10) { L_WARNING("nlevels = %d > 10; setting to 10\n", procName, nlevels); nlevels = 10; } opjVersion = opj_version(); if (opjVersion[0] != '2') { L_ERROR("version is %s; must be 2.0 or higher\n", procName, opjVersion); return 1; } if ((opjVersion[2] - 0x30) != OPJ_VERSION_MINOR) { L_ERROR("version %s: differs from minor = %d\n", procName, opjVersion, OPJ_VERSION_MINOR); return 1; } /* Remove colormap if it exists; result is 8 or 32 bpp */ pixGetDimensions(pix, &w, &h, &d); if (d == 24) { pixs = pixConvert24To32(pix); } else if (d == 32) { pixs = pixClone(pix); } else if (pixGetColormap(pix) == NULL) { pixs = pixConvertTo8(pix, 0); } else { /* colormap */ L_INFO("removing colormap; may be better to compress losslessly\n", procName); pixs = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC); } /* Convert to opj image format. */ image = pixConvertToOpjImage(pixs); pixDestroy(&pixs); /* Set encoding parameters to default values. * We use one layer with the input SNR. */ opj_set_default_encoder_parameters(¶meters); parameters.cp_fixed_quality = 1; parameters.cp_disto_alloc = 0; parameters.cp_fixed_alloc = 0; parameters.tcp_distoratio[0] = snr; parameters.tcp_numlayers = 1; parameters.numresolution = nlevels + 1; /* Create comment for codestream */ if (parameters.cp_comment == NULL) { const char comment1[] = "Created by Leptonica, version "; const char comment2[] = "; using OpenJPEG, version "; size_t len1 = strlen(comment1); size_t len2 = strlen(comment2); char *version1 = getLeptonicaVersion(); const char *version2 = opj_version(); len1 += len2 + strlen(version1) + strlen(version2) + 1; parameters.cp_comment = (char *)MALLOC(len1); snprintf(parameters.cp_comment, len1, "%s%s%s%s", comment1, version1, comment2, version2); FREE(version1); } /* Get the encoder handle */ if ((l_codec = opj_create_compress(OPJ_CODEC_JP2)) == NULL) { opj_image_destroy(image); FREE(parameters.cp_comment); return ERROR_INT("failed to get the encoder handle\n", procName, 1); } /* Catch and report events using callbacks */ if (debug) { opj_set_info_handler(l_codec, info_callback, NULL); opj_set_warning_handler(l_codec, warning_callback, NULL); opj_set_error_handler(l_codec, error_callback, NULL); } /* Set up the encoder */ if (!opj_setup_encoder(l_codec, ¶meters, image)) { opj_destroy_codec(l_codec); opj_image_destroy(image); FREE(parameters.cp_comment); return ERROR_INT("failed to set up the encoder\n", procName, 1); } /* Open a compression stream for writing. In 2.0 we could use this: * opj_stream_create_default_file_stream(fp, 0) * but the file stream interface was removed in 2.1. */ rewind(fp); if ((l_stream = opjCreateStream(fp, 0)) == NULL) { opj_destroy_codec(l_codec); opj_image_destroy(image); FREE(parameters.cp_comment); return ERROR_INT("failed to open l_stream\n", procName, 1); } /* Encode the image */ if (!opj_start_compress(l_codec, image, l_stream)) { opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); FREE(parameters.cp_comment); return ERROR_INT("opj_start_compress failed\n", procName, 1); } if (!opj_encode(l_codec, l_stream)) { opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); FREE(parameters.cp_comment); return ERROR_INT("opj_encode failed\n", procName, 1); } success = opj_end_compress(l_codec, l_stream); /* Clean up */ opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); FREE(parameters.cp_comment); if (success) return 0; else return ERROR_INT("opj_end_compress failed\n", procName, 1); }