cc_composite_template_body.h 7.39 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* -*- c -*- *******************************************************/
/*
 * Copyright (C) 2011 Sandia Corporation
 * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 * the U.S. Government retains certain rights in this software.
 *
 * This source code is released under the New BSD License.
 */

/* This is not a traditional header file, but rather a "macro" file that defines
 * a template for a decompression function.  (If this were C++, we would
 * actually use tempaltes.)  In general, there are many flavors of the
 * decompression functionality which differ only slightly.  Rather than maintain
 * lots of different code bases or try to debug big macros, we just include this
 * file with various parameters.
 *
 * The following macros must be defined:
18 19 20 21
 *      CCC_FRONT_COMPRESSED_IMAGE - compressed image to blend in front.
 *      CCC_BACK_COMPRESSED_IMAGE - compressed image to blend in back.
 *      CCC_DEST_COMPRESSED_IMAGE - the resulting compressed image buffer.
 *      CCC_COMPOSITE(front_pointer, back_pointer, dest_pointer) - given
22 23
 *              pointers to actual data in the three buffers, perform the
 *              actual compositing operation and increment the pointers.
24 25
 *      CCC_PIXEL_SIZE - the number of bytes required to store the data
 *              for one pixel.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
 *
 * All of the above macros are undefined at the end of this file.
 */

#ifndef ICET_IMAGE_DATA
#error Need ICET_IMAGE_DATA macro.  Is this included in image.c?
#endif
#ifndef INACTIVE_RUN_LENGTH
#error Need INACTIVE_RUN_LENGTH macro.  Is this included in image.c?
#endif
#ifndef ACTIVE_RUN_LENGTH
#error Need ACTIVE_RUN_LENGTH macro.  Is this included in image.c?
#endif

#define CCC_MIN(x, y) ((x) < (y) ? (x) : (y))

{
    /* Use IceTByte for byte-based pointer arithmetic. */
    const IceTByte *_front;
    const IceTByte *_back;
    IceTByte *_dest;
    IceTVoid *_dest_runlengths;
    IceTSizeType _num_pixels;
    IceTSizeType _pixel;
    IceTSizeType _front_num_inactive;
    IceTSizeType _front_num_active;
    IceTSizeType _back_num_inactive;
    IceTSizeType _back_num_active;
    IceTSizeType _dest_num_active;

56 57
    _num_pixels = icetSparseImageGetNumPixels(CCC_FRONT_COMPRESSED_IMAGE);
    if (_num_pixels != icetSparseImageGetNumPixels(CCC_BACK_COMPRESSED_IMAGE)) {
58 59 60
        icetRaiseError(ICET_SANITY_CHECK_FAIL,
                       "Input buffers do not agree for compressed-compressed"
                       " composite.");
61 62
    }
    icetSparseImageSetDimensions(
63 64 65
                           CCC_DEST_COMPRESSED_IMAGE,
                           icetSparseImageGetWidth(CCC_FRONT_COMPRESSED_IMAGE),
                           icetSparseImageGetHeight(CCC_BACK_COMPRESSED_IMAGE));
66

67 68 69
    _front = ICET_IMAGE_DATA(CCC_FRONT_COMPRESSED_IMAGE);
    _back = ICET_IMAGE_DATA(CCC_BACK_COMPRESSED_IMAGE);
    _dest = ICET_IMAGE_DATA(CCC_DEST_COMPRESSED_IMAGE);
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    _dest_runlengths = NULL;

    _pixel = 0;
    _front_num_inactive = _front_num_active = 0;
    _back_num_inactive = _back_num_active = 0;
    _dest_num_active = 0;
    while (_pixel < _num_pixels) {
        /* When num_active is 0, we have exhausted all active pixels and the
           buffer pointer must be pointing to run lengths. */
        while(   (_front_num_active == 0)
              && ((_front_num_inactive + _pixel) < _num_pixels) ) {
            _front_num_inactive += INACTIVE_RUN_LENGTH(_front);
            _front_num_active = ACTIVE_RUN_LENGTH(_front);
            _front += RUN_LENGTH_SIZE;
        }
        while(   (_back_num_active == 0)
              && ((_back_num_inactive + _pixel) < _num_pixels) ) {
            _back_num_inactive += INACTIVE_RUN_LENGTH(_back);
            _back_num_active = ACTIVE_RUN_LENGTH(_back);
            _back += RUN_LENGTH_SIZE;
        }

        {
            IceTSizeType _dest_num_inactive
                = CCC_MIN(_front_num_inactive, _back_num_inactive);
            if (_dest_num_inactive > 0) {
                /* Record active pixel count.  (Special case on first iteration
                 * where there is no runlength and no place to put it.) */
                if (_dest_runlengths != NULL) {
99
                    ACTIVE_RUN_LENGTH(_dest_runlengths) = _dest_num_active;
100
                    _dest_num_active = 0;
101 102 103
                }
                _dest_runlengths = _dest;
                _dest += RUN_LENGTH_SIZE;
104 105
                /* Handle inactive pixel region. */
                _pixel += _dest_num_inactive;
106 107
                _front_num_inactive -= _dest_num_inactive;
                _back_num_inactive -= _dest_num_inactive;
108
                INACTIVE_RUN_LENGTH(_dest_runlengths) = _dest_num_inactive;
109 110 111 112 113
            } else {
                /* Handle special case where first pixel is active. */
                if (_dest_runlengths == NULL) {
                    _dest_runlengths = _dest;
                    _dest += RUN_LENGTH_SIZE;
114
                    INACTIVE_RUN_LENGTH(_dest_runlengths) = 0;
115 116 117 118
                }
            }
        }

119 120 121 122 123 124 125 126 127 128 129 130 131
        /* At this point, either the front or back (or both) have no inactive
           pixels. */

        if ((0 < _front_num_inactive) && (0 < _back_num_active)) {
            IceTSizeType _num_to_copy
                = CCC_MIN(_front_num_inactive, _back_num_active);
            _front_num_inactive -= _num_to_copy;
            _back_num_active -= _num_to_copy;
            _dest_num_active += _num_to_copy;
            _pixel += _num_to_copy;
            memcpy(_dest, _back, CCC_PIXEL_SIZE*_num_to_copy);
            _dest += CCC_PIXEL_SIZE*_num_to_copy;
            _back += CCC_PIXEL_SIZE*_num_to_copy;
132 133
        }

134 135 136 137 138 139 140 141 142 143
        if ((0 < _back_num_inactive) && (0 < _front_num_active)) {
            IceTSizeType _num_to_copy
                = CCC_MIN(_back_num_inactive, _front_num_active);
            _back_num_inactive -= _num_to_copy;
            _front_num_active -= _num_to_copy;
            _dest_num_active += _num_to_copy;
            _pixel += _num_to_copy;
            memcpy(_dest, _front, CCC_PIXEL_SIZE*_num_to_copy);
            _dest += CCC_PIXEL_SIZE*_num_to_copy;
            _front += CCC_PIXEL_SIZE*_num_to_copy;
144 145 146
        }

        if ((_front_num_inactive == 0) && (_back_num_inactive == 0)) {
147 148 149 150 151 152 153
            IceTSizeType _num_to_composite
                = CCC_MIN(_front_num_active, _back_num_active);
            _front_num_active -= _num_to_composite;
            _back_num_active -= _num_to_composite;
            _dest_num_active += _num_to_composite;
            _pixel += _num_to_composite;
            for ( ; 0 < _num_to_composite; _num_to_composite--) {
154
                CCC_COMPOSITE(_front, _back, _dest);
155 156 157
            }
        }
    }
158 159

    if (_dest_runlengths != NULL) {
160
        ACTIVE_RUN_LENGTH(_dest_runlengths) = _dest_num_active;
161 162 163
    }

    if (_pixel != _num_pixels) {
164
        icetRaiseError(ICET_INVALID_VALUE, "Corrupt compressed image.");
165
    }
166 167 168 169

    {
        /* Compute the actual number of bytes used to store the image. */
        IceTPointerArithmetic _buffer_begin
170
            =(IceTPointerArithmetic)ICET_IMAGE_HEADER(CCC_DEST_COMPRESSED_IMAGE);
171 172 173
        IceTPointerArithmetic _buffer_end
            =(IceTPointerArithmetic)_dest;
        IceTPointerArithmetic _compressed_size = _buffer_end - _buffer_begin;
174
        ICET_IMAGE_HEADER(CCC_DEST_COMPRESSED_IMAGE)
175 176 177
            [ICET_IMAGE_ACTUAL_BUFFER_SIZE_INDEX]
            = (IceTInt)_compressed_size;
    }
178 179
}

180 181 182 183
#undef CCC_FRONT_COMPRESSED_IMAGE
#undef CCC_BACK_COMPRESSED_IMAGE
#undef CCC_DEST_COMPRESSED_IMAGE
#undef CCC_COMPOSITE
184
#undef CCC_PIXEL_SIZE