使用C++和Mysql进行图像存取操作记录

news2024/9/8 11:36:58

使用C++和Mysql进行图像存取操作记录

配置:
1.Mysql == 5.5.19
2.Vs2019
3.C++

一、创建图像存储表格

选择数据库指令:
将databasename改成你想操作的数据库就行。我这边依旧在student_manager数据库下进行操作。

use databasename;

在这里插入图片描述

CREATE TABLE images(image_name VARCHAR(255) NOT NULL,image_data LONGBLOB NOT NULL,PRIMARY KEY (image_name));

备注:
1.mage_name列被设定为VARCHAR(255),意味着它可以存储最多255个字符的图像名称。你可以根据需要调整这个长度。
2.image_data列被设定为LONGBLOB类型,用于存储图像数据的二进制形式。
3.主键约束(PRIMARY KEY),这意味着每个图像名称都必须是唯一的。

在这里插入图片描述
在Navicat中刷新可以看到
在这里插入图片描述

二、修改数据库表结构

使用第一步创建表格后,直接对表格插入图像时,如果下报错:

Failed to insert data:Error:Data too long for column 'image_data' at row 1

这个错误表明你试图插入的数据超过了 image_data 列的最大允许大小。为了处理这个问题,你需要确保 image_data 列的类型和大小足够大以存储你的图像数据。
需要进行以下步骤:
1.修改数据库表结构:
确保 image_data 列的类型为 LONGBLOB,它可以存储最大 4GB 的数据。
修改指令为:

ALTER TABLE images MODIFY COLUMN image_data LONGBLOB;

images表格替换成自己的表格名字。
在mysql终端依次输入:

use student_manager;//选择数据库
ALTER TABLE images MODIFY COLUMN image_data LONGBLOB;//修改images表格

在这里插入图片描述

  1. 更新代码:
    在插入数据之前设置 max_allowed_packet,这个在后续代码中完善。

三、图像以BLOB格式插入表格

代码如下:

#include <Windows.h> 
#include <mysql.h> 
#include<iostream> 
#include <opencv2/core.hpp> 
#include <opencv2/imgcodecs.hpp> 
#include <opencv2/highgui.hpp>

using namespace cv; 
using namespace std; 

// 定义一个结构体用于存储图像数据
struct ImageData
{
    string image_name; // 图像名称
    vector<uchar> image_data; // 图像数据
};

// 将图像插入数据库的函数
void insertImageToDatabase(const ImageData& imgData)
{
    MYSQL mysql; // 定义MySQL对象
    mysql_init(&mysql); // 初始化MySQL对象
    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "GBK"); // 设置字符集为GBK

    // 连接到数据库
    if (mysql_real_connect(&mysql, "localhost", "root", "123456", "student_manager", 3306, NULL, 0))
    {
        printf("Mysql connected \n"); // 连接成功
    }
    else
    {
        printf("Mysql connected fail :Error:%s\n", mysql_error(&mysql)); // 连接失败,输出错误信息
        return; // 返回
    }

    // 设置 max_allowed_packet
    if (mysql_query(&mysql, "SET GLOBAL max_allowed_packet=67108864")) // 设置为64M
    {
        printf("Failed to set max_allowed_packet: %s\n", mysql_error(&mysql)); // 设置失败,输出错误信息
        mysql_close(&mysql); // 关闭数据库连接
        return; // 返回
    }

    // 准备SQL查询
    const char* query = "INSERT INTO images (image_name, image_data) VALUES (?, ?)";
    MYSQL_STMT* stmt = mysql_stmt_init(&mysql); // 初始化预处理语句
    if (!stmt)
    {
        printf("mysql_stmt_init() out of memory\n"); // 初始化失败,内存不足
        mysql_close(&mysql); // 关闭数据库连接
        return; // 返回
    }

    if (mysql_stmt_prepare(stmt, query, strlen(query)))//执行成功时返回值为0 !!!!!!!!!!!!
    {
        printf("mysql_stmt_prepare() failed: %s\n", mysql_stmt_error(stmt)); // 预处理语句准备失败,输出错误信息
        mysql_stmt_close(stmt); // 关闭预处理语句
        mysql_close(&mysql); // 关闭数据库连接
        return; // 返回
    }

    // 绑定参数
    MYSQL_BIND bind[2]; // 定义绑定参数数组
    memset(bind, 0, sizeof(bind)); // 初始化绑定参数数组

    // 绑定图像名称
    bind[0].buffer_type = MYSQL_TYPE_STRING; // 设置参数类型为字符串
    bind[0].buffer = (char*)imgData.image_name.c_str(); // 设置参数值为图像名称
    bind[0].buffer_length = imgData.image_name.length(); // 设置参数长度为图像名称长度

    // 绑定图像数据
    bind[1].buffer_type = MYSQL_TYPE_BLOB; // 设置参数类型为BLOB
    bind[1].buffer = (char*)imgData.image_data.data(); // 设置参数值为图像数据
    bind[1].buffer_length = imgData.image_data.size(); // 设置参数长度为图像数据大小

    if (mysql_stmt_bind_param(stmt, bind))
    {
        printf("mysql_stmt_bind_param() failed: %s\n", mysql_stmt_error(stmt)); // 绑定参数失败,输出错误信息
        mysql_stmt_close(stmt); // 关闭预处理语句
        mysql_close(&mysql); // 关闭数据库连接
        return; // 返回
    }

    // 执行SQL查询
    if (mysql_stmt_execute(stmt))
    {
        printf("Failed to insert data:Error:%s\n", mysql_stmt_error(stmt)); // 执行查询失败,输出错误信息
    }
    else
    {
        printf("Image inserted successfully\n"); // 执行查询成功,输出成功信息
    }

    // 关闭预处理语句和数据库连接
    mysql_stmt_close(stmt); // 关闭预处理语句
    mysql_close(&mysql); // 关闭数据库连接
}

int main()
{
    // 使用OpenCV加载图像
    Mat image = imread("D:/work/C++Code/SQL/2.png", IMREAD_COLOR); // 读取图像
    if (image.empty())
    {
        cout << "Could not open or find the image" << endl; // 图像读取失败,输出错误信息
        return -1; // 返回错误码
    }

    // 将图像转换为vector<uchar>
    vector<uchar> image_data(image.data, image.data + image.total() * image.elemSize()); // 将图像数据存储到vector中

    // 创建ImageData对象
    ImageData imgData;
    imgData.image_name = "example_image"; // 设置图像名称
    imgData.image_data = image_data; // 设置图像数据

    // 将图像插入数据库
    insertImageToDatabase(imgData); // 调用插入函数

    return 0; // 返回成功码
}

在Navicat中可以看到如下数据:在这里插入图片描述

四、取图

代码如下:

#define HAVE_STRUCT_TIMESPEC // 避免与MySQL库中的定义冲突
#include <windows.h>
#include <mysql.h> // 包含MySQL库的头文件
#include <opencv2/opencv.hpp> // 包含OpenCV库的头文件
#include <iostream> // 包含标准输入输出流库
#include <vector> // 包含标准向量库
#include <fstream> // 包含文件流库




using namespace std; // 使用标准命名空间
using namespace cv; // 使用OpenCV命名空间


void saveImageFromDB(const std::string& dbName, const std::string& tableName, const std::string& imageName, const std::string& outputPath) {
    MYSQL* conn;
    MYSQL_RES* res;
    MYSQL_ROW row;
    unsigned long* lengths; // 用于存储每列的长度  

    // 初始化连接  
    conn = mysql_init(NULL);

    // 连接到数据库  
    if (!mysql_real_connect(conn, "localhost", "root", "123456", dbName.c_str(), 0, NULL, 0)) {
        std::cerr << "Connection failed: " << mysql_error(conn) << std::endl;
        return;
    }

    // 准备 SQL 查询  
    std::string query = "SELECT image_data FROM " + tableName + " WHERE image_name = '" + imageName + "'";

    // 执行查询  
    if (mysql_query(conn, query.c_str())) {
        std::cerr << "Query failed: " << mysql_error(conn) << std::endl;
        mysql_close(conn);
        return;
    }

    // 获取结果  
    res = mysql_use_result(conn);

    
    // 检查是否有数据  
    if (res) {
        row = mysql_fetch_row(res);
        if (row != NULL) {
            lengths = mysql_fetch_lengths(res); // 获取每列的长度  

            // 假设第一列是 image_data(BLOB 类型)  
            std::size_t len = lengths[0]; // 使用第一列的长度  
            std::vector<char> imageData(row[0], row[0] + len);

            // 写入文件(与之前相同)  
            std::ofstream file(outputPath, std::ios::binary);
            if (file.is_open()) {
                file.write(imageData.data(), imageData.size());
                file.close();
                std::cout << "Image saved to " << outputPath << std::endl;
            }
            else {
                std::cerr << "Failed to open file for writing" << std::endl;
            }
        }
        mysql_free_result(res);
    }
    

    // 关闭连接  
    mysql_close(conn);
}



int main() {
  
    // 从数据库中提取图像并保存到文件
    saveImageFromDB("student_manager", "images", "example_image.jpg", "D:/work/C++Code/SQL/output/example_image.jpg");

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1963453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

知迪动态丨北斗智联领导团队莅临知迪科技上海研发中心

7月29日&#xff0c;北斗智联领导团队来到知迪科技参观考察。知迪科技总裁周强先生率公司管理层与技术代表热情接待。 北斗智联一行在知迪科技公司团队的陪同下&#xff0c;首先观摩了在技术展示区陈列的车辆数据记录设备、总线信号分析及仿真设备、ADAS HiL测试台架、测试自动…

【PostGresql】---- pgSql 将列中合并字符串拆分为多行 实例代码

-- 将 AQY_ID,AQY 中的字符串拆分为多行 SELECT"ID","AQY_ID","AQY",UNNEST ( string_to_array( "AQY_ID", , ) ) AS "AQY_ID_1",UNNEST ( string_to_array( "AQY", , ) ) AS "AQY_1" FROM"JF_SGC…

科目一考试题库(超全)!7分钟一把过科目一(总结经验)

1、先看视频 先了解考试规范、流程以及重要的考点难点&#xff0c;做到心中有数&#xff0c;大部分人觉得重难点在扣分题和罚款题上面&#xff0c;可以在网上看一些视频讲解&#xff0c;1.5倍速快速过一遍看的过程中记录一些笔记&#xff0c;可以随便看的而且真滴有用 2、认真刷…

教你如何从Flink小白成为Contributor最终拿到腾讯的Offer

简言&#xff1a;一开始我也是怀揣着成为一个技术大老的梦想开始的&#xff0c;尽管我现在已经入职腾讯三年多了有时候觉得自己还是一个菜鸡哈..... 写这个文章希望可以帮助到刚刚接触大数据&#xff0c;并且对技术怀揣着梦想的朋友们&#xff0c;大家互相学习哈(对Flink不是很…

成都云飞浩容文化传媒有限公司领航电商新纪元

在数字经济浪潮汹涌的今天&#xff0c;电商行业作为时代的弄潮儿&#xff0c;正以前所未有的速度改变着商业版图。成都&#xff0c;这座历史悠久而又充满活力的城市&#xff0c;正孕育着一家在电商服务领域独树一帜的企业——成都云飞浩容文化传媒有限公司。作为一家深耕电商服…

Linux系统编程(4):消息队列

Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。 而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室 以及 BSD&#xff08;加州大学伯克利分校的伯克利软件发布中心&#xff09;&#xff0c; 他们在进程间通信方面的侧重点有所不同&#xff1b; 前…

歌唱比赛活动策划方案书

&#xff08;一&#xff09;海选 1、时间&#xff1a;12月16日 2、地点&#xff1a;公司食堂 3、比赛评委设置&#xff1a;共计6名评委。 4、比赛规则&#xff1a; &#xff08;1&#xff09;选手按报名顺序及上报歌曲进行清唱&#xff08;限时2分钟&#xff0c;类型…

时间序列分析方法之 -- 指数平滑(Exponential Smoothing)原理及Python代码示例

目录 原理 适用情况 Python 示例代码 结论 原理 指数平滑&#xff08;Exponential Smoothing&#xff09;是一种用于时间序列分析和预测的平滑技术。与简单移动平均&#xff08;SMA&#xff09;和加权移动平均&#xff08;WMA&#xff09;不同&#xff0c;指数平滑通过对最…

手势传感器 - 从零开始认识各种传感器【第十八期】

手势传感器|从零开始认识各种传感器 1、什么是手势传感器 手势传感器是一种能够感知人类手势或动作的传感器。它可以捕捉、识别和解释人类的手部动作或姿势&#xff0c;并将其转换成电信号或数字信号&#xff0c;通过识别人体的手势动作来实现与电子设备的交互&#xff0c;如控…

Traefik系列

一、入门Traefik系列——基础简介 官方文档 https://doc.traefik.io/traefik/[1] 简介 Traefik是一个为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Re…

运算放大器电路

一、电路符号 V 、V - 是电源输入。 二、输出特性图 A是运放的固有参数&#xff0c;非常大&#xff0c;可以达到几十万。 四、电压跟随电路 五、负反馈电路 在负反馈电路中&#xff0c;Vn Vp&#xff0c;运算放大器的所有神奇操作都是基于负反馈电路和输出特性曲线&#xff01…

.NET6 加入 SkyWalking 服务

1. 新建 .NET6 Web程序集 名称&#xff1a; MySkywalking.Web 1.1 引用 SkyAPM.Agent.AspNetCore 2.修改 Program.cs 2.1 增加环境变量配置 2.2 添加 Skywalking服务 builder.Services.AddSkyAPM(); 2.3 program.cs 参照代码如下&#xff1a; namespace MySkywalking.We…

IoTDB 入门教程 实战篇⑤——Python示例(开源)

文章目录 一、前文二、新建Python项目三、安装依赖四、示例源码五、参考 一、前文 IoTDB入门教程——导读 本文详细阐述了如何通过一个Python项目成功连接到IoTDB时序数据库&#xff0c;进而展示了如何向该数据库高效地写入数据以及执行精确的数据查询操作。 此示例旨在为读者提…

构建铁塔基站安全防护网:视频AI智能监控技术引领智慧化转型

一、背景现状 随着通信技术的快速发展&#xff0c;铁塔基站作为重要的通信基础设施&#xff0c;其安全、稳定、高效的运行对于保障通信网络的畅通至关重要。然而&#xff0c;铁塔基站大多分布在公路边、高山、野外等区域&#xff0c;巡检难度大&#xff0c;维护效率低&#xf…

聚观早报 | 华为nova Flip官宣;苹果iOS 17.6正式版发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 7月31日消息 华为nova Flip官宣 苹果iOS 17.6正式版发布 方程豹豹5全系降价 vivo X200 Pro主摄参数 谷歌Pixel …

模型剪枝综述

目录 1 深度神经网络的稀疏性&#xff1a; 2 剪枝算法分类&#xff1a; 3 具体的剪枝方法包括&#xff1a; 4 剪枝算法流程&#xff1a; 5 几种常见的剪枝算法&#xff1a; 6 结构化剪枝和非结构化剪枝各有其优缺点&#xff1a; 7 剪枝算法对模型精度的影响 8 影响剪枝…

什么是 5G?

什么是 5G&#xff1f; 5G 是第五代无线蜂窝技术&#xff0c;与以前的网络相比&#xff0c;它提供了更高的上传和下载速度、更一致的连接以及更高的容量。5G 比目前流行的 4G 网络更快、更可靠&#xff0c;并有可能改变我们使用互联网访问应用程序、社交网络和信息的方式。例如…

ETL数据集成丨将DB2数据同步至Postgres数仓实践

随着企业数字化转型的加速&#xff0c;数据已成为企业的重要资产。为了更好地挖掘数据价值&#xff0c;企业纷纷建立自己的数据仓库&#xff0c;以便于数据分析和决策。在众多数据库中&#xff0c;DB2和Postgres作为两款备受欢迎的数据库&#xff0c;如何实现它们之间的数据同步…

Qt基础 | 主机信息查询 | QHostInfo的介绍和使用 | QNetworkInterface的介绍和使用

文章目录 一、Qt 网络模块介绍二、主机信息查询1.QHostlnfo 和 QNetworkInterface 类2.QHostlnfo 的使用2.1 获取本机主机名和 IP 地址2.2 查找主机的地址信息 3.QNetworkInterface 的使用 Qt 网络模块&#xff1a; Qt基础 | 主机信息查询 | QHostInfo的介绍和使用 | QNetworkI…

线上语音交友平台成熟案例源码出售本地找搭子交友app软件线下陪玩系统开发服务

1、上麦相亲互动:直播间内除了红娘外&#xff0c;还有男女用户两个视频麦位&#xff0c;直播间符合要求的用户可以申请上麦, 2、公屏聊天:为上麦用户可以通过在公屏发言的方式参与直播间内的话题互动。 3、私信异性用户之间可以发送私信消息&#xff0c;通过付要或开通会员可解…