[疯狂Java]AWT:位图传送(内存镜像/缓冲)

处理BufferedImage的工具类(Swing用) 帮助你在Swing图像处理上得心应手的 BufferedImage 图像处理工具类 阅读详情

1. AWT位图处理机制:

    1) 如果AWT只能绘制简单的几何图形那会显得过于单调,因此AWT允许绘制位图,可以将位图作为组件的外观;

    2) AWT表现位图的机制:

         i. 因为位图比较复杂,最好是一次性画到屏幕上,比如之前讲过的例子,如果位图里有两条线,那么你一次将两条线同时画到屏幕上一定要比分别画两条线到屏幕上要快很多;

         ii. 因此位图必须先在内存/显卡中先准备花(即先在内存中“画”好),然后一次性冲刷到屏幕上;

         iii. 总结:即位图采用内存传送的机制,必须现在内存中画好,然后一次性传送到屏幕上显示;

    3) 那么关键问题就是如何在内存中“画”位图呢?我们知道在屏幕上画图直接用Graphics类对象就行了,那内存里也可以用Graphics吗?答案是可以的,我们知道在MFC中设备环境CDC的绘制对象可以不停变化,可以在屏幕绘图、在打印机内存中绘图、直接在内存中绘图等等,Graphics也一样,在paint、update中获得的g就是屏幕环境,而通过BufferedImage类的getGraphics方法获得的对象g就是内存环境了,可以通过g调用和屏幕Graphics相同的绘图方法在内存中绘图,只不过在内存中绘制的并不是真实的图像,而仅仅是图像的数据表示,但不过调用的方法都还是一样的,这在AWT底层隐藏了两者的区别而已;


2. 使用BufferedImage在内存中绘制位图:

    1) 位图在AWT中对应的类是Image类,只不过该类是一个纯抽象类,因为没有实用价值,要绘制位图就必须使用Image的子类BufferedImage;

    2) 顾名思义BufferedImage就是缓冲位图的意思,即它所表示的位图存在于内存中,等到位图在内存中绘制完毕后再通过其他方法将其刷到屏幕上显示;

    3) 构造器:BufferedImage(int width, int height, int imageType); // 前两个参数表示位图的宽和高

    4) imageType是BufferedImage定义的静态常量,表示用什么方式绘制位图,共有两种,一种是TYPE_INT_RGB(4字节三原色),另一种是TYPE_BYTE_GRAY(单字节灰度值);

    5) 但是构造器仅仅就是定义了一个内存中的位图对象,仅仅就是开辟了一个内存镜像而已,但什么都没有画,是一个空的位图,要绘制图形就必须使用BufferedImage的getGraphics方法得到内存环境设备描述符:Graphics getGraphics(); // 返回的对象就是可以直接在内存中绘图的Graphics对象了

!!绘图时跟屏幕Graphics没有任何区别,什么drawLine之类的完全一样,只不过不是画在屏幕上,而是画在内存镜像中;


3. 位图传送:

    1) 内存镜像中的位图已经画好了,就等待传送至屏幕上显示了;

    2) 位图要绘制在哪个组件中就调用那个组件的屏幕Graphics的drawImage方法即可,将准备好的BufferedImage作为该方法的参数传入即可,就直接将内存镜像传送至屏幕了;

    3) 原型:boolean Graphics.drawImage(Image img, int x, int y, ImageObserver observer);

         i. img就是要传送到屏幕上的位图,直接传BufferedImage的对象即可;

         ii. (x, y)就是位图在组件中的坐标(组件左上角为原点);

         iii. observer是位图传送时的监督者,监督正在传送的时候内存中的位图是否还正在绘制,这是什么意思呢?就是说有些应用程序要求极高的绘图效率,因此可能会采用多线程绘图,比如内存中已经绘制了1/2了,还有剩下1/2没画好,那么就先将前1/4线冲到屏幕上,就是要如此高效的利用CPU时间,尽量减少等待,因此内存绘图和位图传送就使用两个线程进行,因此有可能遇到传送比绘制更快的情形,即要绘制的那个像素点仍然还在改变(被绘制),因此遇到这种冲突是drawImage就会返回false并终端drawImage方法,正常情况下就返回true;

         iv. 这里我们先不用多线程,因此没有监督者,该参数传null即可,这是就默认单线程,即必须等待内存镜像画完后才能传送;


4. 示例:手绘程序

    1) 秘诀就是MouseMotionListener监听器的mouseDragged方法,在鼠标拖拽时会触发该方法,可以利用MouseEvent的getX和getY方法获取拖拽轨迹上的坐标,根据改坐标画线,由于拖拽时触发该事件的事件间隔非常短,每段间隔画一条线,连起来就无限近似曲线了,非常和谐;

    2) 只不过画线是画在内存镜像中的,而每画一条线就进行一次位图传送,对,这非常低效,但仅仅是为了演示位图传送罢了;

public class AwtTest extends WindowAdapter {
	
	private Frame f = new Frame("Hand Draw");

	private final int DRAW_WIDTH = 500;
	private final int DRAW_HEIGHT = 400;
	private DrawCanvas drawArea = new DrawCanvas();
	private BufferedImage bufImg = new BufferedImage(DRAW_WIDTH, DRAW_HEIGHT, BufferedImage.TYPE_INT_RGB);
	private Graphics gmm = bufImg.getGraphics();
	private Color foreColor = new Color(255, 0, 0); // 当前画笔的颜色
	class DrawCanvas extends Canvas {

		@Override
		public void paint(Graphics g) { // 通过位图传送的方式将图像传送至画布在屏幕上显示
		// 因此我们的手绘程序其实并不是直接在屏幕上手绘,而是现在内存中手绘,然后传送至屏幕
			// TODO Auto-generated method stub
			// super.paint(g);
			g.drawImage(bufImg, 0, 0, null);
		}

	}
	
	private PopupMenu pop = new PopupMenu();
	private MenuItem red = new MenuItem("red");
	private MenuItem green = new MenuItem("green");
	private MenuItem blue = new MenuItem("blue");
	
	// 上一次鼠标拖动事件发生时鼠标的位置
	private int preX = -1;
	private int preY = -1;
	
	public void init() {
		f.addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				// super.windowClosing(e);
				System.exit(0);
			}
			
		});
		
		drawArea.addMouseMotionListener(new MouseMotionAdapter() {

			@Override
			public void mouseDragged(MouseEvent e) {
				// TODO Auto-generated method stub
				// super.mouseDragged(e);
				if (preX > 0 && preY > 0) { // 如果上次鼠标拖动的终点已存在
					gmm.setColor(foreColor); // 那就直接在内存中画线(要先设置当前颜色,可能已经通过右键菜单改变)
					gmm.drawLine(preX, preY, e.getX(), e.getY());
				}
				
				// 将本次拖拽的终点记录下来
				preX = e.getX();
				preY = e.getY();
				
				drawArea.repaint(); // 画好后进行位图传送
				// 这里的策略是画一条传送一次,效率仍然很低,因为要求实时显示画线轨迹,这里只是为了演示位图传送而已
			}
			
		});
		
		drawArea.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseReleased(MouseEvent e) {
				// TODO Auto-generated method stub
				// super.mouseReleased(e);
				if (e.isPopupTrigger()) {
					pop.show(drawArea, e.getX(), e.getY());
				}
				
				// 鼠标松开意味着可能发生了两种事件的一种
				// 第一种就是右键松开,表示弹出右键菜单,即上面的代码
				// 另一种就是画图键(左键)松开,表示一段手绘的结束
				// 这两种事件都意味着一段手绘的结束,为了重新开始下一段手绘要把preX和preY初始化
				preX = -1;
				preY = -1;
			}
			
		});
		
		ActionListener menuListener = e -> {
			if (e.getActionCommand().equals("red")) {
				foreColor = new Color(255, 0, 0);
			}
			else if (e.getActionCommand().equals("green")) {
				foreColor = new Color(0, 255, 0);
			}
			else if (e.getActionCommand().equals("blue")) {
				foreColor = new Color(0, 0, 255);
			}
		};
		red.addActionListener(menuListener);
		green.addActionListener(menuListener);
		blue.addActionListener(menuListener);
		
		f.add(drawArea);
			drawArea.setPreferredSize(new Dimension(DRAW_WIDTH, DRAW_HEIGHT));
			gmm.fillRect(0, 0, DRAW_WIDTH, DRAW_HEIGHT); // 初始时默认背景色为白色
			drawArea.add(pop);
				pop.add(red);
				pop.add(green);
				pop.add(blue);
				
		f.pack();
		f.setVisible(true);
	}

	public static void main(String[] args) {
		new AwtTest().init();
	}

}


Java OpenCV开发——图像镜像翻转 主要使用OpenCV的flip()方法,可以实现图像的垂直、水平以及同时垂直镜像翻转。    flip是Core的静态方法,用法为:    public static void flip(Mat src, Mat dst, int flipCode)    参数说明:   src:输入图像;   dst:输出图像;   flipCode:     = 0 图像向下翻转 阅读详情

相关推荐

Java工程师转型AI开发:从CRUD到机器学习的实战指南

机器学习作为人工智能的核心技术,正在重塑软件开发范式。其核心原理是通过数据训练模型实现预测与决策,相比传统编程更强调概率思维和数据驱动。在工程实践中,Python因其丰富的AI生态成为主流工具,但Java工程师的工程化能力仍是宝贵资产。通过微服务架构、嵌入式推理等混合开发模式,可以实现Java与Python技术栈的优势互补。典型应用场景包括金融风控、推荐系统等,其中特征工程和模型部署是关键挑战。本文基于作者转型经验,详解如何将Spring Boot工程能力与scikit-learn等框架结合,构建可落地的A

weixin_34152820的博客 415

图像垂直镜像

图像垂直镜像 x1=x0 y1=h-y0 import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; /** * 图像垂直镜像 * x1=x0 * y1=h-y0 * */ public class ch5_4 { public static void main(Stri.

qq_44729518的博客 858

Java 图片镜像翻转源码

通过将图片解析成二维数组,然后对二维数组一维数组逆序,进而实现镜像翻转

2、AWT介绍

AWT是Swing的前身,我们使用AWT学习底层的实现而用Swing来画一些界面AWT:抽象的窗口工具(Abstract Windows Tools),包含了很多的类和接口!用于GUI编程,GUI:图形用户界面编程AWT包含了各种各样的元素:窗口、按钮、文本框。

nytcjsjboss的博客 348

用java学画图,显示轨迹,实现双缓冲效果

理解画图时,Graphics对象从哪里来的,画到什么地方去,如何实现画图时显示轨迹,代码简单,但搞懂简单的代码后,对其他的理解就非常方便,适合初学者.

java AWT实现简单画图器(可打开、保存、清除界面、选择颜色等)

java实现画图编辑器,主要实现的功能有,线,圆,矩形(读者可自己添加),以及图像的保存,打开,画笔颜色的选择

Java实现图片的镜像处理

一 获取网络图片并实现流的输出 /** * 获取网络图 * * @param url * @return */ public static BufferedImage downloadImage(String url) throws Exception { log.info("下载网络图片:" + url); byte[] bytes = HttpsUtils.getBytes(url); Inpu

calm_encode的博客 1236

状态错误CS0234命名空间“Windows”中不存在类型或命名空间名“Management”(是否缺少程序集引用?)

解决源码编译UE打包失败问题

五百零一 2338

java image zoom_java图片基本操作-缩放,旋转,镜像,拼接

/*** 缩放*/public static void zoomByScale(BufferedImage bufImage, double scale) throwsIOException {//获取缩放后的长和宽int _width = (int) (scale *bufImage.getWidth());int _height = (int) (scale *bufImage.getHeig...

weixin_36068796的博客 355

IMU、INS、GNSS与组合导航:从原理到工程实践全解析

在自动驾驶、无人机和机器人等智能系统的定位方案中,IMU、INS、GNSS和组合导航常被混为一谈,但它们在硬件层级、数据特性和误差机制上截然不同。IMU作为惯性测量单元,以百赫兹以上频率输出加速度和角速度;INS基于IMU完成姿态、速度与位置的递推解算,却因积分累积误差而随时间漂移;GNSS提供绝对位置,但易受遮挡和干扰。组合导航通过卡尔曼滤波将两者融合,实现短期不飘、长期不偏的连续定位,这正是高精度导航系统的技术底座。工程落地时,从IMU标定、Allan方差分析到相机/LiDAR与IMU外参标定,再到松耦

weixin_29193259的博客 383

Pipeline更多理解

Pipe 类型用途VIGVideo Image Generator:用于图层显示,支持 scaling、rotationRGB简单图层显示,较低优先级DMA主要用于 writeback / WFD / composition output,即从 framebuffer 输出到外部设备(或 memory)Cursor小图层,用于显示指针等很可能是:分别用于主屏、仪表、虚拟显示的输出路径或者用于不同的 display 去做 GPU_TARGET / writeback 的拷贝你看到的意思。

Damon_X的博客 1053

java AWT处理位图

Image抽象类和BufferedImage实现类 Image类代表位图,但它是一个抽象类,无法直接创建Image对象,为此java为它提供了一个BufferedImage子类,这个子类是一个可以访问图像类据缓冲区的Image实现类。构造方法: BufferedImage(int width, int height, int imageType):创建指定大小,指定图像类型的BufferedIm

若有博文对您有帮助,欢迎点赞关注,收藏评论。 867

医疗器械软件测试输出内容(1)

*单元测试(Unit Testing):**单元测试是软件测试的最底层,用于验证软件中最小的可测试单元——函数、方法或模块。系统测试是在集成测试之后进行的,它对整个系统进行测试,验证系统在不同部分集成在一起后是否满足需求和规格。: 集成测试是在单元测试之后进行的,它关注不同单元之间的交互和集成。对于不同安全级别的软件(IEC 62304 A类、B类、C类),在体系上要求输出的文件内容有所区别。**说明:**将集成测试和软件系统测试合并为一项单一的计划和一组活动是可接收的。

ct745363083的博客 1867

Java中AWT、Swing与SWT三大GUI技术的原理与效率差异

MineHe原创看了一下对Java GUI讨论的帖子,所以写了一篇文章来阐述一下各种GUI技术的优劣。Java世界中,目前最知名的三大GUI库分别是:1、AWT(Abstract Window Toolkit)抽象窗口工具包库,包含于所有的Java SDK中2、Swing高级图形库,包含于Java2 SDK中3、来自IBM Eclipse开源项目的SWT(Standard Widget Toolk

远方 3144

5G物理层基础知识

1、关于RB和RE (1) RB(Resource Block,资源块)频率上连续12个子载波,时域上一个slot(时隙,14个ofdm符号) (2) RE(Resource Element,资源单元)频率上一个子载波,及时域上一个ofdm符号 注意:协议规定,5G每个时隙(非扩展CP)的符号数为14个(扩展CP情况下每个时隙有12个符号),而LTE(非扩展CP)每个时隙的符号数为7个。 简单说:一个12X14的方格,大的整个叫一个RB,每一个小块叫一个RE。另外,一个RE可存放一个调制符号(mo.

qq_39074243的博客 2万+

linux入侵排查-综合日志分析

2.分析攻击者首次成功登录web管理后台的时间 还可以知道攻击者可能是通过10.2.4.11这个跳板服务器跳过来的,然后我们继续排查,可以发现日志中POST请求大多都是1047字节,然后往后大多是300字节,POST请求的响应状态码有200和302这两个,其中的302是爆破成功后持续爆破产生的日志,再1047字节和300字节中间夹着一个978字节,就是200响应和302响应的中间。7.分析攻击者留下的持久化后门的时间和后门执行情况 排查计划任务,发现有一个计划任务还是被加密的,应该是反弹shell的。

chinese_cabbage0的博客 644

图片镜像翻转 Java

前言 开发软件时,icon有时候找不到对应的翻转图,所以我借鉴了网上一段程序来进行翻转 代码 import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class ImageMirror { publi...

ALEX的博客 3779

24、JavaFX MP3 音频播放器开发详解

本文详细介绍了如何使用JavaFX开发一个功能丰富的MP3音频播放器,涵盖文件拖放加载、音频播放控制、音频频谱可视化、进度定位滑块等核心功能,并提供了完整的代码实现和解析。适合希望学习JavaFX多媒体应用开发的开发者参考。

wind6的博客 170

Java中Image的水平翻转、缩放与自由旋转操作

bufferedimage.getColorModel().getTransparency()以获得原始图片透明度用于生成缓存图,在缓存图进行相应操作即可。 /** * 旋转图片为指定角度 * * @param bufferedimage * 目标图像 * @param degree *

z69183787的专栏 1万+

uniapp - 超详细的 H5 公众号网页微信登录示例代码,提供从 0-1 公众号配置及详细注释代码(站在新手小白的角度)第三方微信授权登录的实现!!

uniapp微信浏览器H5授权微信登录,UniApp开发H5接入微信登录的全过程,uniapp的H5页面使用微信登录,uniapp H5微信授权登录,H5之微信授权登陆 (uniapp网页版微信授权登录),uni-app开发H5第三方微信授权登录的实现,uniapp如何实现微信授权登录,公众号H5页面接入微信登录流程,uni-app - 最详细 H5 网页接入微信登录功能,提供公众号配置与详细注释示例代码(移动端网页实现点击登录按钮后 调用微信公众号授权登录功能 详细讲解接入流程与详细示例代码)官方最新超级

✅ 精选推荐文章 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

图片镜像水平翻转,垂直翻转以及顺时针,逆时针旋转

let image = board.image! //水平翻转 let flipImageOrientation = (image.imageOrientation.rawValue + 4) % 8 let flipImage = UIImage(CGImage: image.CGImage!, scale: image.scale, orientation: UIImageOrien

鬼谷传人的博客 1万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java之BufferedImage简谈

转载地址:http://blog.163.com/yuhua_kui/blog/static/9679964420139118203818/ 1. 创建一个BufferedImage对象import java.awt.Frame;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Grap

beijixingtianyake的专栏 2626

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

使用Java实现双缓冲绘图

使用Java实现双缓冲绘图当我们使用AWT或Swing绘图时,如果绘制的图像刷新太快,会出现屏闪现象,如之前写的俄罗斯方块小游戏,屏闪现象就很明显。虽然这种闪烁不会给程序的效果造成太大的影响,但给程序的使用者造成了些许不便,针对这种现象,我们大都是采取双缓冲的方式来解决的。双缓冲是计算机动画处理中的传统技术,在用其他语言编程时也可以实现。导致屏闪的原因拿上一篇文章中的俄罗斯方块来说明。当创建窗体对象

小明的专栏 1万+

Java内存图以及堆、栈、常量区、静态区、方法区的区别

如果是一个类里面的静态成员变量和静态成员方法,它是存储在方法区的,静态成员变量是在方法区的静态域里面,而静态成员方法是在方法区的class二进制信息里面(.class文件和方法区里面的二进制信息不一样,读取.class文件按照虚拟机需要的格式存储在方法区。这种格式包括数据结构方面),静态成员和静态成员方法使用时不用创建对象,即类加载初始化后就可以使用,并且是线程共享的。通过图中分析,很多问题也能够迎

Marvel__Dead 胡艺宝的博客 2万+
上一篇: [疯狂Java]AWT:绘图、动画
下一篇: [疯狂Java]AWT:位图IO
Lirx_Tech
博客等级 码龄12年 215粉丝 148原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值