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

int eps_encode_grayscale_block ( unsigned char **  block,
int  W,
int  H,
int  w,
int  h,
int  x,
int  y,
unsigned char *  buf,
int *  buf_size,
char *  fb_id,
int  mode 
)

Encode a GRAYSCALE block

This function encodes a signle grayscale image block of size w by h pixels as block of type EPS_GRAYSCALE_BLOCK. It is assumed that the block is taken from the image of size W by H pixels at position (x, y). All these parameters should be consistent. The encoded data is stored in the buf of size buf_size.

Note:
The most surprising thing here is that you can choose almost any (see note below) buf_size you wish! Thus you can precisely control encoding bit-rate. This technique is called embedded coding. In a few words, any encoded prefix can be used to decode a whole image. So, you can safely truncate stream at any point.
The caller should allocate at least EPS_MIN_GRAYSCALE_BUF bytes for the buf.
On successful return, the value pointed by the buf_size will be overwritten with a real amount of bytes used in the buf (it will be less then or equal to the original buf_size value).
Depending on the mode parameter maximal block width or height is either EPS_MAX_BLOCK_SIZE (if mode = EPS_MODE_NORMAL) or EPS_MAX_BLOCK_SIZE + 1 (if mode = EPS_MODE_OTLPF).
There is no restrictions on the image size itself.
The caller should select a value for the fb_id parameter from the list generated by the eps_get_fb_info function.
The caller should not use orthogonal filterbanks with mode = EPS_MODE_OTLPF. Orthogonality type can be queried with the eps_get_fb_info function.
Parameters:
blockImage block
WImage width
HImage height
wBlock width
hBlock height
xBlock X coordinate
yBlock Y coordinate
bufBuffer
buf_sizeBuffer size
fb_idFilterbank ID
modeEither EPS_MODE_NORMAL or EPS_MODE_OTLPF
Returns:
The function returns either EPS_OK (the block is successfully encoded), or EPS_PARAM_ERROR (one or more parameters are incorrect) or EPS_UNSUPPORTED_FB (filterbank with specified fb_id not found).

Definition at line 601 of file libmain.c.

References analysis_2D(), CLIP, dc_level_shift(), EPS_MAX_BLOCK_SIZE, EPS_MIN_GRAYSCALE_BUF, EPS_MODE_NORMAL, EPS_MODE_OTLPF, EPS_OK, EPS_PARAM_ERROR, EPS_UNSUPPORTED_FB, extend_channel(), free_2D(), get_block_size(), get_fb(), malloc_2D(), MIN, ORTHOGONAL, round_channel(), speck_encode(), stuff_data(), filterbank_t_tag::type, and xmalloc().

{
    filterbank_t *fb;

    unsigned char *buf_next;
    int bytes_left;

    unsigned char *stuff_buf;
    int stuff_bytes;
    int stuff_max;
    int stuff_cut;

    coeff_t **pad_block;
    coeff_t **dwt_block;
    int **int_block;

    int speck_bytes;
    int block_size;
    int str_len;

    unsigned char dc_int;
    coeff_t dc;

    crc32_t hdr_crc;
    crc32_t data_crc;

    unsigned char *crc_pos;

    /* Sanity checks */
    if (!block || !buf || !buf_size || !fb_id) {
        return EPS_PARAM_ERROR;
    }

    /* Check input parameters for consistency */
    if ((mode != EPS_MODE_NORMAL) && (mode != EPS_MODE_OTLPF)) {
        return EPS_PARAM_ERROR;
    }

    if ((W <= 0) || (H <= 0)) {
        return EPS_PARAM_ERROR;
    }

    if ((w < 1) || (h < 1)) {
        return EPS_PARAM_ERROR;
    }

    if (w > EPS_MAX_BLOCK_SIZE + mode == EPS_MODE_OTLPF) {
        return EPS_PARAM_ERROR;
    }

    if (h > EPS_MAX_BLOCK_SIZE + mode == EPS_MODE_OTLPF) {
        return EPS_PARAM_ERROR;
    }

    if ((x < 0) || (y < 0)) {
        return EPS_PARAM_ERROR;
    }

    if ((x + w > W) || (y + h > H)) {
        return EPS_PARAM_ERROR;
    }

    if (*buf_size < EPS_MIN_GRAYSCALE_BUF) {
        return EPS_PARAM_ERROR;
    }

    /* Find filterbank from id */
    if (!(fb = get_fb(fb_id))) {
        return EPS_UNSUPPORTED_FB;
    }

    /* EPS_MODE_NORMAL is the only valid choise for orthogonal filters */
    if ((fb->type == ORTHOGONAL) && (mode != EPS_MODE_NORMAL)) {
        return EPS_PARAM_ERROR;
    }

    buf_next = buf;
    bytes_left = *buf_size;

    /* Compute block size */
    block_size = get_block_size(w, h, mode, 2);

    /* Extend block */
    pad_block = (coeff_t **) malloc_2D(block_size, block_size, sizeof(coeff_t));
    extend_channel(block, pad_block, w, h, block_size, block_size);

    /* DC level shift */
    dc = dc_level_shift(pad_block, block_size, block_size);
    dc_int = (unsigned char) CLIP(dc);

    /* Wavelet transform */
    dwt_block = (coeff_t **) malloc_2D(block_size, block_size, sizeof(coeff_t));
    analysis_2D(pad_block, dwt_block, block_size, mode, fb);
    free_2D((void *) pad_block, block_size, block_size);

    /* Round coefficients */
    int_block = (int **) malloc_2D(block_size, block_size, sizeof(int));
    round_channel(dwt_block, int_block, block_size);
    free_2D((void *) dwt_block, block_size, block_size);

    /* Write block header */
    str_len = snprintf((char *) buf_next, bytes_left,
        "type=gs;W=%d;H=%d;w=%d;h=%d;x=%d;y=%d;"
        "m=%d;dc=%d;fb=%s;",
        W, H, w, h, x, y, mode, dc_int, fb_id);

    assert(str_len < bytes_left);

    buf_next += str_len;
    bytes_left -= str_len;

    /* Compute and save block CRC */
    hdr_crc = epsilon_crc32(buf, str_len);
    hdr_crc = (hdr_crc ^ (hdr_crc >> 16)) & 0xffff;

    str_len = snprintf((char *) buf_next, bytes_left,
                       "chk=%04x;crc=????????;", hdr_crc);

    assert(str_len < bytes_left);

    buf_next += str_len;
    bytes_left -= str_len;

    crc_pos = buf_next - 9;

    /* Encode coefficients */
    speck_bytes = speck_encode(int_block, block_size,
                               buf_next, bytes_left);

    free_2D((void *) int_block, block_size, block_size);

    /* Byte stuffing */
    stuff_max = speck_bytes + speck_bytes / 254 + 1;
    stuff_buf = (unsigned char *) xmalloc(stuff_max);
    stuff_bytes = stuff_data(buf_next, stuff_buf, speck_bytes, stuff_max);

    assert(stuff_bytes >= speck_bytes);

    /* Cut encoded stream to fit it within available space */
    stuff_cut = MIN(bytes_left, stuff_bytes);
    memcpy(buf_next, stuff_buf, stuff_cut);

    free(stuff_buf);

    /* Compute and save data CRC */
    data_crc = epsilon_crc32(buf_next, stuff_cut);
    snprintf((char *) crc_pos, 9, "%08x", data_crc);
    crc_pos[8] = ';';

    buf_next += stuff_cut;
    bytes_left -= stuff_cut;

    /* Compute real amount of available bytes */
    *buf_size = buf_next - buf;

    return EPS_OK;
}

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index