C++程序  |  117行  |  4.68 KB

/*
 * soft_geo_tasks_priv.cpp - soft geometry map tasks
 *
 *  Copyright (c) 2017 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author: Wind Yuan <feng.yuan@intel.com>
 */

#include "soft_geo_tasks_priv.h"

namespace XCam {

namespace XCamSoftTasks {

XCamReturn
GeoMapTask::work_range (const SmartPtr<Arguments> &base, const WorkRange &range)
{
    static const Uchar zero_luma_byte[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    static const Uchar2 zero_uv_byte[4] = {{128, 128}, {128, 128}, {128, 128}, {128, 128}};
    SmartPtr<GeoMapTask::Args> args = base.dynamic_cast_ptr<GeoMapTask::Args> ();
    XCAM_ASSERT (args.ptr ());
    UcharImage *in_luma = args->in_luma.ptr (), *out_luma = args->out_luma.ptr ();
    Uchar2Image *in_uv = args->in_uv.ptr (), *out_uv = args->out_uv.ptr ();
    Float2Image *lut = args->lookup_table.ptr ();
    XCAM_ASSERT (in_luma && in_uv);
    XCAM_ASSERT (out_luma && out_uv);
    XCAM_ASSERT (lut);

    Float2 factors = args->factors;
    XCAM_ASSERT (
        !XCAM_DOUBLE_EQUAL_AROUND (factors.x, 0.0f) &&
        !XCAM_DOUBLE_EQUAL_AROUND (factors.y, 0.0f));

    Float2 out_center ((out_luma->get_width () - 1.0f ) / 2.0f, (out_luma->get_height () - 1.0f ) / 2.0f);
    Float2 lut_center ((lut->get_width () - 1.0f) / 2.0f, (lut->get_height () - 1.0f) / 2.0f);
    float x_step = 1.0f / factors.x;
    float y_step = 1.0f / factors.y;

#undef OUT_BOUND
#define OUT_BOUND(image, first, last) \
        (in_pos[first].x >= image->get_width ()) ||   \
        (in_pos[first].y >= image->get_height ()) ||  \
        (in_pos[last].x <= 0.0f) || (in_pos[last].y <= 0.0f)

    for (uint32_t y = range.pos[1]; y < range.pos[1] + range.pos_len[1]; ++y)
        for (uint32_t x = range.pos[0]; x < range.pos[0] + range.pos_len[0]; ++x)
        {
            // calculate 8x2 luma, center aligned
            Float2 in_pos[8];
            float  luma_value[8];
            Uchar  luma_uc[8];
            uint32_t out_x = x * 8, out_y = y * 2;

            //1st-line luma
            Float2 out_pos (out_x, out_y);
            out_pos -= out_center;
            Float2 first = out_pos / factors;
            first += lut_center;
            Float2 lut_pos[8] = {
                first, Float2(first.x + x_step, first.y),
                Float2(first.x + x_step * 2, first.y), Float2(first.x + x_step * 3, first.y),
                Float2(first.x + x_step * 4, first.y), Float2(first.x + x_step * 5, first.y),
                Float2(first.x + x_step * 6, first.y), Float2(first.x + x_step * 7, first.y)
            };
            lut->read_interpolate_array<Float2, 8> (lut_pos, in_pos);
            in_luma->read_interpolate_array<float, 8> (in_pos, luma_value);
            convert_to_uchar_N<float, 8> (luma_value, luma_uc);
            if (OUT_BOUND (in_luma, 0, 7))
                out_luma->write_array_no_check<8> (out_x, out_y, zero_luma_byte);
            else
                out_luma->write_array_no_check<8> (out_x, out_y, luma_uc);

            //4x1 UV
            Float2  uv_value[4];
            Uchar2  uv_uc[4];
            in_pos[0] /= 2.0f;
            in_pos[1] = in_pos[2] / 2.0f;
            in_pos[2] = in_pos[4] / 2.0f;
            in_pos[3] = in_pos[6] / 2.0f;
            in_uv->read_interpolate_array<Float2, 4> (in_pos, uv_value);
            convert_to_uchar2_N<Float2, 4> (uv_value, uv_uc);
            if (OUT_BOUND (in_uv, 0, 3))
                out_uv->write_array_no_check<4> (x * 4, y, zero_uv_byte);
            else
                out_uv->write_array_no_check<4> (x * 4, y, uv_uc);

            //2nd-line luma
            lut_pos[0].y = lut_pos[1].y = lut_pos[2].y = lut_pos[3].y = lut_pos[4].y = lut_pos[5].y =
                                              lut_pos[6].y = lut_pos[7].y = first.y + y_step;
            lut->read_interpolate_array<Float2, 8> (lut_pos, in_pos);
            in_luma->read_interpolate_array<float, 8> (in_pos, luma_value);
            convert_to_uchar_N<float, 8> (luma_value, luma_uc);
            if (OUT_BOUND (in_luma, 0, 7))
                out_luma->write_array_no_check<8> (out_x, out_y + 1, zero_luma_byte);
            else
                out_luma->write_array_no_check<8> (out_x, out_y + 1, luma_uc);
        }
    return XCAM_RETURN_NO_ERROR;
}

}

}