将NV21图像某一区域变黑色

一 转换方法

将NV21图像某一区域变黑色_第1张图片

黑色是R,G,B都是0,因此Y通道是0,UV通道都是128

二 方法

将NV21图像某一区域变黑色_第2张图片

// Correction of abscissa according to width
void fix_x(int &x, int width) {
    if (x < 0) {
        x = 0;
    }
    else if (x >= width) {
        x = width - 1;
    }
}
void fix_y(int &y, int height) {
    if (y < 0) {
        y = 0;
    }
    else if (y >= height) {
        y = height - 1;
    }    
}
// Correct rectangular area according to image width and height
bool fix(int &left, int &top, int &right, int &bottom, int width, int height) {
    fix_x(left, width);
    fix_x(right, width);

    fix_y(top, height);
    fix_y(bottom, height);
    int w = right - left;
    int h = bottom - top;
    if (w <= 0 || h <= 0) {
        return false;
    }
    return true;    
}
// blacken the designated area of nv12 image
// left:Abscissa of upper left corner of rectangular area
// top:Vertical coordinate of upper left corner of rectangular area
// right:Abscissa of lower right corner of rectangular area
// bottom:Vertical coordinate of the lower right corner of the rectangular area
// width:Original image width
// height:Original image height
// ppu8Plane_y:Y channel address
// ppu8Plane_uv:UV channel address
void blackening_nv12(int left, 
                     int top,
                     int right, 
                     int bottom,
                     int width,
                     int height,
                     unsigned char *ppu8Plane_y,
                     unsigned char *ppu8Plane_uv) {
    if (!ppu8Plane_y || !ppu8Plane_uv) {
        return;
    }
    if (!fix(left, top, right, bottom, width, height)) {
        return;
    }
    int w = right - left;
    for (int j = top;j <= bottom;j++) {
        memset(ppu8Plane_y + left + j * width, 0, w);
        memset(ppu8Plane_uv + left + j / 2 * width, 128, w);
    }
}

测试:

#include 
#include 
#include 
enum FILE_WRITE_MODE {
    OVER_WRITE,
    APPEND_WRITE
};
inline bool get_file_content(const char *path, std::string &str) {
    std::ifstream ifs(path, std::ios::in);
    if (!ifs || !ifs.good()) {
        return false;
    }
    str.assign((std::istreambuf_iterator(ifs)), std::istreambuf_iterator());
    ifs.close();
    return !str.empty();
}
bool write_file_content(const char *path, const char *buf, size_t size, unsigned mode) {
    if (!path || !buf) {
        return false;
    }
    std::ofstream  ofs;
    switch (mode)
    {
    case OVER_WRITE:
        ofs.open(path, std::ios::in | std::ios::trunc);
        if (!ofs.is_open()) {
            return false;
        }
        break;
    case APPEND_WRITE:
        ofs.open(path, std::ios::in | std::ios::app);
        if (!ofs.is_open()) {
            return false;
        }
        break;
    default:
        return false;
        break;
    }
    ofs.write(buf, size);
    ofs.close();
    return true;
}
int main() {
    std::string str;
    if (get_file_content("./1653210331_1920x1080_56029_33_1920x1080.NV12", str)) {
        size_t size = str.size();
        std::cout << "load success! size:" << size << std::endl;
        unsigned char *ppu8Plane0 = (unsigned char *)malloc(1920 * 1080 * 3 / 2);
        unsigned char *ppu8Plane1 = ppu8Plane0 + 1920 * 1080;
        memcpy(ppu8Plane0, str.c_str(), size);
        blackening_nv12(0, 0, 1920 / 2 - 1, 1080 - 1, 1920, 1080, ppu8Plane0, ppu8Plane1);
        size = 1920 * 1080 * 3 / 2;
        if (write_file_content("./11_1920x1080.NV12", (char *)ppu8Plane0, size, OVER_WRITE)) {
            std::cout << "rewrite success! size:" << size << std::endl;
        }
    }

    return 0;
}

你可能感兴趣的:(开源组件,C++算法系列,c++)