Reformat whole codebase with astyle.options (#128)
[openjpeg.git] / src / bin / mj2 / opj_mj2_wrap.c
1 /*
2  * The copyright in this software is being made available under the 2-clauses
3  * BSD License, included below. This software may be subject to other third
4  * party and contributor rights, including patent rights, and no such rights
5  * are granted under this license.
6  *
7  * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
8  * Copyright (c) 2002-2014, Professor Benoit Macq
9  * Copyright (c) 2003-2007, Francois-Olivier Devaux
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "openjpeg.h"
39 #include "cio.h"
40 #include "j2k.h"
41 #include "jp2.h"
42 #include "mj2.h"
43
44 static int int_ceildiv(int a, int b)
45 {
46     return (a + b - 1) / b;
47 }
48
49 /**
50 Size of memory first allocated for MOOV box
51 */
52 #define TEMP_BUF 10000
53
54 #define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
55
56 /* -------------------------------------------------------------------------- */
57
58 static int test_image(const char *fname, mj2_cparameters_t *cp)
59 {
60     FILE *reader;
61     opj_image_t *image;
62     unsigned char *src;
63     opj_dinfo_t *dinfo;
64     opj_cio_t *cio;
65     opj_dparameters_t dparameters;
66     int success;
67     long src_len;
68
69     success = 0;
70
71     if ((reader = fopen(fname, "rb")) == NULL) {
72         return success;
73     }
74
75     fseek(reader, 0, SEEK_END);
76     src_len = ftell(reader);
77     fseek(reader, 0, SEEK_SET);
78     src = (unsigned char*) malloc(src_len);
79     fread(src, 1, src_len, reader);
80     fclose(reader);
81
82     if (memcmp(src, J2K_CODESTREAM_MAGIC, 4) != 0) {
83         free(src);
84         return success;
85     }
86     memset(&dparameters, 0, sizeof(opj_dparameters_t));
87
88     opj_set_default_decoder_parameters(&dparameters);
89
90     dinfo = opj_create_decompress(CODEC_J2K);
91
92     opj_setup_decoder(dinfo, &dparameters);
93
94     cio = opj_cio_open((opj_common_ptr)dinfo, src, src_len);
95
96     image = opj_decode(dinfo, cio);
97
98     free(src);
99     cio->buffer = NULL;
100     opj_cio_close(cio);
101
102     if (image == NULL) {
103         goto fin;
104     }
105
106     cp->numcomps = image->numcomps;
107     cp->w = image->comps[0].w;
108     cp->h = image->comps[0].h;
109     cp->prec = image->comps[0].prec;
110
111     if (image->numcomps > 2) {
112         if ((image->comps[0].dx == 1)
113                 && (image->comps[1].dx == 2)
114                 && (image->comps[2].dx == 2)
115                 && (image->comps[0].dy == 1)
116                 && (image->comps[1].dy == 2)
117                 && (image->comps[2].dy == 2)) { /* horizontal and vertical*/
118             /*   Y420*/
119             cp->enumcs = ENUMCS_SYCC;
120             cp->CbCr_subsampling_dx = 2;
121             cp->CbCr_subsampling_dy = 2;
122         } else if ((image->comps[0].dx == 1)
123                    && (image->comps[1].dx == 2)
124                    && (image->comps[2].dx == 2)
125                    && (image->comps[0].dy == 1)
126                    && (image->comps[1].dy == 1)
127                    && (image->comps[2].dy == 1)) { /* horizontal only*/
128             /*   Y422*/
129             cp->enumcs = ENUMCS_SYCC;
130             cp->CbCr_subsampling_dx = 2;
131             cp->CbCr_subsampling_dy = 1;
132         } else if ((image->comps[0].dx == 1)
133                    && (image->comps[1].dx == 1)
134                    && (image->comps[2].dx == 1)
135                    && (image->comps[0].dy == 1)
136                    && (image->comps[1].dy == 1)
137                    && (image->comps[2].dy == 1)) {
138             /*   Y444 or RGB */
139
140             if (image->color_space ==  CLRSPC_SRGB) {
141                 cp->enumcs = ENUMCS_SRGB;
142
143                 /*    cp->CbCr_subsampling_dx = 0; */
144                 /*    cp->CbCr_subsampling_dy = 0; */
145             } else {
146                 cp->enumcs = ENUMCS_SYCC;
147
148                 cp->CbCr_subsampling_dx = 1;
149                 cp->CbCr_subsampling_dy = 1;
150             }
151         } else {
152             goto fin;
153         }
154     } else {
155         cp->enumcs = ENUMCS_GRAY;
156         /*  cp->CbCr_subsampling_dx = 0; */
157         /*  cp->CbCr_subsampling_dy = 0; */
158     }
159     if (image->icc_profile_buf) {
160         cp->meth = 2;
161         free(image->icc_profile_buf);
162         image->icc_profile_buf = NULL;
163     } else {
164         cp->meth = 1;
165     }
166
167     success = 1;
168 fin:
169     if (dinfo) {
170         opj_destroy_decompress(dinfo);
171     }
172
173     if (image) {
174         opj_image_destroy(image);
175     }
176
177     return success;
178 }
179
180 /**
181 sample error callback expecting a FILE* client object
182 */
183 static void error_callback(const char *msg, void *client_data)
184 {
185     FILE *stream = (FILE*)client_data;
186     fprintf(stream, "[ERROR] %s", msg);
187 }
188 /**
189 sample warning callback expecting a FILE* client object
190 */
191 static void warning_callback(const char *msg, void *client_data)
192 {
193     FILE *stream = (FILE*)client_data;
194     fprintf(stream, "[WARNING] %s", msg);
195 }
196 /**
197 sample debug callback expecting a FILE* client object
198 */
199 static void info_callback(const char *msg, void *client_data)
200 {
201     FILE *stream = (FILE*)client_data;
202     fprintf(stream, "[INFO] %s", msg);
203 }
204
205 /* -------------------------------------------------------------------------- */
206
207
208
209 static void read_siz_marker(FILE *file, opj_image_t *image)
210 {
211     int len, i;
212     char buf, buf2[2];
213     unsigned char *siz_buffer;
214     opj_cio_t *cio;
215
216     fseek(file, 0, SEEK_SET);
217     do {
218         fread(&buf, 1, 1, file);
219         if (buf == (char)0xff) {
220             fread(&buf, 1, 1, file);
221         }
222     } while (!(buf == (char)0x51));
223
224     fread(buf2, 2, 1, file);  /* Lsiz                */
225     len = ((buf2[0]) << 8) + buf2[1];
226
227     siz_buffer = (unsigned char*) malloc(len * sizeof(unsigned char));
228     fread(siz_buffer, len, 1, file);
229     cio = opj_cio_open(NULL, siz_buffer, len);
230
231     cio_read(cio, 2);         /* Rsiz (capabilities) */
232     image->x1 = cio_read(cio, 4); /* Xsiz                */
233     image->y1 = cio_read(cio, 4); /* Ysiz                */
234     image->x0 = cio_read(cio, 4); /* X0siz               */
235     image->y0 = cio_read(cio, 4); /* Y0siz               */
236     cio_skip(cio, 16);            /* XTsiz, YTsiz, XT0siz, YT0siz        */
237
238     image->numcomps = cio_read(cio, 2);   /* Csiz                */
239     image->comps =
240         (opj_image_comp_t *) malloc(image->numcomps * sizeof(opj_image_comp_t));
241
242     for (i = 0; i < image->numcomps; i++) {
243         int tmp;
244         tmp = cio_read(cio, 1);     /* Ssiz_i          */
245         image->comps[i].prec = (tmp & 0x7f) + 1;
246         image->comps[i].sgnd = tmp >> 7;
247         image->comps[i].dx = cio_read(cio, 1);  /* XRsiz_i         */
248         image->comps[i].dy = cio_read(cio, 1);  /* YRsiz_i         */
249         image->comps[i].resno_decoded = 0;  /* number of resolution decoded */
250         image->comps[i].factor = 0; /* reducing factor by component */
251     }
252     fseek(file, 0, SEEK_SET);
253     opj_cio_close(cio);
254     free(siz_buffer);
255 }
256
257 static void setparams(opj_mj2_t *movie, opj_image_t *image)
258 {
259     int i, depth_0, depth, sign;
260
261     movie->tk[0].w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
262     movie->tk[0].h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
263     mj2_init_stdmovie(movie);
264
265     movie->tk[0].depth = image->comps[0].prec;
266
267     if (image->numcomps == 3) {
268         if ((image->comps[0].dx == 1)
269                 && (image->comps[1].dx == 1)
270                 && (image->comps[2].dx == 1)) {
271             movie->tk[0].CbCr_subsampling_dx = 1;
272         } else if ((image->comps[0].dx == 1)
273                    && (image->comps[1].dx == 2)
274                    && (image->comps[2].dx == 2)) {
275             movie->tk[0].CbCr_subsampling_dx = 2;
276         } else {
277             fprintf(stderr, "Image component sizes are incoherent\n");
278         }
279
280         if ((image->comps[0].dy == 1)
281                 && (image->comps[1].dy == 1)
282                 && (image->comps[2].dy == 1)) {
283             movie->tk[0].CbCr_subsampling_dy = 1;
284         } else if ((image->comps[0].dy == 1)
285                    && (image->comps[1].dy == 2)
286                    && (image->comps[2].dy == 2)) {
287             movie->tk[0].CbCr_subsampling_dy = 2;
288         } else {
289             fprintf(stderr, "Image component sizes are incoherent\n");
290         }
291     }
292
293     movie->tk[0].sample_rate = 25;
294
295     movie->tk[0].jp2_struct.numcomps = image->numcomps;   /* NC */
296
297     /* Init Standard jp2 structure */
298
299     movie->tk[0].jp2_struct.comps =
300         (opj_jp2_comps_t *) malloc(movie->tk[0].jp2_struct.numcomps * sizeof(
301                                        opj_jp2_comps_t));
302     movie->tk[0].jp2_struct.precedence = 0;   /* PRECEDENCE*/
303     movie->tk[0].jp2_struct.approx = 0;   /* APPROX*/
304     movie->tk[0].jp2_struct.brand = JP2_JP2;  /* BR         */
305     movie->tk[0].jp2_struct.minversion = 0;   /* MinV       */
306     movie->tk[0].jp2_struct.numcl = 1;
307     movie->tk[0].jp2_struct.cl = (unsigned int *) malloc(
308                                      movie->tk[0].jp2_struct.numcl * sizeof(int));
309     movie->tk[0].jp2_struct.cl[0] = JP2_JP2;  /* CL0 : JP2  */
310     movie->tk[0].jp2_struct.C = 7;      /* C : Always 7*/
311     movie->tk[0].jp2_struct.UnkC =
312         0;      /* UnkC, colorspace specified in colr box*/
313     movie->tk[0].jp2_struct.IPR = 0;      /* IPR, no intellectual property*/
314     movie->tk[0].jp2_struct.w = int_ceildiv(image->x1 - image->x0,
315                                             image->comps[0].dx);
316     movie->tk[0].jp2_struct.h = int_ceildiv(image->y1 - image->y0,
317                                             image->comps[0].dy);
318
319     depth_0 = image->comps[0].prec - 1;
320     sign = image->comps[0].sgnd;
321     movie->tk[0].jp2_struct.bpc = depth_0 + (sign << 7);
322
323     for (i = 1; i < image->numcomps; i++) {
324         depth = image->comps[i].prec - 1;
325         sign = image->comps[i].sgnd;
326         if (depth_0 != depth) {
327             movie->tk[0].jp2_struct.bpc = 255;
328         }
329     }
330
331     for (i = 0; i < image->numcomps; i++)
332         movie->tk[0].jp2_struct.comps[i].bpcc =
333             image->comps[i].prec - 1 + (image->comps[i].sgnd << 7);
334
335     if ((image->numcomps == 1 || image->numcomps == 3)
336             && (movie->tk[0].jp2_struct.bpc != 255)) {
337         movie->tk[0].jp2_struct.meth = 1;
338     } else {
339         movie->tk[0].jp2_struct.meth = 2;
340     }
341
342     if (image->numcomps == 1) {
343         movie->tk[0].jp2_struct.enumcs = 17;    /* Grayscale */
344     }
345
346     else if ((image->comps[0].dx == 1)
347              && (image->comps[1].dx == 1)
348              && (image->comps[2].dx == 1)
349              && (image->comps[0].dy == 1)
350              && (image->comps[1].dy == 1)
351              && (image->comps[2].dy == 1)) {
352         movie->tk[0].jp2_struct.enumcs = 16;    /* RGB */
353     }
354
355     else if ((image->comps[0].dx == 1)
356              && (image->comps[1].dx == 2)
357              && (image->comps[2].dx == 2)
358              && (image->comps[0].dy == 1)
359              && (image->comps[1].dy == 2)
360              && (image->comps[2].dy == 2)) {
361         movie->tk[0].jp2_struct.enumcs = 18;    /* YUV */
362     }
363
364     else {
365         movie->tk[0].jp2_struct.enumcs = 0;    /* Unknown profile */
366     }
367 }
368
369 int main(int argc, char *argv[])
370 {
371     opj_cinfo_t* cinfo;
372     opj_event_mgr_t event_mgr;      /* event manager */
373     unsigned int snum;
374     opj_mj2_t *movie;
375     mj2_sample_t *sample;
376     unsigned char* frame_codestream;
377     FILE *mj2file, *j2kfile;
378     char *j2kfilename;
379     unsigned char *buf;
380     int offset, mdat_initpos;
381     opj_image_t img;
382     opj_cio_t *cio;
383     mj2_cparameters_t parameters;
384
385     if (argc != 3) {
386         printf("Usage: %s source_location mj2_filename\n", argv[0]);
387         printf("Example: %s input/input output.mj2\n", argv[0]);
388         return 1;
389     }
390
391     mj2file = fopen(argv[2], "wb");
392
393     if (!mj2file) {
394         fprintf(stderr, "failed to open %s for writing\n", argv[2]);
395         return 1;
396     }
397     memset(&img, 0, sizeof(opj_image_t));
398     /*
399     configure the event callbacks (not required)
400     setting of each callback is optionnal
401     */
402     memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
403     event_mgr.error_handler = error_callback;
404     event_mgr.warning_handler = warning_callback;
405     event_mgr.info_handler = info_callback;
406
407     /* get a MJ2 decompressor handle */
408     cinfo = mj2_create_compress();
409
410     /* catch events using our callbacks and give a local context */
411     opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
412
413     /* setup the decoder encoding parameters using user parameters */
414     memset(&parameters, 0, sizeof(mj2_cparameters_t));
415     movie = (opj_mj2_t*) cinfo->mj2_handle;
416
417     j2kfilename = (char*)malloc(strlen(argv[1]) + 12);/* max. '%6d' */
418     sprintf(j2kfilename, "%s_00001.j2k", argv[1]);
419
420     if (test_image(j2kfilename, &parameters) == 0) {
421         goto fin;
422     }
423
424     parameters.frame_rate = 25; /* DEFAULT */
425
426     mj2_setup_encoder(movie, &parameters);
427
428
429     /* Writing JP, FTYP and MDAT boxes
430     Assuming that the JP and FTYP boxes won't be longer than 300 bytes */
431
432     buf = (unsigned char*) malloc(300 * sizeof(unsigned char));
433     cio = opj_cio_open(movie->cinfo, buf, 300);
434     mj2_write_jp(cio);
435     mj2_write_ftyp(movie, cio);
436     mdat_initpos = cio_tell(cio);
437     cio_skip(cio, 4);
438     cio_write(cio, MJ2_MDAT, 4);
439     fwrite(buf, cio_tell(cio), 1, mj2file);
440     free(buf);
441
442     /* Insert each j2k codestream in a JP2C box */
443     snum = 0;
444     offset = 0;
445     while (1) {
446         mj2_sample_t * new_sample;
447         mj2_chunk_t * new_chunk;
448         sample = &movie->tk[0].sample[snum];
449         sprintf(j2kfilename, "%s_%05d.j2k", argv[1], snum);
450         j2kfile = fopen(j2kfilename, "rb");
451         if (!j2kfile) {
452             if (snum == 0) { /* Could not open a single codestream */
453                 fprintf(stderr, "failed to open %s for reading\n", j2kfilename);
454                 return 1;
455             } else {        /* Tried to open a inexistant codestream */
456                 fprintf(stdout, "%d frames are being added to the MJ2 file\n", snum);
457                 break;
458             }
459         }
460
461         /* Calculating offset for samples and chunks */
462         offset += cio_tell(cio);
463         sample->offset = offset;
464         movie->tk[0].chunk[snum].offset =
465             offset;  /* There will be one sample per chunk */
466
467         /* Calculating sample size */
468         fseek(j2kfile, 0, SEEK_END);
469         sample->sample_size = ftell(j2kfile) +
470                               8; /* Sample size is codestream + JP2C box header */
471         fseek(j2kfile, 0, SEEK_SET);
472
473         /* Reading siz marker of j2k image for the first codestream */
474         if (snum == 0) {
475             read_siz_marker(j2kfile, &img);
476         }
477
478         /* Writing JP2C box header */
479         frame_codestream = (unsigned char*) malloc(sample->sample_size + 8);
480         cio = opj_cio_open(movie->cinfo, frame_codestream, sample->sample_size);
481         cio_write(cio, sample->sample_size, 4); /* Sample size */
482         cio_write(cio, JP2_JP2C, 4); /* JP2C */
483
484         /* Writing codestream from J2K file to MJ2 file */
485         fread(frame_codestream + 8, sample->sample_size - 8, 1, j2kfile);
486         fwrite(frame_codestream, sample->sample_size, 1, mj2file);
487         cio_skip(cio, sample->sample_size - 8);
488
489         /* Ending loop */
490         fclose(j2kfile);
491         snum++;
492         new_sample = (mj2_sample_t*)
493                      realloc(movie->tk[0].sample, (snum + 1) * sizeof(mj2_sample_t));
494         new_chunk = (mj2_chunk_t*)
495                     realloc(movie->tk[0].chunk, (snum + 1) * sizeof(mj2_chunk_t));
496         if (new_sample && new_chunk) {
497             movie->tk[0].sample = new_sample;
498             movie->tk[0].chunk = new_chunk;
499         } else {
500             fprintf(stderr, "Failed to allocate enough memory to read %s\n", j2kfilename);
501             return 1;
502         }
503         free(frame_codestream);
504     }
505
506     /* Writing the MDAT box length in header */
507     offset += cio_tell(cio);
508     buf = (unsigned char*) malloc(4 * sizeof(unsigned char));
509     cio = opj_cio_open(movie->cinfo, buf, 4);
510     cio_write(cio, offset - mdat_initpos, 4);
511     fseek(mj2file, (long)mdat_initpos, SEEK_SET);
512     fwrite(buf, 4, 1, mj2file);
513     fseek(mj2file, 0, SEEK_END);
514     free(buf);
515
516     /* Setting movie parameters */
517     movie->tk[0].num_samples = snum;
518     movie->tk[0].num_chunks = snum;
519     setparams(movie, &img);
520
521     /* Writing MOOV box */
522     buf = (unsigned char*) malloc((TEMP_BUF + snum * 20) * sizeof(unsigned char));
523     cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF + snum * 20));
524     mj2_write_moov(movie, cio);
525     fwrite(buf, cio_tell(cio), 1, mj2file);
526
527     /* Ending program */
528     free(img.comps);
529     opj_cio_close(cio);
530
531 fin:
532     fclose(mj2file);
533     mj2_destroy_compress(movie);
534     free(j2kfilename);
535
536     return 0;
537 }