Toolkit.getDefaultToolkit().getImage(...) 方法应该是有缓存的

本文介绍了如何使用Toolkit.getDefaultToolkit().getImage()方法加载图片,并通过MediaTracker确保图片加载完成后再进行操作。同时,文章提供了解决图片加载延迟问题的方法,并演示了如何将图片从源路径移动到目标路径,包括图片加载、刷新和删除原始文件的过程。
部署运行你感兴趣的模型镜像

Toolkit.getDefaultToolkit().getImage(...) 方法可接受 String 或者是 URL 参数,用以指定图像文件的路径。
如果图片路径是不变的,那么该方法返回的 Image 对象就会是最开始那一个,除非你重启了应用。

public static void main(String[] args){
		//a.jpg  473*209  b.jpg 98*113
		imgCache("D:\\dps\\demo\\a.jpg", "D:\\dps\\demo\\b.jpg");
	}
	public static void imgCache(final String srcImgFilePath,final String destImgFilePath){
			Image img=null;
			try{
				img= Toolkit.getDefaultToolkit().getImage(srcImgFilePath);
				//如果图片过大,可能会出现延迟,为了防止这种情况发生我们可以在图片完全被加载进来
				MediaTracker mediaTracker = new MediaTracker(new Container());
				mediaTracker.addImage(img, 0);
				mediaTracker.waitForID(0);
			}catch(InterruptedException ex){
				System.out.println("解析"+srcImgFilePath+" 图片出错,出错原因:"+ex.getMessage());
			}
			System.out.println("width:"+img.getWidth(null)+" height:"+img.getHeight(null));
			//删除图片
			File aImgFilePath=new File(srcImgFilePath); 
			if(aImgFilePath.exists()){
				aImgFilePath.delete();
			}
			//重命名 
			File  bImgFilePath=new File(destImgFilePath);
			bImgFilePath.renameTo(aImgFilePath);
			//读取b.jpg 图片
			try{
				img= Toolkit.getDefaultToolkit().getImage(srcImgFilePath);
				//如果图片过大,可能会出现延迟,为了防止这种情况发生我们可以在图片完全被加载进来
				MediaTracker mediaTracker = new MediaTracker(new Container());
				mediaTracker.addImage(img, 0);
				mediaTracker.waitForID(0);
			}catch(InterruptedException ex){
				System.out.println("解析"+srcImgFilePath+" 图片出错,出错原因:"+ex.getMessage());
			}
			System.out.println("width:"+img.getWidth(null)+" height:"+img.getHeight(null));
	}

 

解决办法:
 查询jdkAPi,最后通过对返回的 Image 调用 flush 方法,可以手动丢弃以前加载的信息

img= Toolkit.getDefaultToolkit().getImage(srcImgFilePath);
img.flush();
 

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

private static void creatFrame() { try { robot = new Robot(); } catch (AWTException e) { e.printStackTrace(); } // ========== 1. 创建主窗口 ========== JFrame mainFrame = new JFrame("电脑杀毒(自动采集)"); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 使用BorderLayout,左侧采集区域,右侧控制面板 mainFrame.setLayout(new BorderLayout()); // 采集画面原始分辨率 int originalWidth = 1920; int originalHeight = 1080; double aspectRatio = 16.0 / 9.0; // 修正:考虑标题栏高度的窗口尺寸计算 int captureDisplayWidth = 800; // 左侧采集区域显示宽度 int captureDisplayHeight = 450; // 左侧采集区域显示高度 (800×450 = 16:9) int rightPanelWidth = 200; // 右侧面板宽度(根据图片估算) // 窗口内容区域尺寸 int contentWidth = captureDisplayWidth + rightPanelWidth; int contentHeight = captureDisplayHeight; // 设置窗口内容区域尺寸 mainFrame.setSize(contentWidth, contentHeight); // 修正:获取窗口Insets(边框和标题栏尺寸) mainFrame.pack(); Insets insets = mainFrame.getInsets(); int totalWindowWidth = contentWidth + insets.left + insets.right; int totalWindowHeight = contentHeight + insets.top + insets.bottom; // 重新设置窗口尺寸(包含标题栏和边框) mainFrame.setSize(totalWindowWidth, totalWindowHeight); mainFrame.setLocationRelativeTo(null); // ========== 2. 左侧:采集区域(动态保持16:9比例) ========== JFXPanel fxPanel = new JFXPanel(); // 创建采集容器 - 关键:使用AspectRatioPanel保持16:9比例 JPanel captureContainer = new JPanel(new BorderLayout()) { @Override public Dimension getPreferredSize() { // 获取父容器可用空间 Container parent = getParent(); if (parent != null) { int availableWidth = parent.getWidth(); int availableHeight = parent.getHeight(); // 计算保持16:9比例的最大尺寸 int width, height; // 方案1:优先保证宽度填充,允许上下留白 width = availableWidth; height = (int) (width / aspectRatio); // 如果计算出的高度超过可用高度,则采用方案2:优先保证高度填充,允许左右留白 if (height > availableHeight) { height = availableHeight; width = (int) (height * aspectRatio); } return new Dimension(width, height); } return new Dimension(captureDisplayWidth, captureDisplayHeight); } }; captureContainer.setBackground(Color.BLACK); // 使用包装面板实现居中显示(允许留白时居中) JPanel captureWrapper = new JPanel(new GridBagLayout()); captureWrapper.setBackground(Color.BLACK); captureWrapper.add(captureContainer); // 确保JFXPanel填充整个采集容器 fxPanel.setLayout(new BorderLayout()); captureContainer.add(fxPanel, BorderLayout.CENTER); // 将采集包装器添加到左侧 mainFrame.add(captureWrapper, BorderLayout.CENTER); // ========== 3. 右侧:控制面板(自适应高度) ========== JPanel rightPanel = new JPanel(); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS)); rightPanel.setBackground(new Color(245, 245, 245)); rightPanel.setBorder(BorderFactory.createEmptyBorder(15, 10, 15, 10)); rightPanel.setPreferredSize(new Dimension(rightPanelWidth, contentHeight)); mainFrame.add(rightPanel, BorderLayout.EAST); // ========== 4. 控制面板内容(精确匹配图片) ========== // Administrator标签 JLabel adminLabel = new JLabel("Administrator", JLabel.CENTER); adminLabel.setFont(new Font("微软雅黑", Font.BOLD, 14)); adminLabel.setAlignmentX(Component.CENTER_ALIGNMENT); adminLabel.setMaximumSize(new Dimension(Short.MAX_VALUE, 25)); rightPanel.add(adminLabel); rightPanel.add(Box.createRigidArea(new Dimension(0, 15))); // QQ= 标签和输入框 JPanel qqPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); qqPanel.setBackground(new Color(245, 245, 245)); qqPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 30)); JLabel qqLabel = new JLabel("QQ="); qqLabel.setFont(new Font("微软雅黑", Font.BOLD, 14)); JTextField qqField = new JTextField(10); qqField.setFont(new Font("微软雅黑", Font.PLAIN, 14)); qqField.setHorizontalAlignment(JTextField.LEFT); qqPanel.add(qqLabel); qqPanel.add(qqField); rightPanel.add(qqPanel); rightPanel.add(Box.createRigidArea(new Dimension(0, 20))); // 当前角色 JPanel currentRolePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0)); currentRolePanel.setBackground(new Color(245, 245, 245)); currentRolePanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 35)); JLabel currentRoleLabel = new JLabel("当前角色:"); currentRoleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); Constant.text_jusse_now_num = new JTextField("1"); Constant.text_jusse_now_num.setFont(new Font("微软雅黑", Font.BOLD, 14)); Constant.text_jusse_now_num.setHorizontalAlignment(JTextField.CENTER); Constant.text_jusse_now_num.setPreferredSize(new Dimension(50, 25)); currentRolePanel.add(currentRoleLabel); currentRolePanel.add(Constant.text_jusse_now_num); rightPanel.add(currentRolePanel); rightPanel.add(Box.createRigidArea(new Dimension(0, 10))); // 所有角色 JPanel allRolePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0)); allRolePanel.setBackground(new Color(245, 245, 245)); allRolePanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 35)); JLabel allRoleLabel = new JLabel("所有角色:"); allRoleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); JTextField allRoleValue = new JTextField("27"); allRoleValue.setFont(new Font("微软雅黑", Font.BOLD, 14)); allRoleValue.setHorizontalAlignment(JTextField.CENTER); allRoleValue.setPreferredSize(new Dimension(50, 25)); allRoleValue.setEditable(false); allRoleValue.setBackground(new Color(245, 245, 245)); allRolePanel.add(allRoleLabel); allRolePanel.add(allRoleValue); rightPanel.add(allRolePanel); rightPanel.add(Box.createRigidArea(new Dimension(0, 25))); // 测试功能按钮 JButton testButton = new JButton("测试功能"); testButton.setFont(new Font("微软雅黑", Font.BOLD, 16)); testButton.setBackground(new Color(70, 130, 180)); testButton.setForeground(Color.WHITE); testButton.setAlignmentX(Component.CENTER_ALIGNMENT); testButton.setMaximumSize(new Dimension(Short.MAX_VALUE, 40)); testButton.setFocusPainted(false); rightPanel.add(testButton); rightPanel.add(Box.createVerticalGlue()); // ========== 5. 按钮事件处理 ========== testButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // MS2130FXCapture.startCapture(fxPanel); } }); // ========== 6. 窗口设置 ========== // 窗口图标 try { Image icon = Toolkit.getDefaultToolkit() .getImage(new File(Constant.desktopPathImages + "icon.ico").toURI().toURL()); mainFrame.setIconImage(icon); } catch (Exception e) { e.printStackTrace(); } // ========== 7. 关键:窗口缩放时动态调整比例 ========== mainFrame.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { // 获取窗口内容区域尺寸(不含标题栏和边框) int contentWidth = mainFrame.getContentPane().getWidth(); int contentHeight = mainFrame.getContentPane().getHeight(); // 动态计算右侧面板宽度(固定或按比例) int newRightPanelWidth = rightPanelWidth; // 可以改为按比例计算 // 计算采集区域可用宽度 int availableCaptureWidth = contentWidth - newRightPanelWidth; int availableCaptureHeight = contentHeight; // 计算保持16:9比例的采集区域尺寸 int captureWidth, captureHeight; // 优先尝试宽度填充(可能产生上下留白) captureWidth = availableCaptureWidth; captureHeight = (int) (captureWidth / aspectRatio); // 如果高度超出,改为高度填充(可能产生左右留白) if (captureHeight > availableCaptureHeight) { captureHeight = availableCaptureHeight; captureWidth = (int) (captureHeight * aspectRatio); } // 设置采集容器尺寸 captureContainer.setPreferredSize(new Dimension(captureWidth, captureHeight)); captureContainer.revalidate(); captureContainer.repaint(); // 调整右侧面板尺寸 rightPanel.setPreferredSize(new Dimension(newRightPanelWidth, contentHeight)); rightPanel.revalidate(); } }); // 显示窗口 mainFrame.setVisible(true); // 自动开始采集 new Thread(() -> { MS2130FXCapture.startCapture(fxPanel); }).start(); // SwingUtilities.invokeLater(() -> { // MS2130FXCapture.startCapture(fxPanel); // }); } 这是我的creatFrame()方法在dnf类的main方法中执行 package com.dnf.main; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.swing.SwingUtilities; import org.opencv.core.Mat; import org.opencv.videoio.VideoCapture; import org.opencv.videoio.VideoWriter; import org.opencv.videoio.Videoio; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.embed.swing.SwingFXUtils; import javafx.scene.Scene; import javafx.scene.image.ImageView; import javafx.scene.image.WritableImage; import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; import javafx.scene.layout.CornerRadii; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; public class MS2130FXCapture { private static ImageView imageView; private static VideoCapture videoCapture; private static volatile boolean isRunning = false; private static volatile boolean isFXInitialized = false; private static final Lock initLock = new ReentrantLock(); private static Thread captureThread; // 复用对象(兼容Java 8,移除PixelBuffer) private static Mat frameMat = new Mat(); private static BufferedImage bufImg; // 复用缓冲图像 private static WritableImage fxImg; // 复用JavaFX图像 private static byte[] pixelBuffer; // 复用像素数组 /** * 启动采集 */ public static void startCapture(JFXPanel fxPanel) { System.out.println("[自动采集] 开始初始化采集"); if (isRunning) { stopCapture(); } int deviceIndex = findValidDeviceIndex(); if (deviceIndex == -1) { System.err.println("[错误] 未找到MS2130设备"); return; } if (!isFXInitialized) { initLock.lock(); try { if (!isFXInitialized) { System.out.println("[FX初始化] 首次启动JavaFX平台"); SwingUtilities.invokeLater(() -> { Platform.runLater(() -> { try { Platform.startup(() -> { isFXInitialized = true; initFXCapture(fxPanel, deviceIndex); }); } catch (IllegalStateException e) { System.out.println("[FX初始化] 平台已存在,直接绑定"); isFXInitialized = true; initFXCapture(fxPanel, deviceIndex); } }); }); } } finally { initLock.unlock(); } } else { Platform.runLater(() -> initFXCapture(fxPanel, deviceIndex)); } } /** * 初始化UI组件(兼容Java 8) */ private static void initFXCapture(JFXPanel fxPanel, int deviceIndex) { imageView = new ImageView(); imageView.setPreserveRatio(true); imageView.setSmooth(false); // 降低CPU开销 imageView.setCache(false); // 避免内存缓存累积 StackPane root = new StackPane(imageView); root.setBackground( new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, javafx.geometry.Insets.EMPTY))); imageView.fitWidthProperty().bind(root.widthProperty()); imageView.fitHeightProperty().bind(root.heightProperty()); fxPanel.setScene(new Scene(root)); openDeviceAndStartCapture(deviceIndex); } /** * 设备枚举(快速释放资源) */ private static int findValidDeviceIndex() { for (int i = 0; i < 4; i++) { Mat testFrame = new Mat(); try (AutoCloseableVideoCapture testCapture = new AutoCloseableVideoCapture(i)) { VideoCapture capture = testCapture.getVideoCapture(); if (capture.isOpened()) { if (capture.read(testFrame) && !testFrame.empty()) { return i; } } } catch (Exception e) { e.printStackTrace(); } finally { testFrame.release(); } } return -1; } /** * 打开设备并配置参数(兼容低版本OpenCV) */ private static void openDeviceAndStartCapture(int deviceIndex) { if (videoCapture != null) { if (videoCapture.isOpened()) videoCapture.release(); videoCapture = null; } videoCapture = new VideoCapture(deviceIndex + Videoio.CAP_DSHOW); if (!videoCapture.isOpened()) { System.err.println("[错误] 无法打开设备"); return; } // 降低分辨率减少内存占用 videoCapture.set(Videoio.CAP_PROP_FRAME_WIDTH, 1980); videoCapture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 1080); // 兼容低版本OpenCV的编码格式设置 videoCapture.set(Videoio.CAP_PROP_FOURCC, VideoWriter.fourcc('M', 'J', 'P', 'G')); resetReusableObjects(); isRunning = true; captureThread = new Thread(() -> captureAndDisplayLoop()); captureThread.setDaemon(true); captureThread.start(); // videoCapture.release(); } /** * 重置复用对象 */ private static void resetReusableObjects() { if (frameMat != null) { frameMat.release(); frameMat = new Mat(); } bufImg = null; fxImg = null; pixelBuffer = null; } /** * 采集循环(强化资源释放) */ private static void captureAndDisplayLoop() { long lastFrameTime = 0; final long frameInterval = 33; // 30fps while (isRunning) { if (Thread.currentThread().isInterrupted()) break; // 优先抓取最新帧 if (!videoCapture.grab()) { try { Thread.sleep(5); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } continue; } // 释放上一帧内存 if (!frameMat.empty()) { frameMat.release(); } // 读取新帧 if (!videoCapture.retrieve(frameMat) || frameMat.empty()) { try { Thread.sleep(5); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } continue; } // 控制帧率 long currentTime = System.currentTimeMillis(); if (currentTime - lastFrameTime < frameInterval) continue; lastFrameTime = currentTime; // 处理帧(兼容Java 8的图像转换) processFrame(frameMat); } cleanupResources(); System.out.println("[采集线程] 循环结束"); } /** * 处理帧(移除PixelBuffer,用传统方式转换) */ private static void processFrame(Mat mat) { int width = mat.cols(); int height = mat.rows(); int channels = mat.channels(); int bufferSize = width * height * channels; // 复用像素数组 if (pixelBuffer == null || pixelBuffer.length != bufferSize) { pixelBuffer = new byte[bufferSize]; } mat.get(0, 0, pixelBuffer); // 复用BufferedImage(兼容颜色格式) if (bufImg == null || bufImg.getWidth() != width || bufImg.getHeight() != height) { // 用TYPE_3BYTE_BGR兼容OpenCV的BGR格式 bufImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); } // 更新缓冲图像像素 byte[] imgPixels = ((DataBufferByte) bufImg.getRaster().getDataBuffer()).getData(); System.arraycopy(pixelBuffer, 0, imgPixels, 0, bufferSize); // 复用JavaFX图像 if (fxImg == null || fxImg.getWidth() != width || fxImg.getHeight() != height) { fxImg = new WritableImage(width, height); } // 转换为JavaFX图像(兼容Java 8) SwingFXUtils.toFXImage(bufImg, fxImg); // 更新UI Platform.runLater(() -> { if (imageView != null && isRunning) { imageView.setImage(fxImg); } }); } /** * 清理资源 */ private static void cleanupResources() { // 释放OpenCV资源 if (videoCapture != null) { if (videoCapture.isOpened()) videoCapture.release(); videoCapture = null; } if (frameMat != null) { frameMat.release(); frameMat = null; } // 释放Java对象 Platform.runLater(() -> { if (imageView != null) imageView.setImage(null); }); bufImg = null; fxImg = null; pixelBuffer = null; } /** * 停止采集 */ public static void stopCapture() { isRunning = false; if (captureThread != null && captureThread.isAlive()) { captureThread.interrupt(); try { captureThread.join(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } captureThread = null; } cleanupResources(); System.out.println("[停止采集] 资源已释放"); } } 这是MS2130FXCapture.java类 现在有个问题运行程序后,内存占用很快到1200MB一直维持在这里了,怎么优化减少内存的使用,VideoCapture这个对象好像很占用内存怎么释放不需要的之前的帧
最新发布
10-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值