窗口界面代码如下:
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中图片透明度设置。先得到原图的每一个像素点信息,再赋值给新的图片对 象,再创建新图对象时,透明度可设置
* 经测试大图片这样做很慢,因此这里开了三个线程同时渲染
* @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 futureTask1 = new FutureTask(() -> {
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 futureTask2 = new FutureTask(() -> {
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 futureTask3 = new FutureTask(() -> {
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