Logo Search packages:      
Sourcecode: librasterlite version File versions  Download package

int eps_decode_truecolor_block ( unsigned char **  block_R,
unsigned char **  block_G,
unsigned char **  block_B,
unsigned char *  buf,
eps_block_header hdr 
)

Decode a TRUECOLOR block

This function decodes a TRUECOLOR image block from the buf. The resulted RGB data will be stored in the block_R, block_G, and block_B arrays respectively. Block and image dimensions as well as other necessary information is taken from the hdr structure filled by the eps_read_block_header function beforehand.

Note:
The caller should not invoke this function if the buf contains no data, i.e. eps_block_header::data_size = 0.
The caller should allocate block_R, block_G, and block_B arrays beforehand. Block dimensions as well as other information is available in the hdr structure.
Parameters:
block_RRed component
block_GGreen component
block_BBlue component
bufBuffer
hdrBlock header
Returns:
The function returns either EPS_OK (the block is successfully decoded), or EPS_PARAM_ERROR (one or more parameters are incorrect) or EPS_UNSUPPORTED_FB (filterbank used by encoder not found) or EPS_FORMAT_ERROR (unsupported data format).

Definition at line 1223 of file libmain.c.

References bilinear_resample_channel(), tc_hdr_tag::Cb_rt, clip_channel(), convert_YCbCr_to_RGB(), copy_channel(), tc_hdr_tag::Cr_rt, eps_block_header_tag::data_size, tc_hdr_tag::dc_Cb, tc_hdr_tag::dc_Cr, dc_level_unshift(), tc_hdr_tag::dc_Y, EPS_FORMAT_ERROR, EPS_MODE_OTLPF, EPS_OK, EPS_PARAM_ERROR, EPS_RESAMPLE_444, EPS_UNSUPPORTED_FB, extract_channel(), tc_hdr_tag::fb_id, free_2D(), get_block_size(), get_fb(), tc_hdr_tag::h, eps_block_header_tag::hdr_size, malloc_2D(), tc_hdr_tag::mode, tc_hdr_tag::resample, reset_RGB(), speck_decode(), split_channels(), synthesis_2D(), eps_block_header_tag::tc, unstuff_data(), tc_hdr_tag::w, xmalloc(), and tc_hdr_tag::Y_rt.

{
    filterbank_t *fb;

    unsigned char *unstuff_buf;
    int unstuff_bytes;

    unsigned char *buf_Y;
    unsigned char *buf_Cb;
    unsigned char *buf_Cr;
    unsigned char *buf_Cb_Cr;

    int speck_bytes_Y;
    int speck_bytes_Cb;
    int speck_bytes_Cr;
    int speck_bytes_Cb_Cr;

    int full_size;
    int half_size;

    int **int_block_Y;
    int **int_block_Cb;
    int **int_block_Cr;

    coeff_t **dwt_block_Y;
    coeff_t **dwt_block_Cb;
    coeff_t **dwt_block_Cr;

    coeff_t **pad_block_Y;
    coeff_t **pad_block_Cb;
    coeff_t **pad_block_Cr;

    coeff_t **pad_block_R;
    coeff_t **pad_block_G;
    coeff_t **pad_block_B;

    coeff_t **block_Y;
    coeff_t **block_Cb;
    coeff_t **block_Cr;

    int block_Y_size;
    int block_Cb_size;
    int block_Cr_size;

    unsigned char dc_Y_int;
    unsigned char dc_Cb_int;
    unsigned char dc_Cr_int;

    /* Sanity checks */
    if (!block_R || !block_G || !block_B) {
        return EPS_PARAM_ERROR;
    }

    if (!buf || !hdr) {
        return EPS_PARAM_ERROR;
    }

    if (hdr->data_size < 1) {
        return EPS_PARAM_ERROR;
    }

    /* Reset RGB channels */
    reset_RGB(block_R, block_G, block_B, hdr->tc.w, hdr->tc.h);

    /* Find filterbank by id */
    if (!hdr->tc.fb_id) {
        return EPS_UNSUPPORTED_FB;
    }

    fb = get_fb(hdr->tc.fb_id);
    assert(fb);

    /* Unstaff data */
    unstuff_buf = (unsigned char *) xmalloc(hdr->data_size *
        sizeof(unsigned char));

    unstuff_bytes = unstuff_data(buf + hdr->hdr_size, unstuff_buf,
        hdr->data_size, hdr->data_size);

    /* Consistency check */
    if (unstuff_bytes > hdr->tc.Y_rt + hdr->tc.Cb_rt + hdr->tc.Cr_rt) {
        free(unstuff_buf);
        return EPS_FORMAT_ERROR;
    }

    /* Dummy data */
    if (unstuff_bytes == 0) {
        unstuff_buf[0] = 0;
        unstuff_bytes = 1;
    }

    /* Allocate memory for Y and (Cb + Cr) channels */
    buf_Y = (unsigned char *) xmalloc(unstuff_bytes *
        sizeof(unsigned char));

    buf_Cb_Cr = (unsigned char *) xmalloc(unstuff_bytes *
        sizeof(unsigned char));

    /* Split stream into Y and (Cb + Cr) channels */
    split_channels(unstuff_buf, buf_Y, buf_Cb_Cr, unstuff_bytes,
                   hdr->tc.Y_rt, hdr->tc.Cb_rt + hdr->tc.Cr_rt,
                   &speck_bytes_Y, &speck_bytes_Cb_Cr);

    /* No longer needed */
    free(unstuff_buf);

    /* Consistency check */
    if (speck_bytes_Cb_Cr > hdr->tc.Cb_rt + hdr->tc.Cr_rt) {
        free(buf_Y);
        free(buf_Cb_Cr);
        return EPS_FORMAT_ERROR;
    }

    /* Dummy data */
    if (speck_bytes_Y == 0) {
        buf_Y[0] = 0;
        speck_bytes_Y = 1;
    }

    /* Dummy data */
    if (speck_bytes_Cb_Cr == 0) {
        buf_Cb_Cr[0] = 0;
        speck_bytes_Cb_Cr = 1;
    }

    /* Allocate memory for Cb and Cr channels */
    buf_Cb = (unsigned char *) xmalloc(speck_bytes_Cb_Cr *
        sizeof(unsigned char));

    buf_Cr = (unsigned char *) xmalloc(speck_bytes_Cb_Cr *
        sizeof(unsigned char));

    /* Split merged (Cb + Cr) channel into Cb and Cr channels */
    split_channels(buf_Cb_Cr, buf_Cb, buf_Cr, speck_bytes_Cb_Cr,
                   hdr->tc.Cb_rt, hdr->tc.Cr_rt,
                   &speck_bytes_Cb, &speck_bytes_Cr);

    /* No longer needed */
    free(buf_Cb_Cr);

    /* Dummy data */
    if (speck_bytes_Cb == 0) {
        buf_Cb[0] = 0;
        speck_bytes_Cb = 1;
    }

    /* Dummy data */
    if (speck_bytes_Cr == 0) {
        buf_Cr[0] = 0;
        speck_bytes_Cr = 1;
    }

    /* Compute block sizes for full and resampled channels */
    full_size = get_block_size(hdr->tc.w, hdr->tc.h, hdr->tc.mode, 4);
    half_size = full_size / 2 + (hdr->tc.mode == EPS_MODE_OTLPF);

    if (hdr->tc.resample == EPS_RESAMPLE_444) {
        block_Y_size = full_size;
        block_Cb_size = full_size;
        block_Cr_size = full_size;
    } else {
        block_Y_size = full_size;
        block_Cb_size = half_size;
        block_Cr_size = half_size;
    }

    /* Allocate memory for Y,Cb,Cr channels */
    int_block_Y = (int **) malloc_2D(block_Y_size, block_Y_size,
        sizeof(int));
    int_block_Cb = (int **) malloc_2D(block_Cb_size, block_Cb_size,
        sizeof(int));
    int_block_Cr = (int **) malloc_2D(block_Cr_size, block_Cr_size,
        sizeof(int));

    /* Decode data */
    speck_decode(buf_Y, speck_bytes_Y, int_block_Y, block_Y_size);
    speck_decode(buf_Cb, speck_bytes_Cb, int_block_Cb, block_Cb_size);
    speck_decode(buf_Cr, speck_bytes_Cr, int_block_Cr, block_Cr_size);

    /* No longer needed */
    free(buf_Y);
    free(buf_Cb);
    free(buf_Cr);

    /* Allocate memory for real-valued wavelet coefficients */
    dwt_block_Y = (coeff_t **) malloc_2D(block_Y_size, block_Y_size,
        sizeof(coeff_t));
    dwt_block_Cb = (coeff_t **) malloc_2D(block_Cb_size, block_Cb_size,
        sizeof(coeff_t));
    dwt_block_Cr = (coeff_t **) malloc_2D(block_Cr_size, block_Cr_size,
        sizeof(coeff_t));

    /* Copy data with type extension */
    copy_channel(int_block_Y, dwt_block_Y, block_Y_size);
    copy_channel(int_block_Cb, dwt_block_Cb, block_Cb_size);
    copy_channel(int_block_Cr, dwt_block_Cr, block_Cr_size);

    /* No longer needed */
    free_2D((void *) int_block_Y, block_Y_size, block_Y_size);
    free_2D((void *) int_block_Cb, block_Cb_size, block_Cb_size);
    free_2D((void *) int_block_Cr, block_Cr_size, block_Cr_size);

    /* Allocate memory for restored Y,Cb,Cr channels */
    block_Y = (coeff_t **) malloc_2D(block_Y_size, block_Y_size,
        sizeof(coeff_t));
    block_Cb = (coeff_t **) malloc_2D(block_Cb_size, block_Cb_size,
        sizeof(coeff_t));
    block_Cr = (coeff_t **) malloc_2D(block_Cr_size, block_Cr_size,
        sizeof(coeff_t));

    /* Inverse wavelet transform */
    synthesis_2D(dwt_block_Y, block_Y, block_Y_size, hdr->tc.mode, fb);
    synthesis_2D(dwt_block_Cb, block_Cb, block_Cb_size, hdr->tc.mode, fb);
    synthesis_2D(dwt_block_Cr, block_Cr, block_Cr_size, hdr->tc.mode, fb);

    /* No longer needed */
    free_2D((void *) dwt_block_Y, block_Y_size, block_Y_size);
    free_2D((void *) dwt_block_Cb, block_Cb_size, block_Cb_size);
    free_2D((void *) dwt_block_Cr, block_Cr_size, block_Cr_size);

    /* Get DC values */
    dc_Y_int = (unsigned char) hdr->tc.dc_Y;
    dc_Cb_int = (unsigned char) hdr->tc.dc_Cb;
    dc_Cr_int = (unsigned char) hdr->tc.dc_Cr;

    /* DC level unshift */
    dc_level_unshift(block_Y, (coeff_t) dc_Y_int,
        block_Y_size, block_Y_size);
    dc_level_unshift(block_Cb, (coeff_t) dc_Cb_int,
        block_Cb_size, block_Cb_size);
    dc_level_unshift(block_Cr, (coeff_t) dc_Cr_int,
        block_Cr_size, block_Cr_size);

    if (hdr->tc.resample == EPS_RESAMPLE_444) {
        /* No upsampling */
        pad_block_Y = block_Y;
        pad_block_Cb = block_Cb;
        pad_block_Cr = block_Cr;
    } else {
        pad_block_Y = block_Y;

        /* Allocate memory for full-sized Cb and Cr channels */
        pad_block_Cb = (coeff_t **) malloc_2D(full_size, full_size,
            sizeof(coeff_t));

        pad_block_Cr = (coeff_t **) malloc_2D(full_size, full_size,
            sizeof(coeff_t));

        /* Upsample Cb and Cr channels according to 4:2:0 scheme */
        bilinear_resample_channel(block_Cb, pad_block_Cb,
                                  block_Cb_size, block_Cb_size,
                                  full_size, full_size);

        bilinear_resample_channel(block_Cr, pad_block_Cr,
                                  block_Cr_size, block_Cr_size,
                                  full_size, full_size);

        /* No longer needed */
        free_2D((void *) block_Cb, block_Cb_size, block_Cb_size);
        free_2D((void *) block_Cr, block_Cr_size, block_Cr_size);
    }

    /* Allocate memory for extended R,G,B channels */
    pad_block_R = (coeff_t **) malloc_2D(full_size, full_size,
        sizeof(coeff_t));
    pad_block_G = (coeff_t **) malloc_2D(full_size, full_size,
        sizeof(coeff_t));
    pad_block_B = (coeff_t **) malloc_2D(full_size, full_size,
        sizeof(coeff_t));

    /* Convert from Y,Cb,Cr to R,G,B color space */
    convert_YCbCr_to_RGB(pad_block_Y, pad_block_Cb, pad_block_Cr,
                         pad_block_R, pad_block_G, pad_block_B,
                         full_size, full_size);

    /* No longer needed */
    free_2D((void *) pad_block_Y, full_size, full_size);
    free_2D((void *) pad_block_Cb, full_size, full_size);
    free_2D((void *) pad_block_Cr, full_size, full_size);

    /* Clip R,G,B channels */
    clip_channel(pad_block_R, full_size, full_size);
    clip_channel(pad_block_G, full_size, full_size);
    clip_channel(pad_block_B, full_size, full_size);

    /* Extract original data from R,G,B channels */
    extract_channel(pad_block_R, block_R,
                    full_size, full_size,
                    hdr->tc.w, hdr->tc.h);

    extract_channel(pad_block_G, block_G,
                    full_size, full_size,
                    hdr->tc.w, hdr->tc.h);

    extract_channel(pad_block_B, block_B,
                    full_size, full_size,
                    hdr->tc.w, hdr->tc.h);

    /* No longer needed */
    free_2D((void *) pad_block_R, full_size, full_size);
    free_2D((void *) pad_block_G, full_size, full_size);
    free_2D((void *) pad_block_B, full_size, full_size);

    return EPS_OK;
}

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index