基于processing的图片处理app(伪)教程
项目课(计算机)
前言
Fuck Hanhe
建议是有些许计算机基础的来看,数学系的学生可以先学下c++的基本语法(b站搜索黑马程序员),这个大二要学。
前置知识是 函数,变量,循环语句和判断语句。
c2成功坠机,感觉第二次做的那个比第一个好太多了。
没办法,至少第二个做的时候有人给你美术图片,第一个发消息在群里征询美术意见都没声音的。
室友拿了b3,一个朋友拿了b2,他们的程序看起来就friendly些。
是应数的计算机周会很坑爹,微积分期中考,4级考试,3k字的新生课(军训推迟上课但提交报告时间没推迟)
建议小组是两个程序,一个美化,一个视频,一个文案。
不要像我一样一个人把程序美化全包了
本篇教程不会让你得很高的分,只是让你更快的学些有用的东西
所以关于教学processing的部分很简单,是让你对着书看的
窗口大小建议设置小点,否则后面改起来很痛苦,很多人的电脑并不是2560的
不要像lhh一样我写了前言又不看,直奔主题又说自己看不懂,我真的无语。
里面()多是我想让你手打()
有错误和意见请批评指正,多谢啦!(*´・ω・`)⊃,我会一步步完善的。
processing基础部分
真心想学好的可以看我资源分享里的书(中文),看完1——9章下面只是一些简单的东西
英文版
https://ebookcentral.proquest.com/lib/dundee/detail.action?docID=4333729
我下面的也只能给有基础的看感觉(否则我也有写书的水平了,乐)
第一次可以先用ai生成几个实例或者看processing自带样板来熟悉一下这门语言
下载processing
好多同学卡在第一步下载了,一般是要梯子去github下的,如果是计算机系的要早点准备了,github将是你的一个很关键的平台,用来学习找项目什么的。
在后面的资源分享(自愿返乡)里有win版的
设置里可以调中文和字体大小,不要像我一样在最后才知道。
一般用法
程序由若干个函数组成,而程序语句只能在函数中调用。
Processing 提供大量预定义函数,直接调用即可,本文会讲到一些与图片处理相关的。
setup() 函数:程序启动时运行一次,用于初始化窗口大小、背景色等。
draw() 函数:每秒默认运行 60 次(帧率可调),用于持续更新画面。
通俗来讲,点击运行,首先setup()就会执行里面的语句,在执行完后就会进入draw()的循环执行中。
ai样例
void setup() {
size(800, 600); // 窗口尺寸
background(255); // 背景色(白色)
}
void draw() {
ellipse(mouseX, mouseY, 50, 50); // 跟随鼠标画圆
}
数据类型
我们会把数据储存到变量中,而每个变量都有其数据类型,计算机将会根据其类型来分配不同的内存来储存。
知道这些就行
int是整数、float是小数、PImage是图片
String是文字,需要用""括起来,如"i am die"
boolean 是 布尔类型, 储存的是true和 false掌控逻辑判断
类型 名字; //不带赋值
类型 名字 = 值; //带赋值
数组
就是要存储多个int,float时要用到的,连续储存不同数据的结构。
注意数组是从0开始计算的。定义一个大小为2的int数组a,里面只有a[0]、a[1]
类型[] 名字;
类型[]名字 = new 类型[数量];
动态数组
可以通过 ArrayList 类来实现。ArrayList 是 Java 集合框架的一部分,它提供了动态调整大小的数组功能,这意味着你不需要在创建时指定数组的大小,并且可以在运行时添加或删除元素。
更多的自行了解,资料比processing多太多了
import java.util.ArrayList;
void setup(){
// 创建一个存储整数的 ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
// 或者指定初始容量
ArrayList<String> words = new ArrayList<>(10);
main();
}
void main(){
numbers.add(1); //增加数组元素
int a = numbers.get(0); //访问数组元素,0是下标
numbers.remove(0); //移除索引为0的袁术
numbers.add(1); //增加数组元素
numbers.set(0, 50); // 将索引 0 处的元素更新为 50
int size = numbers.size(); // 获取当前元素数量
// 使用增强的 for 循环
for (Integer num : numbers) {
System.out.println(num);
}
}
运算符
+,-,*,/ 分别是加、减、乘、整除
= 是赋值不是相等
boolean类型运算符包括&&(短路与,都为正确才正确)、
||(短路或,有一个正确就正确)、
!(非,取反面)、
| == | 等于 |
| != | 不等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于或等于 |
| <= | 小于或等于 |
语句
学会 if、for循环就行,骚年,百度吧!看我代码也行
if (条件) {
// 当条件为真时执行的代码块
}
if (条件1) {
// 当条件1为真时执行的代码块
} else if (条件2) {
// 当条件1为假且条件2为真时执行的代码块
} else {
// 当所有条件都不满足时执行的代码块
}
for (初始化; 条件; 迭代) {
// 每次循环要执行的代码块
}
像素
理解为带颜色的坐标点就行,不断密集就形成了图像。具体的百度了解。
左上角是坐标原点,往右是x轴,往下是y轴
可以先写个void mousePressed(){println(mouseX+","+mouseY);}来熟悉一下
其中mouseX是鼠标点击的横坐标,mouseY是鼠标点击的纵坐标
void mousePressed(){代码块}是函数的形式,是processing自带的用来监视鼠标点击的
类似的还有
void mouseReleased(){代码块}:当鼠标按钮释放时调用。
void mouseClicked(){代码块}:当鼠标点击(按下并释放)时调用。
void mouseMoved(){代码块}:当鼠标移动且没有按钮被按下时调用。
void mouseDragged(){代码块}:当鼠标移动且有按钮被按下时调用。
void mouseWheel(){代码块}:当鼠标滚轮滚动时调用。
有RGB和HSV两种系统用colorMode(HSB)和colorMode(RGB)可以切换
这也是实现亮度,透明度和饱和度的关键
HSV (色相hue, 饱和度saturation, 明度value), 也称HSB
// 设置颜色模式为 HSB 并定义每个分量的最大值
colorMode(HSB, 360, 100, 100, 100);
// 最后一个参数是 alpha (透明度)的最大值
// 使用 HSB 定义颜色并包含透明度 (alpha)
fill(240, 80, 60, 50); // 蓝色,中等饱和度,低亮度,半透明
rect(50, 50, 100, 100);
透明度我是用tint(value)和noTint()实现的,0~255的透明度数值value
line、rect、text
其实可以没必要掌握,让美工在画图上画好,自己在打判定点就行,为啥要用processing画图???当然这是有必要掌握的(其他数学软件),但在实现图像编辑器的时候没用。
stroke(Ccolor) //设置边的颜色
noStroke() //消去边
可以设置边的颜色,Ccolor我记得是填颜色对应的数字,0是黑,255是白,还有用网络编码的##FFC0CB(粉红)
fill(Ccolor) //里面的填充色
nofill(); //没有填充
设置内部颜色
line(起始点x,起始点y,结束点x,结束点y)
用不到一点
rect(起始点x,起始点y,长,宽)
第一种,我用的最多
rextMode(CENTER)
rect(中心点x,中心点y,长,宽)
没用过,防查重可以
text(文本内容,起始点x,起始点y)
textSize(字体大小)
textLeading(行距)
textAlign(halign, valign); //下面贴AI详解
halign: 水平对齐方式,可以是以下之一:
LEFT (默认):文本的左边缘与给定的 x 坐标对齐。
CENTER:文本的水平中心与给定的 x 坐标对齐。
RIGHT:文本的右边缘与给定的 x 坐标对齐。
valign: 垂直对齐方式,可以是以下之一:
BASELINE (默认):文本的基线(字母的底部线)与给定的 y 坐标对齐。
TOP:文本的顶部与给定的 y 坐标对齐。
CENTER:文本的垂直中心与给定的 y 坐标对齐。
BOTTOM:文本的底部与给定的 y 坐标对齐。
文本内容是String类型的
最难调控的一个,往往调这个的坐标用一上午还搞不好,可惜没早点知道画图解决就行,tip区还是要用text的我真的。
但文本功能是必用的。
参数
mouseX,mouseY是鼠标的坐标
displayWidth 和 displayHeight 是屏幕大小
width 和 height 是窗口大小
图像
PImage 图像名 = loadImage("文件名.文件类型"); //载入图片
image(图像名,起始点x,起始点y); //展示图片
image(图像名,起始点x,起始点y,长,宽); //有放缩的展示图片
get(x,y,长,宽) //获取窗口上显示的像素,返回类型是PImage
图像名.save("modified_example.png"); // 将图像保存为 PNG 文件
下面展示了对图片的像素级操作
img.loadPixels();
colorMode(HSB);
for (int i = 0; i < img.pixels.length; i++) {
color c = img.pixels[j];
float h = hue(c);
float s = saturation(c)*saturationNum[nowUsing]/100;
float b = brightness(c)*brightnessNum[nowUsing]/100;
img.pixels[j] = color(h, s, b);
}
img.updatePixels();
colorMode(RGB);
函数
计算机的建议看书自学,下面只是简单介绍下
点击查看代码
/*返回类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, ...) {
// 函数体
}
*/
void main(String[]args){
// 函数体
}
/*这个就是函数的形式,返回值类型就是使用函数后所留下的值
比如 x = sin(0), sin()就是一个函数,其中0就是参数,返回的值就是sin(0)的值0
所以 x被赋上了0的值
参数列表中的变量用于接收调用该函数或方法时传递的值,使得函数能够根据外部提供的数据执行特定的操作。
在实践中就会知道的,应篇幅原因大头放在代码思路,不懂建议百度
*/
//使用就是
main();
//main里面的代码就会执行啦
那先来介绍不同于JAVA的部分,没有了main(),而是setup()和draw()
其实还有个settings()
执行一遍的setup,我们要来做什么呢?
简而言之就是初始化,设置背景,加载图片,构建对象,初始化数组等等一次性功能都可以放上去。
void setup() {
size(800, 600); // 创建一个 800x600 像素的窗口
// 加载图片和字体
//在同文件夹下面就行,一般是放在名字为data的子文件夹下
img = loadImage("myImage.jpg");
font = createFont("Arial", 32);
// 设置颜色模式
colorMode(HSB, 360, 100, 100);
// 设置背景颜色
background(240, 80, 60); // 使用 HSB 模式设置背景色为蓝色,中等饱和度,低亮度
//设置回来
colorMode(RGB);
// 设置文本
textFont(font);
fill(255);
noStroke();
// 打印一条消息到控制台作为Debug
println("Setup completed.");
}
void draw() {
// 主循环代码放在这里
//可以用loop(),noLoop()来优化循环,节省资源,但是我懒所以我的代码都没这样做。
//详细点的请看代码实现
}
关于map()、constrain()等等函数可以自行了解,我觉得用map实现百分比,constrain实现限制挺不错的。
代码实现思路
先规划好程序整体框架,哪个部分是图片展示,哪个部分是tip区,哪个部分是操作区等等
等你队友画好图再开始写一些判定的指令,然后写一些效果的实现
注释打在函数体里,介绍函数功能和参数列表的变量的含义
尽量有tip,display,work三个区
而且从写代码前就分开,写代码时也互不影响
林瀚和要的保存我记得是保存display展示的区域,get就行。
判定点
拿到图后敲判定点
if(mouseX > real_x && mouseX < real_x + real_width &&
mouseY > real_y && mouseY < real_y + real_height &&){
//鼠标放上去的操作,比如实现图片动态,出现tip
}
void MousePressed(){
if(mouseX > real_x && mouseX < real_x + real_width &&
mouseY > real_y && mouseY < real_y + real_height &&){
//鼠标点上去的操作,实现什么功能
}
}
切换背景图
重新加载张新图片就行
载入图片、展示图片、保存图片
可以用数组,大小设置大点就是了。用img_cnt记录图片数量
动态数组也行,我就是。
selectInput("Select an image file:", "ImgSelect");
出现一个窗口,"Select an image file:"是窗口标题,"ImgSelect"是调用的函数如下
void ImgSelect(File path) {
//传递了文件path
println("Select the path of the new image you want to use");
if (path == null) {
println("You selected nothing");
return;
}
//将File path转化为String paths,取的是绝对路径
String paths = path.getAbsolutePath();
//图片载入
PImage tmp = loadImage(paths);
if (tmp == null) {
println("Failed to load the new image");
}
else {
println("Loaded image: " + paths);
images.add(tmp);
lastImages.add(tmp);
originalImages.add(tmp);
nowUsing++;
}
println("The new image from " + path);
x[nowUsing] = 250;
y[nowUsing] = 0;
calculateSize();
}
同理保存也可以这么实现用if和boolean分开就行
打印图片可以每次操作打印一次,用一个布尔类型is_act就行。
我没这样做,我懒(*´・ω・`)⊃
把display赛在draw里一直在打印
void display(){
//打印图片
if (nowUsing == -1) return; //跳过当前图片
for(int i = 0; i < images.size(); i++) {
if (i == nowUsing) continue;
//设置效果范围pushMatrix()、popMatrix()
//display_x,display_y 显示区左上点,fine_x,fine_y 合适大小
pushMatrix();
//加载图片、效果处理
image(img, display_x,display_y,fine_w,fine_h);
popMatrix();
}
//设置效果范围pushMatrix()、popMatrix()
//display_x,display_y 显示区左上点,fine_x,fine_y 合适大小
pushMatrix();
//加载当前图片、效果处理
image(img, display_x,display_y,fine_w,fine_h);
popMatrix();
}
滑条
样子自己用两个矩形手搭建一个吧,一个矩形的位置跟着变动就行。
拖动就是弄个布尔变量dragging在mouseDragged()根据位置改变值就行,判定还挺难打的。
图片效果
- 旋转:rotate()
- 移动:改变坐标
- 截切:get()获取PImage就行
- 放缩:
PImage的resize方法很可以,或者scale()
但是很可怕的一点,rotate和scale都会改变坐标系,怎么变回来请读者自证
PImage.filter()是很重要的一个实现
filter(kind)
filter(kind, param)
kind:这是你想要应用的效果类型。它可以是以下预定义常量之一:
THRESHOLD:将图像转换为黑白二值图像,使用可选参数作为阈值(0.0 到 1.0)。默认值为 0.5。
GRAY:将图像转换为灰度图像。
INVERT:反转图像的颜色。
OPAQUE:使图像中的透明部分变为不透明。
BLUR:应用高斯模糊效果。可选参数控制模糊的程度,默认值为 1。
ERODE:减少亮区域的大小,通常用来消除小的亮点。
DILATE:增加亮区域的大小,通常用来增强图像中的亮点。
param:这是一个可选参数,某些滤镜效果需要额外的参数来调整其强度或特性,如上述提到的 THRESHOLD 和 BLUR。
高级策略
Graphics()
使用Graphics可以用来实现多图层,我没怎么用的上大家可以自己想想。
文字一个图层,不同图片不同图层这样子的。
贴两个介绍
https://vimsky.com/examples/usage/processing-PGraphics-pr.html
https://processing.org/reference/pgraphics
controlp5
在 Processing IDE 中安装,导入ControlP5 库,
林瀚和这个xx,最后一节课才给你讲,服了。通宵把几个可能有用的对象学了一下,AI给的东西基本都是和JAVA混在一起了,你要想学明白只能看examples。
我用这个实现了一个图像编辑器,在资源分享里。
Download controlP5
- [1]Open Processing.
- [2]Follow the Sketch -> Import Library -> Add Library
- [3]Search ControlP5 and install it.
初始化
import controlP5.*;
ControlP5 cp5;
void setup() {
size(888, 888);
cp5 = new ControlP5(this); // 初始化 ControlP5
}
构建按钮
cp5.addButton("Load") //增加对象
.setPosition(70, 5) //设置位置,左上角
.setSize(110, 110) //判定大小
.setImage(loadIcon) //增加图片,可以没有,按钮上的就是label了
.setLabel("Load"); //重新给label命名,不是给对象命名
//获取按钮的label并进行设置。
cp5.getController("Load")
.getCaptionLabel()
.setFont(createFont("Arial", 30)) //Front
.align(ControlP5.CENTER, ControlP5.CENTER) //位置
构建滑条(有2维的可以自己摸索)
//和按钮几乎同理
cp5.addSlider("slider")
.setPosition(10,30)
.setSize(230,40)
.setRange(0,360)
.setValue(0)
;
//“slider”是滑条名字,下面代码来自官方样例
//改变滑条名字label
cp5.getController("slider")
.getValueLabel()
.align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE)
.setPaddingX(0);
//改变滑条值label
cp5.getController("slider")
.getCaptionLabel()
.align(ControlP5.RIGHT, ControlP5.BOTTOM_OUTSIDE)
.setPaddingX(0);
窗口
可以用java带的窗口或processing自带的窗口实现更friendly的交互。
资源分享
要借鉴随便,查重能过就行
通过网盘分享的文件:资源分享
链接: https://pan.baidu.com/s/1kHhoRknMwbB0phsjGCTYuw?pwd=DICU 提取码: DICU
骂人
点击查看代码
写这段的理由是为了纪念神人林汉翮,程序写了段introduction他说字太多没人会看,进界面又说会有看不懂操作的人,呃呃那我introduction写了干嘛,后面全删了呃呃。
林汉翮,在交草案的前一节课教你最有用的 controlP5 结果教出来还是一坨的人。到最后发现这些都不重要,重要的是你的界面和code风格能不能让他满意。举他女儿12岁做的程序玩具来说所有人都能做到真给我整乐了,我10岁在乡下自学JAVA做好了个仓库管理系统,15岁在高中做个介绍黑茶app加pre也没给你上嘴脸啊。有些东西没教就问你会不会,这个我认,大学是自学的地方,但我说我会你又说怎么没用,说我不会又要叫你怎么不会自学真忍不了。
请新同学们注意,他就是个类人,为什么不顺从他呢。你写的程序必须让这个智力明显低于一般水平的人看的懂,每个地方要详细到泰迪都会用,建议摆烂,反正又有会干代码的人被他气乐的。这东西还有叫到,服了。真当每个学生都是程序员,我又不是计科的?PUA牛魔呢,真气乐了。建议别学,ai跑跑得了,对之后没有一点用。
希望他代码水平比嘴上强。能21天自学实现他这要求那为啥不去大厂上班呢,问我难道这是你一个做的吗我只能呃呃,毕竟我只有0.5个人做这个。
学完后你发现啥都没学到。没提前学过其他程序的真的听得懂他的建议吗。这么多人摆烂连程序都看不懂他不知道是他的问题?任务好做点会有人找外包?羡慕纯零基础努力三周学这个东西认认真真自己写代码,结果还要被说的同学,太爽了。
如果你觉得口气重了确实是我的问题,毕竟3天来我睡两小时拯救两组人,今晚估计又是个不眠夜。

浙公网安备 33010602011771号