javafx设置图片透明度(饱和度,亮度同理)

  • Post author:
  • Post category:java


窗口界面代码如下:

public class ImageOpsTest extends Application {

	@Override
	public void start(Stage primaryStage) {

		// 创建Image和ImageView对象
		Image image = new Image("/2.PNG");
		ImageView imageView = new ImageView();

		//改变图片透明度
		WritableImage wImage = new ImageUtil().imgOpacity(image, 0.05);

		// 在屏幕上显示图像
		imageView.setImage(wImage);
		StackPane root = new StackPane();
		root.getChildren().add(imageView);
		Scene scene = new Scene(root);
		
		//stage和scene透明设置
		primaryStage.initStyle(StageStyle.TRANSPARENT);
		scene.setFill(Paint.valueOf("#ffffff00"));
		
		
		primaryStage.setTitle("My Test");
		primaryStage.setScene(scene);
		primaryStage.show();
	}

	public static void main(String[] args) {
		launch(args);
	}
}

设置图片透明度代码:(你可能会想尝试修改每个像素的颜色或者透明度并将其写到屏幕上。但是要注意Image对象是只读的,要写入新的数据,你需要一个WritableImage对象来替代之)

public class ImageUtil {

	public static Image backGroundImg;

	/**
	 * @Description javafx中图片透明度设置。先得到原图的每一个像素点信息,再赋值给新的图片对        象,再创建新图对象时,透明度可设置<br>
	 *              经测试大图片这样做很慢,因此这里开了三个线程同时渲染
	 * @param image 需要 改变透明度的图片对象
	 * @param opacity 透明度,介于0-1之间
	 * @return 新的可写的image对象
	 * @author LIu Mingyao
	 */
	public WritableImage imgOpacity(Image image, double opacity) {
        // 获取PixelReader
		PixelReader pixelReader = image.getPixelReader();

		// 创建WritableImage
		WritableImage wImage = new WritableImage((int) image.getWidth(), (int) image.getHeight());
		PixelWriter pixelWriter = wImage.getPixelWriter();
        	 // 单线程更改透明度,得到每个坐标像素点的color,并重新设值,赋予透明度,最后将新color设给新的image对象(wImage的pixelWriter)
		 for (int readY = 0; readY < image.getHeight(); readY++) {
		         for (int readX = 0; readX < image.getWidth(); readX++) {
		             Color color = pixelReader.getColor(readX, readY);
		             System.out.println("\nPixel color at coordinates (" + readX + "," +             
		 readY + ") "+ color.toString());
		             System.out.println("R = " + color.getRed());
		             System.out.println("G = " + color.getGreen());
		             System.out.println("B = " + color.getBlue());
		             System.out.println("Opacity = " + color.getOpacity());
		             System.out.println("Saturation = " + color.getSaturation());
		
		             // 现在写入一个更为明亮的颜色到PixelWriter中
		             // color = color.brighter();
		
		             // 更暗
		             // color.darker();
		
		             // 最后一个参数是透明设置。需要设置透明不能改变原来的,只能重新创建对象赋值,
		             Color c1 = new Color(color.getRed(), color.getGreen(), color.getBlue(), opacity);
		
		             pixelWriter.setColor(readX, readY, c1.brighter());
		         }
		 }
            return wImage;
	}
}

上面代码经过测试大图片写入会比较慢,因此开线程来同时写入(由于国内javafx资料较少,并且本人也是学习阶段,没有找到其他方法改变透明度,可能这种方法比较笨。),开线程改变图片信息的代码如下:

package application.utils;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

import javafx.scene.image.Image;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;

/**
 * @Description 图片处理
 * @author LIu Mingyao
 * @date 2019年4月7日下午1:10:30
 */
public class ImageUtil {

	public static Image backGroundImg;

	/**
	 * @Description javafx中图片透明度设置。
	 *          
	 * @param image 需要 改变透明度的图片对象
	 * @param opacity 透明度,介于0-1之间
	 * @return 新的可写的image对象
	 * @author LIu Mingyao
	 */
	public WritableImage imgOpacity(Image image, double opacity) {

		if (opacity < 0 || opacity > 1) throw new MarsException("透明度需要介于0-1之间,请重新设置透明度!");

		// 获取PixelReader
		PixelReader pixelReader = image.getPixelReader();

		// 创建WritableImage
		WritableImage wImage = new WritableImage((int) image.getWidth(), (int) image.getHeight());
		PixelWriter pixelWriter = wImage.getPixelWriter();

		double imgHeight = image.getHeight();
		double tempHeight = imgHeight % 3;
		// 将原来的单个线程改变透明度(下面注释的代码)改为了三个线程,解决了大图片更改透明度缓慢的问题
		FutureTask<Boolean> futureTask1 = new FutureTask<Boolean>(() -> {
			for (int readY = 0; readY < tempHeight; readY++) {
				for (int readX = 0; readX < image.getWidth(); readX++) {
					Color color = pixelReader.getColor(readX, readY);
					// 最后一个参数是透明设置。需要设置透明不能改变原来的,只能重新创建对象赋值,
					Color c1 = new Color(color.getRed(), color.getGreen(), color.getBlue(),
							opacity);

					pixelWriter.setColor(readX, readY, c1.brighter());
				}
			}
			return true;
		});
		new Thread(futureTask1, "第一个透明度渲染线程").start();

		FutureTask<Boolean> futureTask2 = new FutureTask<Boolean>(() -> {
			for (int readY = (int) tempHeight; readY < 2 * tempHeight; readY++) {
				for (int readX = 0; readX < image.getWidth(); readX++) {
					Color color = pixelReader.getColor(readX, readY);
					Color c1 = new Color(color.getRed(), color.getGreen(), color.getBlue(),
							opacity);
					pixelWriter.setColor(readX, readY, c1.brighter());
				}
			}

			return true;
		});
		new Thread(futureTask2, "第二个透明度渲染线程").start();
		FutureTask<Boolean> futureTask3 = new FutureTask<Boolean>(() -> {
			for (int readY = (int) (2 * tempHeight); readY < imgHeight; readY++) {
				for (int readX = 0; readX < image.getWidth(); readX++) {
					Color color = pixelReader.getColor(readX, readY);
					Color c1 = new Color(color.getRed(), color.getGreen(), color.getBlue(),
							opacity);
					pixelWriter.setColor(readX, readY, c1.brighter());
				}
			}

			return true;
		});
		new Thread(futureTask3, "第三个透明度渲染线程").start();
//		 // 单线程更改透明度,得到每个坐标像素点的color,并重新设值,赋予透明度,最后将新color设给新的image对象(wImage的pixelWriter)
//		 for (int readY = 0; readY < image.getHeight(); readY++) {
//		 for (int readX = 0; readX < image.getWidth(); readX++) {
//		 Color color = pixelReader.getColor(readX, readY);
//		 System.out.println("\nPixel color at coordinates (" + readX + "," + readY + ") "
//		 + color.toString());
//		 System.out.println("R = " + color.getRed());
//		 System.out.println("G = " + color.getGreen());
//		 System.out.println("B = " + color.getBlue());
//		 System.out.println("Opacity = " + color.getOpacity());
//		 System.out.println("Saturation = " + color.getSaturation());
//		
//		 // 现在写入一个更为明亮的颜色到PixelWriter中
//		 // color = color.brighter();
//		
//		 // 更暗
//		 // color.darker();
//		
//		 // 最后一个参数是透明设置。需要设置透明不能改变原来的,只能重新创建对象赋值,
//		 Color c1 = new Color(color.getRed(), color.getGreen(), color.getBlue(), opacity);
//		
//		 pixelWriter.setColor(readX, readY, c1.brighter());
//		 }
//		 }

//这部分代码可以自主选用。用了可以保证全部图片全部刷新完再展示,不然图片是先渲染上部分,再是中下部分
//		try {
//			// 等待三个线程全部执行完毕
//			if (futureTask1.get() && futureTask2.get() && futureTask3.get()) {
//				backGroundImg = wImage;
//			}
//		} catch (InterruptedException | ExecutionException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		return wImage;
	}
}

想要改变图片其他信息同理,只是选用的Color的构造器不同。官方api:

官方Color api



版权声明:本文为qq_40695278原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。