Blame src/lib/openmj2/mj2_convert.c

Packit caffb5
/*
Packit caffb5
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
Packit caffb5
* Copyright (c) 2002-2014, Professor Benoit Macq
Packit caffb5
* Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
Packit caffb5
* All rights reserved.
Packit caffb5
*
Packit caffb5
* Redistribution and use in source and binary forms, with or without
Packit caffb5
* modification, are permitted provided that the following conditions
Packit caffb5
* are met:
Packit caffb5
* 1. Redistributions of source code must retain the above copyright
Packit caffb5
*    notice, this list of conditions and the following disclaimer.
Packit caffb5
* 2. Redistributions in binary form must reproduce the above copyright
Packit caffb5
*    notice, this list of conditions and the following disclaimer in the
Packit caffb5
*    documentation and/or other materials provided with the distribution.
Packit caffb5
*
Packit caffb5
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
Packit caffb5
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit caffb5
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit caffb5
* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit caffb5
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit caffb5
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit caffb5
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit caffb5
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit caffb5
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit caffb5
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit caffb5
* POSSIBILITY OF SUCH DAMAGE.
Packit caffb5
*/
Packit caffb5
Packit caffb5
#include "opj_includes.h"
Packit caffb5
#include "mj2_convert.h"
Packit caffb5
Packit caffb5
/*  -----------------------       */
Packit caffb5
/*                    */
Packit caffb5
/*                    */
Packit caffb5
/*  Count the number of frames        */
Packit caffb5
/*  in a YUV file             */
Packit caffb5
/*                    */
Packit caffb5
/*  -----------------------       */
Packit caffb5
Packit caffb5
unsigned int OPJ_CALLCONV yuv_num_frames(mj2_tk_t * tk, char *infile)
Packit caffb5
{
Packit caffb5
    unsigned int prec_size;
Packit caffb5
    long end_of_f, frame_size;
Packit caffb5
    FILE *f;
Packit caffb5
Packit caffb5
    f = fopen(infile, "rb");
Packit caffb5
    if (!f) {
Packit caffb5
        fprintf(stderr, "failed to open %s for reading\n", infile);
Packit caffb5
        return 0;
Packit caffb5
    }
Packit caffb5
    prec_size = (tk->depth + 7) / 8; /* bytes of precision */
Packit caffb5
Packit caffb5
    frame_size = (long)(tk->w * tk->h * (1.0 + (double) 2 / (double)(
Packit caffb5
            tk->CbCr_subsampling_dx *
Packit caffb5
            tk->CbCr_subsampling_dy)));  /* Calculate frame size */
Packit caffb5
    frame_size *= prec_size;
Packit caffb5
Packit caffb5
    fseek(f, 0, SEEK_END);
Packit caffb5
    end_of_f = ftell(f);      /* Calculate file size */
Packit caffb5
Packit caffb5
    if (end_of_f < frame_size) {
Packit caffb5
        fprintf(stderr,
Packit caffb5
                "YUV does not contains any frame of %d x %d size\n", tk->w,
Packit caffb5
                tk->h);
Packit caffb5
        return 0;
Packit caffb5
    }
Packit caffb5
    fclose(f);
Packit caffb5
Packit caffb5
    return (unsigned int)(end_of_f / frame_size);
Packit caffb5
}
Packit caffb5
Packit caffb5
/*  ----------------------- */
Packit caffb5
/* */
Packit caffb5
/* */
Packit caffb5
/*  YUV to IMAGE */
Packit caffb5
/* */
Packit caffb5
/*  ----------------------- */
Packit caffb5
Packit caffb5
opj_image_t * OPJ_CALLCONV mj2_image_create(mj2_tk_t * tk,
Packit caffb5
        opj_cparameters_t *parameters)
Packit caffb5
{
Packit caffb5
    opj_image_cmptparm_t cmptparm[3];
Packit caffb5
    opj_image_t * img;
Packit caffb5
    int i;
Packit caffb5
    int numcomps = 3;
Packit caffb5
    int subsampling_dx = parameters->subsampling_dx;
Packit caffb5
    int subsampling_dy = parameters->subsampling_dy;
Packit caffb5
Packit caffb5
    /* initialize image components */
Packit caffb5
    memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
Packit caffb5
    for (i = 0; i < numcomps; i++) {
Packit caffb5
        cmptparm[i].prec = tk->depth;
Packit caffb5
        cmptparm[i].bpp = tk->depth;
Packit caffb5
        cmptparm[i].sgnd = 0;
Packit caffb5
        cmptparm[i].dx = i ? subsampling_dx * tk->CbCr_subsampling_dx : subsampling_dx;
Packit caffb5
        cmptparm[i].dy = i ? subsampling_dy * tk->CbCr_subsampling_dy : subsampling_dy;
Packit caffb5
        cmptparm[i].w = tk->w;
Packit caffb5
        cmptparm[i].h = tk->h;
Packit caffb5
    }
Packit caffb5
    /* create the image */
Packit caffb5
    img = opj_image_create(numcomps, cmptparm, CLRSPC_SRGB);
Packit caffb5
    return img;
Packit caffb5
}
Packit caffb5
Packit caffb5
char OPJ_CALLCONV yuvtoimage(mj2_tk_t * tk, opj_image_t * img, int frame_num,
Packit caffb5
                             opj_cparameters_t *parameters, char* infile)
Packit caffb5
{
Packit caffb5
    int i, compno;
Packit caffb5
    int offset, size, max, prec_bytes, is_16, v;
Packit caffb5
    long end_of_f, position;
Packit caffb5
    int numcomps = 3;
Packit caffb5
    int subsampling_dx = parameters->subsampling_dx;
Packit caffb5
    int subsampling_dy = parameters->subsampling_dy;
Packit caffb5
    FILE *yuvfile;
Packit caffb5
    int *data;
Packit caffb5
    unsigned char uc;
Packit caffb5
Packit caffb5
    yuvfile = fopen(infile, "rb");
Packit caffb5
    if (!yuvfile) {
Packit caffb5
        fprintf(stderr, "failed to open %s for readings\n", parameters->infile);
Packit caffb5
        return 1;
Packit caffb5
    }
Packit caffb5
    is_16 = (tk->depth > 8);
Packit caffb5
    prec_bytes = (is_16 ? 2 : 1);
Packit caffb5
Packit caffb5
    offset = (int)((double)(frame_num * tk->w * tk->h) * (1.0 +
Packit caffb5
                   1.0 * (double) 2 / (double)(tk->CbCr_subsampling_dx *
Packit caffb5
                           tk->CbCr_subsampling_dy)));
Packit caffb5
    offset *= prec_bytes;
Packit caffb5
Packit caffb5
    fseek(yuvfile, 0, SEEK_END);
Packit caffb5
    end_of_f = ftell(yuvfile);
Packit caffb5
    fseek(yuvfile, sizeof(unsigned char) * offset, SEEK_SET);
Packit caffb5
    position = ftell(yuvfile);
Packit caffb5
    if (position >= end_of_f) {
Packit caffb5
        fprintf(stderr, "Cannot reach frame number %d in yuv file !!\n",
Packit caffb5
                frame_num);
Packit caffb5
        fclose(yuvfile);
Packit caffb5
        return 1;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    img->x0 = tk->Dim[0];
Packit caffb5
    img->y0 = tk->Dim[1];
Packit caffb5
    img->x1 = !tk->Dim[0] ? (tk->w - 1) * subsampling_dx + 1 : tk->Dim[0] +
Packit caffb5
              (tk->w - 1) * subsampling_dx + 1;
Packit caffb5
    img->y1 = !tk->Dim[1] ? (tk->h - 1) * subsampling_dy + 1 : tk->Dim[1] +
Packit caffb5
              (tk->h - 1) * subsampling_dy + 1;
Packit caffb5
Packit caffb5
    size = tk->w * tk->h * prec_bytes;
Packit caffb5
Packit caffb5
    for (compno = 0; compno < numcomps; compno++) {
Packit caffb5
        max = size / (img->comps[compno].dx * img->comps[compno].dy);
Packit caffb5
        data = img->comps[compno].data;
Packit caffb5
Packit caffb5
        for (i = 0; i < max && !feof(yuvfile); i++) {
Packit caffb5
            v = 0;
Packit caffb5
            fread(&uc, 1, 1, yuvfile);
Packit caffb5
            v = uc;
Packit caffb5
Packit caffb5
            if (is_16) {
Packit caffb5
                fread(&uc, 1, 1, yuvfile);
Packit caffb5
                v |= (uc << 8);
Packit caffb5
            }
Packit caffb5
            *data++ = v;
Packit caffb5
        }
Packit caffb5
    }
Packit caffb5
    fclose(yuvfile);
Packit caffb5
Packit caffb5
    return 0;
Packit caffb5
}
Packit caffb5
Packit caffb5
Packit caffb5
Packit caffb5
/*  ----------------------- */
Packit caffb5
/* */
Packit caffb5
/* */
Packit caffb5
/*  IMAGE to YUV */
Packit caffb5
/* */
Packit caffb5
/*  ----------------------- */
Packit caffb5
Packit caffb5
Packit caffb5
opj_bool OPJ_CALLCONV imagetoyuv(opj_image_t * img, char *outfile)
Packit caffb5
{
Packit caffb5
    FILE *f;
Packit caffb5
    int *data;
Packit caffb5
    int i, v, is_16, prec_bytes;
Packit caffb5
    unsigned char buf[2];
Packit caffb5
Packit caffb5
    if (img->numcomps == 3) {
Packit caffb5
        if (img->comps[0].dx != img->comps[1].dx / 2
Packit caffb5
                || img->comps[1].dx != img->comps[2].dx) {
Packit caffb5
            fprintf(stderr,
Packit caffb5
                    "Error with the input image components size: cannot create yuv file)\n");
Packit caffb5
            return OPJ_FALSE;
Packit caffb5
        }
Packit caffb5
    } else if (!(img->numcomps == 1)) {
Packit caffb5
        fprintf(stderr,
Packit caffb5
                "Error with the number of image components(must be one or three)\n");
Packit caffb5
        return OPJ_FALSE;
Packit caffb5
    }
Packit caffb5
Packit caffb5
    f = fopen(outfile, "a+b");
Packit caffb5
    if (!f) {
Packit caffb5
        fprintf(stderr, "failed to open %s for writing\n", outfile);
Packit caffb5
        return OPJ_FALSE;
Packit caffb5
    }
Packit caffb5
    is_16 = (img->comps[0].prec > 8);
Packit caffb5
    prec_bytes = (is_16 ? 2 : 1);
Packit caffb5
    data = img->comps[0].data;
Packit caffb5
Packit caffb5
    for (i = 0; i < (img->comps[0].w * img->comps[0].h); i++) {
Packit caffb5
        v = *data++;
Packit caffb5
        buf[0] = (unsigned char)v;
Packit caffb5
Packit caffb5
        if (is_16) {
Packit caffb5
            buf[1] = (unsigned char)(v >> 8);
Packit caffb5
        }
Packit caffb5
Packit caffb5
        fwrite(buf, 1, prec_bytes, f);
Packit caffb5
    }
Packit caffb5
Packit caffb5
Packit caffb5
    if (img->numcomps == 3) {
Packit caffb5
        data = img->comps[1].data;
Packit caffb5
Packit caffb5
        for (i = 0; i < (img->comps[1].w * img->comps[1].h); i++) {
Packit caffb5
            v = *data++;
Packit caffb5
            buf[0] = (unsigned char)v;
Packit caffb5
Packit caffb5
            if (is_16) {
Packit caffb5
                buf[1] = (unsigned char)(v >> 8);
Packit caffb5
            }
Packit caffb5
Packit caffb5
            fwrite(buf, 1, prec_bytes, f);
Packit caffb5
        }
Packit caffb5
        data = img->comps[2].data;
Packit caffb5
Packit caffb5
        for (i = 0; i < (img->comps[2].w * img->comps[2].h); i++) {
Packit caffb5
            v = *data++;
Packit caffb5
            buf[0] = (unsigned char)v;
Packit caffb5
Packit caffb5
            if (is_16) {
Packit caffb5
                buf[1] = (unsigned char)(v >> 8);
Packit caffb5
            }
Packit caffb5
Packit caffb5
            fwrite(buf, 1, prec_bytes, f);
Packit caffb5
        }
Packit caffb5
    } else if (img->numcomps == 1) {
Packit caffb5
        /* fake CbCr values */
Packit caffb5
        if (is_16) {
Packit caffb5
            buf[0] = 255;
Packit caffb5
            if (img->comps[0].prec == 10) {
Packit caffb5
                buf[1] = 1;
Packit caffb5
            } else if (img->comps[0].prec == 12) {
Packit caffb5
                buf[1] = 3;
Packit caffb5
            } else {
Packit caffb5
                buf[1] = 125;
Packit caffb5
            }
Packit caffb5
        } else {
Packit caffb5
            buf[0] = 125;
Packit caffb5
        }
Packit caffb5
Packit caffb5
        for (i = 0; i < (img->comps[0].w * img->comps[0].h * 0.25); i++) {
Packit caffb5
            fwrite(buf, 1, prec_bytes, f);
Packit caffb5
        }
Packit caffb5
Packit caffb5
Packit caffb5
        for (i = 0; i < (img->comps[0].w * img->comps[0].h * 0.25); i++) {
Packit caffb5
            fwrite(buf, 1, prec_bytes, f);
Packit caffb5
        }
Packit caffb5
    }
Packit caffb5
    fclose(f);
Packit caffb5
    return OPJ_TRUE;
Packit caffb5
}
Packit caffb5
Packit caffb5
/*  ----------------------- */
Packit caffb5
/* */
Packit caffb5
/* */
Packit caffb5
/*  IMAGE to BMP */
Packit caffb5
/* */
Packit caffb5
/*  ----------------------- */
Packit caffb5
Packit caffb5
int OPJ_CALLCONV imagetobmp(opj_image_t * img, char *outfile)
Packit caffb5
{
Packit caffb5
    int w, wr, h, hr, i, pad;
Packit caffb5
    FILE *f;
Packit caffb5
Packit caffb5
    if (img->numcomps == 3 && img->comps[0].dx == img->comps[1].dx
Packit caffb5
            && img->comps[1].dx == img->comps[2].dx
Packit caffb5
            && img->comps[0].dy == img->comps[1].dy
Packit caffb5
            && img->comps[1].dy == img->comps[2].dy
Packit caffb5
            && img->comps[0].prec == img->comps[1].prec
Packit caffb5
            && img->comps[1].prec == img->comps[2].prec) {
Packit caffb5
        /* -->> -->> -->> -->>
Packit caffb5
Packit caffb5
          24 bits color
Packit caffb5
Packit caffb5
        <<-- <<-- <<-- <<-- */
Packit caffb5
Packit caffb5
        f = fopen(outfile, "wb");
Packit caffb5
        if (!f) {
Packit caffb5
            fprintf(stderr, "failed to open %s for writing\n", outfile);
Packit caffb5
            return 1;
Packit caffb5
        }
Packit caffb5
Packit caffb5
        w = img->comps[0].w;
Packit caffb5
        wr = int_ceildivpow2(img->comps[0].w, img->comps[0].factor);
Packit caffb5
Packit caffb5
        h = img->comps[0].h;
Packit caffb5
        hr = int_ceildivpow2(img->comps[0].h, img->comps[0].factor);
Packit caffb5
Packit caffb5
        fprintf(f, "BM");
Packit caffb5
Packit caffb5
        /* FILE HEADER */
Packit caffb5
        /* ------------- */
Packit caffb5
        fprintf(f, "%c%c%c%c",
Packit caffb5
                (unsigned char)(hr * wr * 3 + 3 * hr * (wr % 2) +
Packit caffb5
                                54) & 0xff,
Packit caffb5
                (unsigned char)((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
Packit caffb5
                                >> 8) & 0xff,
Packit caffb5
                (unsigned char)((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
Packit caffb5
                                >> 16) & 0xff,
Packit caffb5
                (unsigned char)((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
Packit caffb5
                                >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
Packit caffb5
                ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,
Packit caffb5
                ((54) >> 16) & 0xff, ((54) >> 24) & 0xff);
Packit caffb5
Packit caffb5
        /* INFO HEADER   */
Packit caffb5
        /* ------------- */
Packit caffb5
        fprintf(f, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff,
Packit caffb5
                ((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (unsigned char)((wr) & 0xff),
Packit caffb5
                (unsigned char)((wr) >> 8) & 0xff,
Packit caffb5
                (unsigned char)((wr) >> 16) & 0xff,
Packit caffb5
                (unsigned char)((wr) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (unsigned char)((hr) & 0xff),
Packit caffb5
                (unsigned char)((hr) >> 8) & 0xff,
Packit caffb5
                (unsigned char)((hr) >> 16) & 0xff,
Packit caffb5
                (unsigned char)((hr) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
Packit caffb5
        fprintf(f, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
Packit caffb5
                ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c",
Packit caffb5
                (unsigned char)(3 * hr * wr +
Packit caffb5
                                3 * hr * (wr % 2)) & 0xff,
Packit caffb5
                (unsigned char)((hr * wr * 3 + 3 * hr * (wr % 2)) >>
Packit caffb5
                                8) & 0xff,
Packit caffb5
                (unsigned char)((hr * wr * 3 + 3 * hr * (wr % 2)) >>
Packit caffb5
                                16) & 0xff,
Packit caffb5
                (unsigned char)((hr * wr * 3 + 3 * hr * (wr % 2)) >>
Packit caffb5
                                24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
Packit caffb5
                ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
Packit caffb5
                ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
Packit caffb5
                ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
Packit caffb5
        fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
Packit caffb5
                ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
Packit caffb5
Packit caffb5
        for (i = 0; i < wr * hr; i++) {
Packit caffb5
            unsigned char R, G, B;
Packit caffb5
            /* a modifier */
Packit caffb5
            /* R = img->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];*/
Packit caffb5
            R = img->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
Packit caffb5
            /* G = img->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];*/
Packit caffb5
            G = img->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
Packit caffb5
            /* B = img->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];*/
Packit caffb5
            B = img->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
Packit caffb5
            fprintf(f, "%c%c%c", B, G, R);
Packit caffb5
Packit caffb5
            if ((i + 1) % wr == 0) {
Packit caffb5
                for (pad = (3 * wr) % 4 ? 4 - (3 * wr) % 4 : 0; pad > 0; pad--) { /* ADD */
Packit caffb5
                    fprintf(f, "%c", 0);
Packit caffb5
                }
Packit caffb5
            }
Packit caffb5
        }
Packit caffb5
        fclose(f);
Packit caffb5
    }
Packit caffb5
    return 0;
Packit caffb5
}