BitSet转为图片

将BitSet数据转为图片,每位占一个格子,效果如图:

BitSet转为图片

下面是图片实现版本:

package com.acgist.snail.gui.statistics;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.Closeable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.BitSet;
import java.util.Objects;

import javax.imageio.ImageIO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.acgist.snail.utils.NumberUtils;

/**
 * <p>位图工具</p>
 * <p>使用图片实现</p>
 * 
 * @author acgist
 * @since 1.0.0
 */
public final class BitmapPainter implements Closeable {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(BitmapPainter.class);

	/**
	 * <p>默认填充高宽</p>
	 */
	private static final int WH = 16;
	/**
	 * <p>默认列数</p>
	 */
	private static final int COL = 50;
	
	/**
	 * <p>填充高宽</p>
	 */
	private final int wh;
	/**
	 * <p>列数</p>
	 */
	private final int col;
	/**
	 * <p>行数</p>
	 */
	private final int row;
	/**
	 * <p>数据长度</p>
	 */
	private final int length;
	/**
	 * <p>数据</p>
	 */
	private final BitSet bitSet;
	/**
	 * <p>存在填充颜色</p>
	 */
	private final Color fillColor;
	/**
	 * <p>没有填充颜色</p>
	 */
	private final Color noneColor;
	/**
	 * <p>边框颜色</p>
	 */
	private final Color borderColor;
	/**
	 * <p>背景颜色</p>
	 */
	private final Color background;
	/**
	 * <p>图片宽度</p>
	 */
	private int width;
	/**
	 * <p>图片高度</p>
	 */
	private int height;
	/**
	 * <p>图片</p>
	 */
	private BufferedImage image;
	/**
	 * <p>画笔</p>
	 */
	private Graphics2D graphics2d;
	/**
	 * <p>边框高宽</p>
	 */
	private final int borderWh = 1;
	
	private BitmapPainter(BitSet bitSet) {
		this(bitSet.size(), bitSet);
	}

	private BitmapPainter(int length, BitSet bitSet) {
		this(WH, COL, length, bitSet);
	}
	
	private BitmapPainter(int wh, int col, int length, BitSet bitSet) {
		this(
			wh, col, length, bitSet,
			new Color(0, 153, 204),
			new Color(200, 200, 200),
			Color.BLACK, Color.WHITE
		);
	}
	
	private BitmapPainter(
		int wh, int col, int length, BitSet bitSet,
		Color fillColor, Color noneColor, Color borderColor, Color background
	) {
		this.wh = wh;
		this.col = col;
		this.row = NumberUtils.ceilDiv(length, col);
		this.fillColor = fillColor;
		this.noneColor = noneColor;
		this.borderColor = borderColor;
		this.background = background;
		this.length = length;
		this.bitSet = bitSet;
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param bitSet 数据
	 * 
	 * @return 工具
	 */
	public static final BitmapPainter newInstance(BitSet bitSet) {
		return new BitmapPainter(bitSet);
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param length 数据长度
	 * @param bitSet 数据
	 * 
	 * @return 工具
	 */
	public static final BitmapPainter newInstance(int length, BitSet bitSet) {
		return new BitmapPainter(length, bitSet);
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param wh 填充高宽
	 * @param col 列数
	 * @param length 数据长度
	 * @param bitSet 数据
	 * 
	 * @return 工具
	 */
	public static final BitmapPainter newInstance(int wh, int col, int length, BitSet bitSet) {
		return new BitmapPainter(wh, col, length, bitSet);
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param wh 填充高宽
	 * @param col 列数
	 * @param length 数据长度
	 * @param bitSet 数据
	 * @param fillColor 存在填充颜色
	 * @param noneColor 没有填充颜色
	 * @param borderColor 边框颜色
	 * @param background 背景颜色
	 * 
	 * @return 工具
	 */
	public static final BitmapPainter newInstance(
		int wh, int col, int length, BitSet bitSet,
		Color fillColor, Color noneColor, Color borderColor, Color background
	) {
		return new BitmapPainter(wh, col, length, bitSet, fillColor, noneColor, borderColor, background);
	}

	/**
	 * <p>画图</p>
	 * 
	 * @return 工具
	 */
	public BitmapPainter draw() {
		this.build();
		this.drawBackground();
		this.drawBorder();
		this.drawFill();
		return this;
	}
	
	/**
	 * <p>创建基本信息</p>
	 */
	private void build() {
		// 计算高宽
		this.width = this.col * (this.wh + this.borderWh) + this.borderWh; // 列数 * (宽度 + 边框) + 右边框
		this.height = this.row * (this.wh + this.borderWh) + this.borderWh; // 行数 * (高度 + 边框) + 底边框
		// 创建图片和画笔
		this.image = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB);
		this.graphics2d = this.image.createGraphics();
	}

	/**
	 * <p>背景颜色</p>
	 */
	private void drawBackground() {
		this.graphics2d.clearRect(0, 0, this.width, this.height);
		this.graphics2d.setPaint(this.background);
		this.graphics2d.fillRect(0, 0, this.width, this.height);
	}
	
	/**
	 * <p>边框</p>
	 */
	private void drawBorder() {
		this.graphics2d.setPaint(this.borderColor);
		// 列
		final int width = this.wh + this.borderWh;
		int x = 0;
		for (int index = 0; index < this.col; index++) {
			x = index * width;
			this.graphics2d.drawLine(x, 0, x, this.height);
		}
		// 右边框
		this.graphics2d.drawLine(this.width - this.borderWh, 0, this.width - this.borderWh, this.height);
		// 行
		final int height = this.wh + this.borderWh;
		int y = 0;
		for (int index = 0; index < this.row; index++) {
			y = index * height;
			this.graphics2d.drawLine(0, y, this.width, y);
		}
		// 底边框
		this.graphics2d.drawLine(0, this.height - this.borderWh, this.width, this.height - this.borderWh);
	}
	
	/**
	 * <p>填充</p>
	 */
	private void drawFill() {
		int col, row;
		final int wh = this.wh + this.borderWh;
		for (int index = 0; index < this.length; index++) {
			row = index / this.col;
			col = index % this.col;
			if(this.bitSet.get(index)) {
				this.graphics2d.setPaint(this.fillColor);
				this.graphics2d.fillRect(col * wh + this.borderWh, row * wh + this.borderWh, this.wh, this.wh);
			} else {
				this.graphics2d.setPaint(this.noneColor);
				this.graphics2d.fillRect(col * wh + this.borderWh, row * wh + this.borderWh, this.wh, this.wh);
			}
		}
	}
	
	/**
	 * <p>保存图片</p>
	 * 
	 * @param format 图片格式
	 * @param path 图片路径
	 */
	public void write(String format, String path) {
		Objects.requireNonNull(this.image, "没有画图");
		try (final var output = new FileOutputStream(path)) {
			ImageIO.write(this.image, format, output);
		} catch (IOException e) {
			LOGGER.error("保存图片异常:{}-{}", format, path, e);
		}
	}

	@Override
	public void close() throws IOException {
		if(this.graphics2d != null) {
			this.graphics2d.dispose();
		}
	}
	
}

下面是JavaFX画布版本:

package com.acgist.snail.gui.statistics;

import java.util.BitSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.acgist.snail.utils.NumberUtils;

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;

/**
 * <p>位图工具</p>
 * <p>使用画布实现</p>
 * 
 * @author acgist
 * @since 1.0.0
 */
public final class CanvasPainter {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(CanvasPainter.class);

	/**
	 * <p>默认填充高宽</p>
	 */
	private static final int WH = 16;
	/**
	 * <p>默认列数</p>
	 */
	private static final int COL = 50;
	
	/**
	 * <p>填充高宽</p>
	 */
	private final int wh;
	/**
	 * <p>列数</p>
	 */
	private final int col;
	/**
	 * <p>行数</p>
	 */
	private final int row;
	/**
	 * <p>数据长度</p>
	 */
	private final int length;
	/**
	 * <p>数据</p>
	 */
	private final BitSet bitSet;
	/**
	 * <p>存在填充颜色</p>
	 */
	private final Color fillColor;
	/**
	 * <p>没有填充颜色</p>
	 */
	private final Color noneColor;
	/**
	 * <p>边框颜色</p>
	 */
	private final Color borderColor;
	/**
	 * <p>背景颜色</p>
	 */
	private final Color background;
	/**
	 * <p>图片宽度</p>
	 */
	private int width;
	/**
	 * <p>图片高度</p>
	 */
	private int height;
	/**
	 * <p>画布</p>
	 */
	private Canvas canvas;
	/**
	 * <p>画笔</p>
	 */
	private GraphicsContext graphics;
	/**
	 * <p>边框高宽</p>
	 */
	private final int borderWh = 1;
	
	private CanvasPainter(BitSet bitSet) {
		this(bitSet.size(), bitSet);
	}

	private CanvasPainter(int length, BitSet bitSet) {
		this(WH, COL, length, bitSet);
	}
	
	private CanvasPainter(int wh, int col, int length, BitSet bitSet) {
		this(
			wh, col, length, bitSet,
			Color.rgb(0, 153, 204),
			Color.rgb(200, 200, 200),
			Color.BLACK, Color.WHITE
		);
	}
	
	private CanvasPainter(
		int wh, int col, int length, BitSet bitSet,
		Color fillColor, Color noneColor, Color borderColor, Color background
	) {
		this.wh = wh;
		this.col = col;
		this.row = NumberUtils.ceilDiv(length, col);
		this.fillColor = fillColor;
		this.noneColor = noneColor;
		this.borderColor = borderColor;
		this.background = background;
		this.length = length;
		this.bitSet = bitSet;
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param bitSet 数据
	 * 
	 * @return 工具
	 */
	public static final CanvasPainter newInstance(BitSet bitSet) {
		return new CanvasPainter(bitSet);
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param length 数据长度
	 * @param bitSet 数据
	 * 
	 * @return 工具
	 */
	public static final CanvasPainter newInstance(int length, BitSet bitSet) {
		return new CanvasPainter(length, bitSet);
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param wh 填充高宽
	 * @param col 列数
	 * @param length 数据长度
	 * @param bitSet 数据
	 * 
	 * @return 工具
	 */
	public static final CanvasPainter newInstance(int wh, int col, int length, BitSet bitSet) {
		return new CanvasPainter(wh, col, length, bitSet);
	}
	
	/**
	 * <p>创建工具</p>
	 * 
	 * @param wh 填充高宽
	 * @param col 列数
	 * @param length 数据长度
	 * @param bitSet 数据
	 * @param fillColor 存在填充颜色
	 * @param noneColor 没有填充颜色
	 * @param borderColor 边框颜色
	 * @param background 背景颜色
	 * 
	 * @return 工具
	 */
	public static final CanvasPainter newInstance(
		int wh, int col, int length, BitSet bitSet,
		Color fillColor, Color noneColor, Color borderColor, Color background
	) {
		return new CanvasPainter(wh, col, length, bitSet, fillColor, noneColor, borderColor, background);
	}

	/**
	 * <p>画图</p>
	 * 
	 * @return 工具
	 */
	public CanvasPainter draw() {
		this.build();
		this.drawBackground();
		this.drawBorder();
		this.drawFill();
		return this;
	}
	
	/**
	 * <p>创建基本信息</p>
	 */
	private void build() {
		// 计算高宽
		this.width = this.col * (this.wh + this.borderWh) + this.borderWh; // 列数 * (宽度 + 边框) + 右边框
		this.height = this.row * (this.wh + this.borderWh) + this.borderWh; // 行数 * (高度 + 边框) + 底边框
		// 创建画布和画笔
		this.canvas = new Canvas(this.width, this.height);
		this.graphics = this.canvas.getGraphicsContext2D();
	}

	/**
	 * <p>背景颜色</p>
	 */
	private void drawBackground() {
		this.graphics.clearRect(0, 0, this.width, this.height);
		this.graphics.setFill(this.background);
		this.graphics.fillRect(0, 0, this.width, this.height);
	}
	
	/**
	 * <p>边框</p>
	 */
	private void drawBorder() {
		this.graphics.setStroke(this.borderColor);
		this.graphics.setLineWidth(this.borderWh);
		// 列
		final int width = this.wh + this.borderWh;
		int x = 0;
		for (int index = 0; index < this.col; index++) {
			x = index * width;
			this.graphics.strokeLine(x, 0, x, this.height);
		}
		// 右边框
		this.graphics.strokeLine(this.width - this.borderWh, 0, this.width - this.borderWh, this.height);
		// 行
		final int height = this.wh + this.borderWh;
		int y = 0;
		for (int index = 0; index < this.row; index++) {
			y = index * height;
			this.graphics.strokeLine(0, y, this.width, y);
		}
		// 底边框
		this.graphics.strokeLine(0, this.height - this.borderWh, this.width, this.height - this.borderWh);
	}
	
	/**
	 * <p>填充</p>
	 */
	private void drawFill() {
		int col, row;
		final int wh = this.wh + this.borderWh;
		for (int index = 0; index < this.length; index++) {
			row = index / this.col;
			col = index % this.col;
			if(this.bitSet.get(index)) {
				this.graphics.setFill(this.fillColor);
				this.graphics.fillRect(col * wh + this.borderWh, row * wh + this.borderWh, this.wh, this.wh);
			} else {
				this.graphics.setFill(this.noneColor);
				this.graphics.fillRect(col * wh + this.borderWh, row * wh + this.borderWh, this.wh, this.wh);
			}
		}
	}
	
	/**
	 * <p>获取画布</p>
	 * 
	 * @return 画布
	 */
	public Canvas canvas() {
		return this.canvas;
	}
	
}