/* ***** BEGIN GPL LICENSE BLOCK ***** * * Copyright 2008 Peter Schlaile * * This file is part of libredcode. * * Libredcode 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. * * Libredcode 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 libredcode; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * ***** END GPL LICENSE BLOCK *****/ #include "codec.h" #include "format.h" #include "debayer.h" #include #include #include #include static void error_callback(const char *msg, void *client_data) { FILE *stream = (FILE*)client_data; fprintf(stream, "[R3D ERR] %s", msg); } static void warning_callback(const char *msg, void *client_data) { FILE *stream = (FILE*)client_data; fprintf(stream, "[R3D WARN] %s", msg); } static void info_callback(const char *msg, void *client_data) { (void)client_data; fprintf(stdout, "[R3D INFO] %s", msg); } #define J2K_CFMT 0 #define JP2_CFMT 1 #define JPT_CFMT 2 struct redcode_frame_raw * redcode_decode_video_raw( struct redcode_frame * frame, int scale) { struct redcode_frame_raw * rv = NULL; opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ opj_cio_t *cio = NULL; 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; opj_set_default_decoder_parameters(¶meters); parameters.decod_format = JP2_CFMT; if (scale == 2) { parameters.cp_reduce = 1; } else if (scale == 4) { parameters.cp_reduce = 2; } else if (scale == 8) { parameters.cp_reduce = 3; } /* 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, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, frame->data + frame->offset, frame->length); 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 0; } /* close the byte stream */ opj_cio_close(cio); /* free remaining structures */ if(dinfo) { opj_destroy_decompress(dinfo); } if((image->numcomps * image->x1 * image->y1) == 0) { opj_image_destroy(image); return 0; } rv = (struct redcode_frame_raw *) calloc( 1, sizeof(struct redcode_frame_raw)); rv->data = image; rv->width = image->comps[0].w; rv->height = image->comps[0].h; return rv; } int redcode_decode_video_float(struct redcode_frame_raw * frame, float * out, int scale) { int* planes[4]; int i; opj_image_t *image = (opj_image_t*) frame->data; if (image->numcomps != 4) { fprintf(stderr, "R3D: need 4 planes, but got: %d\n", image->numcomps); return 0; } for (i = 0; i < 4; i++) { planes[i] = image->comps[i].data; } if (scale == 1) { redcode_ycbcr2rgb_fullscale( planes, frame->width, frame->height, out); } else if (scale == 2) { redcode_ycbcr2rgb_halfscale( planes, frame->width, frame->height, out); } else if (scale == 4) { redcode_ycbcr2rgb_quarterscale( planes, frame->width, frame->height, out); } opj_image_destroy(image); free(frame); return 1; }