【Java编程】【计算机视觉】一种简单的图片加/解密算法

by Li y.c.

一、内容简介

本文介绍一种简单的图片加/解密算法,算法的基本原理十分简单,即逐个(逐行、逐列)地获取图片的像素点颜色值,对其进行一些简单的算数运算操作进行加密,解密过程则相应地为加密运算的逆运算。

二、图片表示基础

在计算机中,图片(我们使用.jpg文件作为示例)在内存中是使用RGB数组进行存储,举例:

在这里插入图片描述

以上图片中,每一个像素点用一个rgb值表示,一般为6位16进制数,例如0x123456,这里0x12表示红度(RED)值,0x34表示绿度(GREEN)值,0x56表示蓝度(BLUE)值。注意到,两位16进制数的取值范围为0~255(0x00到0xFF)。

三、R/G/B值的获取

假如我们知道当前像素点的rgb值为0x123456,如何从中获取到分离的r/g/b值呢?通过简单的位运算即可。如以下java代码:

public class RGBTest {public static void main(String[] args) {String format1 = String.format("%x", (0x123456 >> 16));  // 获取red值(前两位)String format2 = String.format("%x", (0x123456 >> 8) & 0xFF);  // 获取green值(中间两位)String format3 = String.format("%x", (0x123456) & 0xFF);  // 获取blue值(末两位)String format = String.format("%x", (0x123456) & 0xFFFFFF);  // 不做改变System.out.println(format1);System.out.println(format2);System.out.println(format3);System.out.println(format);}
}

运行结果正是我们想要的:

在这里插入图片描述

四、获取整张图片的RGB数组

有了以上的基础,我们就可以将整张图片存储为一个RGB表示的数组,为之后的加/解密操作做基础。使用如下的Java代码:

public List<Integer> getRGB(BufferedImage image, int x, int y) {List<Integer> rgb = new ArrayList<Integer>();if (image != null && x <= image.getWidth() && y <= image.getHeight()) {for (int h = 0; h < y; h++) {for (int w = 0; w < x; w++) {//获得w,h坐标的颜色int pixel = image.getRGB(w, h);rgb.add(pixel);}}}return rgb;}

五、加密函数

我们使用简单的加密操作,即把图片的R/G/B值同时加50后模256(防止值溢出造成噪点【可以想见,若某一通道出现进位,后果是灾难性的】):

// 加密函数public static void Encrypt(Integer[] rgb, int width, int height) {// 输出文件名File file = new File("image_out.jpg");BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) bi.getGraphics();for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {int color = rgb[w + width * h];int red = color >> 16;int green = (color >> 8) & 0xFF;int blue = color & 0xFF;int red_ = (red + 50) % 256;int green_ = (green + 50) % 256;int blue_ = (blue + 50) % 256;Color c = new Color(red_ << 16 | green_ << 8 | blue_);g2.setColor(c);g2.drawLine(w, h, w + 1, h + 1);}}try {ImageIO.write(bi, "jpg", file);} catch (IOException e) {e.printStackTrace();}}

看看加密效果:(以下代码位于主函数中)

// 加密部分:【image_1_1.jpg】---【image_out.jpg】Image_Encrypt r = new Image_Encrypt();File f = new File("image_1_1.jpg");BufferedImage bi = ImageIO.read(f);int width = bi.getWidth();int height = bi.getHeight();List<Integer> l = null;Integer[] rbg = new Integer[width * height];l = r.getRGB(bi, width, height);
//             查看rgb值:
//            System.out.print(l);for (int i = 0; i < width * height; i++) {rbg[i] = l.get(i);}Encrypt(rbg, width, height);

加密后的图像:

在这里插入图片描述

六、解密函数

解密函数应为加密函数的逆运算,考虑到边缘条件,代码如下:

// 解密函数public static void Decrypt(Integer[] rgb, int width, int height) {// 输出文件名File file = new File("image_out_de.jpg");BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) bi.getGraphics();for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {int color = rgb[w + width * h];int red = color >> 16;int green = (color >> 8) & 0xFF;int blue = color & 0xFF;int red_;if (red == 255){red_ = 255;}else{red_ = (red - 50 + 255) % 255;}int green_;if (green == 255){green_ = 255;}else{green_ = (green - 50 + 255) % 255;}int blue_;if (blue == 255){blue_ = 255;}else{blue_ = (blue - 50 + 255) % 255;}Color c = new Color(red_ << 16 | green_ << 8 | blue_);g2.setColor(c);g2.drawLine(w, h, w + 1, h + 1);}}try {ImageIO.write(bi, "jpg", file);} catch (IOException e) {e.printStackTrace();}}

解密后的图像却是这样的:

在这里插入图片描述

推测是由于边缘条件造成的,修改代码中……

【debug】
我们写一个测试类,看看从0到255的值里面,是否有不满足该逆运算关系的:

public class Test {public static void main(String[] args){for (int i = 0;i <= 255;i ++){int j = (i + 50) % 256;int j_ = (j - 50 + 256) % 256;if (i != j_){System.out.print("errr");}}}
}

输出如下:

【没有报错】……??

基准测试

加/解密均不做任何操作,直接由三通道的值拼凑出rgb数组:

加密函数

// 加密函数public static void Encrypt(Integer[] rgb, int width, int height) {// 输出文件名File file = new File("image_out.jpg");BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) bi.getGraphics();for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {int color = rgb[w + width * h];int red = color >> 16;int green = (color >> 8) & 0xFF;int blue = color & 0xFF;// 基准测试int red_ = red;int green_ = green;int blue_ = blue;//                int red_ = (red + 50) % 256;
//                int green_ = (green + 50) % 256;
//                int blue_ = (blue + 50) % 256;Color c = new Color(red_ << 16 | green_ << 8 | blue_);g2.setColor(c);g2.drawLine(w, h, w + 1, h + 1);}}try {ImageIO.write(bi, "jpg", file);} catch (IOException e) {e.printStackTrace();}}

解密函数

// 解密函数public static void Decrypt(Integer[] rgb, int width, int height) {// 输出文件名File file = new File("image_out_de.jpg");BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) bi.getGraphics();for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {int color = rgb[w + width * h];int red = color >> 16;int green = (color >> 8) & 0xFF;int blue = color & 0xFF;// 基准测试int red_ = red;int green_ = green;int blue_ = blue;
//                int red_;
//                if (red == 255){
//                    red_ = 255;
//                }
//                else{
//                    red_ = (red - 50 + 256) % 256;
//                }//                int green_;
//                if (green == 255){
//                    green_ = 255;
//                }
//                else{
//                    green_ = (green - 50 + 256) % 256;
//                }//                int blue_;
//                if (blue == 255){
//                    blue_ = 255;
//                }
//                else{
//                    blue_ = (blue - 50 + 256) % 256;
//                }Color c = new Color(red_ << 16 | green_ << 8 | blue_);g2.setColor(c);g2.drawLine(w, h, w + 1, h + 1);}}try {ImageIO.write(bi, "jpg", file);} catch (IOException e) {e.printStackTrace();}}

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

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

相关文章

从GPT到Gemini 大模型进化史

从GPT到Gemini&#xff1a;大模型进化史 在过去的几年里&#xff0c;人工智能领域经历了翻天覆地的变化&#xff0c;其中最引人注目的莫过于大规模语言模型的发展。从最初的GPT系列到最近的Gemini&#xff0c;这些模型不仅在技术上取得了重大突破&#xff0c;还在实际应用中展…

【AI提示词】中国历史与世界发展对比器

提示说明 输入特定年份&#xff0c;输出该时期中国与世界的发展状况。 提示词 # Role 中国历史与世界发展对比器## Profile - author: xxx - version: 1.0 - description: 输入特定年份&#xff0c;输出该时期中国与世界的发展状况。## Attention 请深入挖掘历史资料&#x…

阿里云OSS应对DDoS攻击策略

阿里云对象存储服务&#xff08;OSS&#xff09;若遭遇DDoS攻击&#xff0c;可结合阿里云提供的安全服务与自身配置优化进行综合防御。以下是具体的解决方案及步骤&#xff1a; 1. 启用阿里云DDoS防护服务 防护服务类型&#xff1a;阿里云提供基础DDoS防护&#xff08;默认免费…

MyCat 分库分表

介绍 问题分析 随着互联网及移动互联网的发展&#xff0c;应用系统的数据量也是成指数式增长&#xff0c;若采用单数据库进行数据存 储&#xff0c;存在以下性能瓶颈&#xff1a; 1. IO瓶颈&#xff1a;热点数据太多&#xff0c;数据库缓存不足&#xff0c;产生大量磁盘IO&a…

C++笔记-list

list即是我们之前学的链表&#xff0c;这篇主要还是讲解list的底层实现&#xff0c;前面会讲一些list区别于前面string和vector的一些接口以及它们的注意事项。 一.list的基本使用 和之前的string&#xff0c;vector一样&#xff0c;有很多之前见过的一些接口&#xff0c;经过…

unityTEngine学习记录2

上一篇了解了下载项目与外部调用的接口&#xff0c;接下来就继续学习根据这个框架来加载场景首先打开te官网&#xff0c;进入教程。 了解框架目录以及功能 首先要了解的就是这个框架的文件结构目录&#xff0c;知道他都是干啥的&#xff0c;在官网的目录结构中介绍了其中重要…

逻辑过期怎么设计

设计“逻辑过期”通常用于缓存、令牌管理、数据有效性验证等场景&#xff0c;其核心是通过业务逻辑判断数据是否过期&#xff08;而非单纯依赖物理时间&#xff09;。以下是设计逻辑过期的关键思路和实现方案&#xff1a; 1. 核心思想 物理过期&#xff1a;基于固定的时间&…

DAY 47 leetcode 232--栈与队列.用栈实现队列

题号232 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; class MyQueue {Stack<Integer> stackIn;Stack<Integer> stackOut;/** Initialize your data structure here. */pu…

逻辑回归 (Logistic Regression)

文章目录 逻辑回归 (Logistic Regression)问题的引出Sigmoid function逻辑回归的解释决策边界 (Decision boundary)逻辑回归的代价函数机器学习中代价函数的设计1. 代价函数的来源&#xff08;1&#xff09;从概率模型推导而来&#xff08;统计学习视角&#xff09;&#xff08…

关于C语言的模拟物理模型

声明&#xff1a;本文全部代码效果基于C语言easyx图形界面库。 引言 关于很多游戏和模型的开发&#xff0c;都需要模拟真实的物理模型 比如&#xff1a;基本矢量运动模型&#xff08;位移&#xff0c;速度&#xff0c;加速度&#xff09;&#xff0c;重力模型&#xff0c;碰撞…

C++编译与链接:从源码到可执行文件的魔法之旅(Visual Studio实践)

文章目录 **C++编译与链接:从源码到可执行文件的魔法之旅(Visual Studio实践)****一、C++编译器的工作流程****二、Visual Studio环境配置实战****三、示例项目:Hello World全流程解析****四、高级技巧与工具链****五、总结与参考资料**C++编译与链接:从源码到可执行文件的…

现代C++的范式演进与工程实践深度解析(本文序号不知道怎么整的,有点问题)

引言:C++的复兴时代 在经历了"已死语言"的质疑后,现代C++正迎来前所未有的复兴。据2024年TIOBE指数显示,C++以8.33%的占比稳居第三,较2020年上升2.1个百分点。这种复兴并非偶然——随着C++20标准的全面落地和C++23特性的逐步实现,这门已有40年历史的语言正在系…

通过gird布局实现div的响应式分布排列

目标&#xff1a;实现对于固定宽度的div盒子在页面中自适应排布&#xff0c;并且最后一行的div盒子可以与前面的盒子对齐。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" con…

WSL2-Ubuntu22.04安装URSim5.21.3

WSL2-Ubuntu22.04安装URSim5.21.3 准备安装启动 准备 名称版本WSL2Ubuntu22.04URSim5.21.3VcXsrvNaN WSL2安装与可视化请见这篇:WSL2-Ubuntu22.04-配置。 安装 我们是wsl2-ubuntu22.04&#xff0c;所以安装Linux版本的URSim&#xff0c;下载之前需要注册一下&#xff0c;即…

产品研发项目管理6大痛点

在产品研发项目管理实践中&#xff0c;企业普遍面临六大系统性挑战&#x1f937;‍♀️&#xff0c;直接影响研发效能与战略目标达成&#x1f514;&#xff0c;具体表现为&#xff1a; ① 产品需求管理不完善&#xff1a;需求与市场脱节&#xff0c;需求不明确、需求变更频繁…

计算机网络基础概论

计算机网络基础概论 目录 一、网络基本概念 1.1. 网络 1.2 互联网 1.3 ip地址 1.3.1 作用 1.3.2 分类 1.4 MAC地址 1.4.1 MAC地址与 IP 地址的关系 1.5 网络协议 二、网络分层模型 2.1 物理层 2.2 数据链路层 2.3 网络层 2.4 传输层 2.5 会话层 2.6 表示层 2.7…

Windows下导入文件中的环境变量

在Windows批处理脚本&#xff08;.bat&#xff09;中&#xff0c;通过文件获取并设置环境变量通常涉及逐行读取文件内容并动态赋值给变量。以下是具体实现方法及示例&#xff1a; 一、从文件读取变量并设置到环境变量 假设有一个配置文件&#xff08;如env_config.txt&#xf…

WebSocket 实现数据实时推送原理

WebSocket 实现数据实时推送的核心机制在于其全双工通信能力和持久的连接特性。以下是其工作原理的详细步骤&#xff1a; 1. 握手阶段&#xff08;HTTP 升级协议&#xff09; 客户端发起请求&#xff1a;通过发送一个带有特殊头部的 HTTP 请求&#xff0c;请求协议升级。 GET …

Linux操作系统学习之---进程状态

目录 明确进程的概念: Linux下的进程状态: 虚拟终端的概念: 见一见现象: 用途之一 : 结合指令来监控进程的状态: 和进程强相关的系统调用函数接口: getpid()和getppid(): fork(): fork函数创建子进程的分流逻辑: 进程之间具有独立性: 进程中存在的写时拷贝: 见一见进程状态…

何小鹏在得意的笑

"小鹏汽车率先迈出了造车新势力出海一大步" 作者 | 魏强 编辑 | 卢旭成 4月15日&#xff0c;小鹏汽车在香港举行小鹏全球热爱之夜和2025首款全球旗舰小鹏X9上市发布会。 当小鹏汽车创始人何小鹏把香车X9交付给香港首批车主的时候&#xff0c;脸上露出经典的笑脸。…