【工具】raw与jpg互转python-cpp

在工作中常常需要将图像转化为raw数据或者yuv数据,这里将提供 cpp 版本和 python 版本的互转代码

代码链接见文档尾部。

cpp 版本

jpg2raw.cpp

#include <fstream>
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

// Windows 和 Linux 下通用的创建目录函数
#ifdef _WIN32
#include <direct.h> // For _mkdir on Windows
#define MKDIR(dir) _mkdir(dir)
#else
#include <sys/stat.h> // For mkdir on POSIX systems
#define MKDIR(dir) mkdir(dir, 0755)
#endif

bool create_directory(const std::string &dir_path)
{
#ifdef _WIN32
    if (_mkdir(dir_path.c_str()) != 0)
    {
        return false;
    }
#else
    if (MKDIR(dir_path.c_str()) != 0 && errno != EEXIST)
    {
        return false;
    }
#endif
    return true;
}

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        std::cerr << "Usage: ./image_to_raw input_image.jpg" << std::endl;
        return -1;
    }

    std::string input_image_path = argv[1];
    std::string base_name = input_image_path.substr(input_image_path.find_last_of('/') + 1); // Unix风格路径分隔符
#ifdef _WIN32
    std::replace(base_name.begin(), base_name.end(), '\\', '/'); // 对于Windows下的反斜杠,统一转换为正斜杠
#endif

    std::cout <<" ----------- input_image_path: " << input_image_path << " ------------------------"<<std::endl;
    std::cout <<" ----------- basename: " << base_name << " ------------------------"<<std::endl;

    std::string raw_dir = "raws/";
    // std::string output_raw_path = raw_dir + base_name + ".raw";

    std::string file_name = input_image_path.substr(input_image_path.find_last_of("/\\") + 1);
    std::string file_name_without_suffix = file_name.substr(0, file_name.find_last_of("."));
    std::string file_name_with_suffix = file_name_without_suffix + ".raw";
    std::string output_raw_path = raw_dir + file_name_with_suffix;


    // 创建 'raw' 子目录(如果不存在)
    if (!create_directory(raw_dir))
    {
        std::cerr << "Failed to create directory: " << raw_dir << std::endl;
        //return -1;
    }

    cv::Mat img = cv::imread(input_image_path, 1);
    if (img.empty())
    {
        std::cerr << "Failed to load the image: " << input_image_path << std::endl;
        return -1;
    }

    int im_width = img.cols;
    int im_height = img.rows;
    int im_depth = img.channels();

    std::cout << "im_width: " << im_width << std::endl;
    std::cout << "im_height: " << im_height << std::endl;
    std::cout << "im_depth: " << im_depth << std::endl;

    // 写入 RAW 文件
    std::ofstream raw_file(output_raw_path, std::ios::binary);
    if (!raw_file.is_open())
    {
        std::cerr << "Failed to open file for writing: " << output_raw_path << std::endl;
        return -1;
    }
    raw_file.write(reinterpret_cast<const char *>(img.data), im_width * im_height * im_depth);
    raw_file.close();

    std::cout << "Converted " << input_image_path << " to " << output_raw_path << std::endl;

    return 0;
}

raw2jpg

#include <fstream>
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <unordered_map>

#ifdef _WIN32
#include <direct.h> // For _mkdir on Windows
#define MKDIR(dir) _mkdir(dir)
#else
#include <sys/stat.h> // For mkdir on POSIX systems
#define MKDIR(dir) mkdir(dir, 0755)
#endif

struct ImageSize
{
    int width;
    int height;
};

const std::unordered_map<int, ImageSize> image_sizes = {
    {921600, {640, 480}},
    {2764800, {1280, 720}},
    {5858640, {1896, 1030}},
    {6220800, {1920, 1080}},
    {11059200, {2560, 1440}},
    {12257280, {2688, 1520}},
    {15116544, {2592, 1944}},
    {3686400, {1280, 960}}};

// 跨平台创建目录函数(仅支持Linux和Windows)
bool create_directory(const std::string &path)
{
#ifdef _WIN32
    return (_mkdir(path.c_str()) == 0);
#else
    return (::mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0);
#endif
}

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        std::cerr << "Usage: ./raw_image_viewer raw_image.raw" << std::endl;
        return -1;
    }

    std::string raw_image_path = argv[1];
    std::cout << "raw_image_path: " << raw_image_path << std::endl;

    // 获取文件大小
    std::ifstream file(raw_image_path, std::ios::binary | std::ios::ate);
    size_t file_size = file.tellg();
    file.close();
    std::cout << "size: " << file_size << " bytes" << std::endl;

    // 查找对应的图像尺寸
    auto it = image_sizes.find(file_size);
    if (it == image_sizes.end())
    {
        std::cout << file_size << " is not supported!" << std::endl;
        return -1;
    }
    const ImageSize &size = it->second;
    int im_width = size.width;
    int im_height = size.height;
    int im_depth = 3; // 假设所有图像都是RGB三通道

    std::cout << "im_width: " << im_width << std::endl;
    std::cout << "im_height: " << im_height << std::endl;
    std::cout << "im_depth: " << im_depth << std::endl;

    cv::Mat raw_image(im_height, im_width, CV_8UC3);

    // 读取 RAW 文件的内容
    std::ifstream raw_file(raw_image_path, std::ios::binary);
    raw_file.read(reinterpret_cast<char *>(raw_image.data), im_width * im_height * im_depth);
    raw_file.close();

    // 提取并创建 images 文件夹(跨平台)
    std::string images_path = "images/";
    bool dir_created = create_directory(images_path);

    std::string file_name = raw_image_path.substr(raw_image_path.find_last_of("/\\") + 1);
    std::string file_name_without_suffix = file_name.substr(0, file_name.find_last_of("."));
    std::string file_name_with_suffix = file_name_without_suffix + ".jpg";
    std::string output_path = images_path + file_name_with_suffix;

    cv::imwrite(output_path, raw_image);

    std::cout << " images_path: " << images_path << std::endl;
    std::cout << " file_name_with_suffix: " << file_name_with_suffix << std::endl;
    std::cout << " file save name: " << output_path << std::endl;

    if (!dir_created)
    {
        std::cerr << "Failed to create 'images' directory." << std::endl;
    }

    // (可选)显示图像
    // cv::imshow("raw_image", raw_image);
    // cv::waitKey(5);
    // cv::destroyAllWindows();

    // (可选)删除原始 RAW 文件
    // std::remove(raw_image_path.c_str());

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(convertRAW2jpg CXX)

# 设置安装目录
set(CMAKE_INSTALL_PREFIX "${PROJECT_BINARY_DIR}/install")
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

# 要求编译器支持C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Windows 特定选项和标志
if(MSVC)
    add_compile_options(/utf-8)
    add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()


# OpenCV 手动配置部分(保留 find_package 并注释)
if(WIN32)
    # find_package(OpenCV REQUIRED)  # 注释掉以使用自定义路径
    set(OpenCV_DIR "D:/opencv480vc16/build" CACHE PATH "Path to a custom OpenCV build on Windows")
    set(OPENCV_INCLUDE_DIRS "${OpenCV_DIR}/include")
    set(OPENCV_LIB_DIR     "${OpenCV_DIR}/x64/vc16/lib") # 根据实际编译器版本调整

    include_directories(${OPENCV_INCLUDE_DIRS})
    link_directories(${OPENCV_LIB_DIR})

    list(APPEND EXTRA_LIBS opencv_world480.lib) # 根据实际OpenCV库名称调整
elseif(NOT WIN32)
    # Linux 下的手动 OpenCV 配置
    # find_package(OpenCV REQUIRED)  # 注释掉以使用自定义路径
    set(OpenCV_DIR "~/install/opencv4.5.4" CACHE PATH "Path to a custom OpenCV build on Unix-like systems")
    set(OPENCV_INCLUDE_DIRS "${OpenCV_DIR}/include/opencv4")
    set(OPENCV_LIB_DIR     "${OpenCV_DIR}/lib")

    include_directories(${OPENCV_INCLUDE_DIRS})
    link_directories(${OPENCV_LIB_DIR})

    list(APPEND EXTRA_LIBS opencv_world -fopenmp -lpthread -lm) # 根据实际OpenCV库名称和依赖调整
endif()

include_directories(${OpenCV_INCLUDE_DIRS})

# 添加源文件
add_executable(raw2jpg src/raw2jpg.cpp)
add_executable(jpg2raw src/jpg2raw.cpp)


target_link_libraries(raw2jpg PRIVATE ${EXTRA_LIBS})
target_link_libraries(jpg2raw PRIVATE ${EXTRA_LIBS})

# 安装目标及辅助脚本
set(TMP_TEST_DIR ${PROJECT_SOURCE_DIR}/temp_example)
install(TARGETS raw2jpg
        RUNTIME DESTINATION examples
        RUNTIME DESTINATION ${TMP_TEST_DIR})

install(TARGETS jpg2raw
        RUNTIME DESTINATION examples
        RUNTIME DESTINATION ${TMP_TEST_DIR})

# 找到 assets 目录下所有的 raw 文件,并安装到临时目录
FILE(GLOB RAWS assets/raws/*.raw)
FILE(GLOB JPGS assets/jpgs/*.jpg)

install(FILES ${RAWS} DESTINATION ${TMP_TEST_DIR}/test_raws)
install(FILES ${JPGS} DESTINATION ${TMP_TEST_DIR}/test_jpgs)

if (WIN32)
    install(FILES ${PROJECT_SOURCE_DIR}/onekey_windows_batch2jpg.bat
            DESTINATION examples
            DESTINATION ${TMP_TEST_DIR})
    install(FILES ${PROJECT_SOURCE_DIR}/onekey_windows_batch2raw.bat
            DESTINATION examples
            DESTINATION ${TMP_TEST_DIR})
else()
    install(FILES ${PROJECT_SOURCE_DIR}/onekey_ubuntu_batch2jpg.sh
            DESTINATION examples
            DESTINATION ${TMP_TEST_DIR})
    install(FILES ${PROJECT_SOURCE_DIR}/onekey_ubuntu_batch2raw.sh
            DESTINATION examples
            DESTINATION ${TMP_TEST_DIR})
endif(WIN32)

批量将 raw 转换为 jpg 的脚本

ubuntu

onekey_ubuntu_batch2jpg.sh

#!/bin/bash
set -e

if [ $# -eq 0 ]; then
	im_path=`pwd`
else
	im_path=$1
fi

echo "batch convert the raw image to jpg images in path: $im_path"
i=0
for im in $(ls $im_path)
do 
	if [ "${im##*.}" = "raw" ]; then
		if [ -f $im_path/$im ];then
			echo "convert $file to jpg image..."
            ./raw2jpg $im_path/$im
			let i+=1
		fi
	fi
done 
echo "DONE: $i pictures been gennerated!"**s**
windows

onekey_windows_batch2jpg.bat

@echo off

@REM 如果没有输入路径, 就使用当前路径
@if "%~1"=="" (
    set "im_path=%cd%"
) else (
    set "im_path=%~1"
)

@REM 输出批处理将要转换文件的路径信息
echo Batch converting RAW images to JPG in the current directory or specified path: %im_path%

@REM 遍历指定目录及其子目录下的所有.raw文件
for /R "%im_path%" %%i in (*.raw) do (
    @REM 获取图片名称(不包括完整路径)
    set "img_file=%%~ni"
    @REM 输出正在处理的原始图像文件名
    echo Processing image: %%i
    @REM 调用 raw2jpg.exe 进行转换,由于程序内部已经设置了输出目录和文件名规则,所以这里仅传入原始文件路径即可
    .\raw2jpg.exe "%%i"
)

@REM 暂停脚本执行,等待用户按键继续
pause

批量将 jpg 转换为 raw 的脚本

ubuntu

onekey_ubuntu_batch2raw.sh

#!/bin/bash
set -e

if [ $# -eq 0 ]; then
	im_path=`pwd`
else
	im_path=$1
fi

echo "batch convert the jpg images to raw image in path: $im_path"
i=0
for im in $(ls $im_path)
do 
	if [ "${im##*.}" = "jpg" ]; then
		if [ -f $im_path/$im ];then
			echo "convert $file to jpg image..."
            ./jpg2raw $im_path/$im
			let i+=1
		fi
	fi
done 
echo "DONE: $i pictures been gennerated!"s
windows

onekey_windows_batch2raw.bat

@echo off

@REM 如果没有输入路径, 就使用当前路径
if "%1"=="" (
    set "im_path=%cd%"
) else (
    set "im_path=%~1"
)

@REM 输出当前处理的路径
echo Batch converting image files to raw images in path: %im_path%

@REM 遍历指定目录及其子目录下的所有.jpg, .jpeg, .bmp, .png文件
for /R "%im_path%" %%i in (*.jpg, *.jpeg, *.bmp, *.png) do (
    @REM 获取图片名称(这里保留完整路径)
    echo Processing image: %%i
    .\jpg2raw.exe "%%i"
)

pause

所有代码见

raw2jpg-github

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄金旺铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值