Program Listing for File xf_flip.hpp

Return to documentation for file (/tmp/ws/src/vitis_common/include/imgproc/xf_flip.hpp)

/*
 * Copyright 2021 Xilinx, Inc.
 *
 * 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.
 */

#ifndef _XF_FLIP_HPP_
#define _XF_FLIP_HPP_

#include "hls_stream.h"
#include "../common/xf_common.hpp"
#include <iostream>

namespace xf {
namespace cv {

// --------------------------------------------------------------------------------------------
// Function to reverse pixel within a pack of pixels
// --------------------------------------------------------------------------------------------
template <int TYPE, int NPC>
XF_TNAME(TYPE, NPC)
reversePixels(XF_TNAME(TYPE, NPC) InPackPixels) {
// clang-format off
        #pragma HLS INLINE
    // clang-format on

    XF_TNAME(TYPE, NPC) OutPackPixels;
    const int XF_PWIDTH = XF_PIXELWIDTH(TYPE, NPC);

    for (int k = 0; k < NPC; k++) {
// clang-format off
            #pragma HLS UNROLL
        // clang-format on
        OutPackPixels.range((NPC - k) * XF_PWIDTH - 1, (NPC - k - 1) * XF_PWIDTH) =
            InPackPixels.range((k + 1) * XF_PWIDTH - 1, k * XF_PWIDTH);
    }

    return OutPackPixels;
} // reversePixels

template <int PTR_WIDTH, int TYPE, int COLS, int NPC, int TC>
void flip_process(ap_uint<PTR_WIDTH> Src_RowPtr[TC], ap_uint<PTR_WIDTH> Dst_RowPtr[TC], uint16_t Width, int Direction) {
// clang-format off
    #pragma HLS INLINE OFF
// clang-format on

        int rd_ptr=0;
        XF_TNAME(TYPE, NPC) pxl_pack;

        for (int i = 0; i < Width; i++) {

    // clang-format off
            #pragma HLS LOOP_TRIPCOUNT min=TC max=TC
            #pragma HLS PIPELINE II=1
        // clang-format on

        if (Direction == 0) // Case of Veritical Flip only
            pxl_pack = Src_RowPtr[i];
        else // Case of Horizontal or both
            pxl_pack = reversePixels<TYPE, NPC>(Src_RowPtr[Width - 1 - i]);

        Dst_RowPtr[i] = pxl_pack;
    }

    return;
}

template <int PTR_WIDTH, int TYPE, int NPC_COLS, int ROWS, int COLS, int NPC>
void _Axi2Mat(ap_uint<PTR_WIDTH>* SrcPtr,
              ap_uint<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC))> SrcRow[NPC_COLS],
              uint16_t Rows,
              uint16_t Cols,
              int Direction,
              int r) {
// clang-format off
        #pragma HLS INLINE OFF
    // clang-format on

        uint16_t NPCCols = Cols >> XF_BITSHIFT(NPC);
        const uint16_t Pixel_width = XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC));

        uint32_t ColsPtrwidth = (((NPCCols * Pixel_width) + PTR_WIDTH - 1) / PTR_WIDTH);

        uint64_t OffsetSrc;

        if(Direction == 1)
            OffsetSrc = r*ColsPtrwidth;
        else
            OffsetSrc = (Rows-1)*ColsPtrwidth - r*ColsPtrwidth;

        MMIterIn<PTR_WIDTH, TYPE, 1, COLS, NPC, -1>::Array2xfMat(SrcPtr+OffsetSrc, SrcRow, 1, Cols, -1);


        return;
}

// Function to process the row

template <int TYPE, int NPC_COLS, int ROWS, int COLS, int NPC>
void _FlipRow(ap_uint<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC))> SrcRow[NPC_COLS],
                    ap_uint<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC))> DstRow[NPC_COLS],
                    uint16_t Rows,
                    uint16_t NPCCols,
                    int Direction){

// clang-format off
    #pragma HLS INLINE OFF
// clang-format on

    flip_process<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC)), TYPE, COLS, NPC, NPC_COLS>(SrcRow, DstRow, NPCCols, Direction);

    return;
}

template <int PTR_WIDTH, int TYPE, int NPC_COLS, int ROWS, int COLS, int NPC>
void _Mat2Axi(ap_uint<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC))> DstRow[NPC_COLS],
                    ap_uint<PTR_WIDTH>*DstPtr,
                    uint16_t Rows,
                    uint16_t Cols,
                    int Direction,
                    int r){

// clang-format off
    #pragma HLS INLINE OFF
// clang-format on

    uint16_t NPCCols = Cols >> XF_BITSHIFT(NPC);
    const uint16_t Pixel_width = XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC));

    uint32_t ColsPtrwidth = (((NPCCols * Pixel_width) + PTR_WIDTH - 1) / PTR_WIDTH);

    uint64_t OffsetDst;

    OffsetDst = r*ColsPtrwidth;
    MMIterOut<PTR_WIDTH, TYPE, 1, COLS, NPC, 1, -1>::xfMat2Array(DstRow, DstPtr+OffsetDst, 1, Cols, -1);

    return;
}

template <int PTR_WIDTH, int TYPE, int ROWS, int COLS, int NPC>
void flip(ap_uint<PTR_WIDTH>* SrcPtr,
                      ap_uint<PTR_WIDTH>* DstPtr,
                      int Rows,
                      int Cols,
                      int Direction){
// clang-format off
    #pragma HLS INLINE OFF
// clang-format on

#ifndef __SYNTHESIS__
    assert(((TYPE == XF_8UC1) || (TYPE == XF_8UC3)) &&
           "Input TYPE must be XF_8UC1 for 1-channel, XF_8UC3 for 3-channel");
    assert(((NPC == XF_NPPC1) || (NPC == XF_NPPC4)) && "NPC must be XF_NPPC1, XF_NPPC4 ");
    assert((Rows <= ROWS) && (Cols <= COLS) && "COLS should be greater than input image size ");
#endif
    const int NPC_COLS = COLS >> XF_BITSHIFT(NPC);
    //const int ROWS = Rows;

    uint16_t NPCCols = Cols >> XF_BITSHIFT(NPC);

    ap_uint<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC))> SrcRow[NPC_COLS];
    ap_uint<XF_WORDDEPTH(XF_WORDWIDTH(TYPE, NPC))> DstRow[NPC_COLS];

// clang-format off
#pragma HLS BIND_STORAGE variable = SrcRow type = ram_s2p impl = bram
#pragma HLS BIND_STORAGE variable = DstRow type = ram_s2p impl = bram
    // clang-format on

    for (int r = 0; r < Rows; r++) {
// clang-format off
        #pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS
        #pragma HLS DATAFLOW
        // clang-format on

        xf::cv::_Axi2Mat<PTR_WIDTH, TYPE, NPC_COLS, ROWS, COLS, NPC>(SrcPtr, SrcRow, Rows, Cols, Direction, r);

        xf::cv::_FlipRow<TYPE, NPC_COLS, ROWS, COLS, NPC>(SrcRow, DstRow, Rows, NPCCols, Direction);

        xf::cv::_Mat2Axi<PTR_WIDTH, TYPE, NPC_COLS, ROWS, COLS, NPC>(DstRow, DstPtr, Rows, Cols, Direction, r);
    }

    return;
}
} // namespace cv
} // namespace xf
#endif //_XF_FLIP_HPP_