栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【BMP格式函数分析器】java语言数学分析项目

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【BMP格式函数分析器】java语言数学分析项目

一、项目简介:

  先给大家看一下这个小项目的效果:

  运行后生成的pic.bmp图片

  没错,这个项目的主要功能就是通过函数生成对应的图像。

  主要是用到的技术有:IO流、BMP格式分析、面向对象程序设计。

  项目结构如下:

  Main类主要用来测试,剩下的三个类我会在下面一一介绍。

二、项目内容: ① Color类

  众所周知,图片其实就是由像素组成的二维矩阵,那我们肯定就要构建一个Color类表示像素了,图片信息的存储就是一个Color类型二维数组存储。

package www.spd.pic;

public class Color {

	public static final Color BLACK = new Color((byte)0x00, (byte)0x00, (byte)0x00);
	public static final Color RED = new Color((byte)0xff, (byte)0x00, (byte)0x00);
	public static final Color GREEN = new Color((byte)0x00, (byte)0xff, (byte)0x00);
	public static final Color BLUE = new Color((byte)0x00, (byte)0x00, (byte)0xff);


	byte red;
	byte green;
	byte blue;

	
	public Color(byte red, byte green, byte blue) {

		this.red = red;
		this.green = green;
		this.blue = blue;

	}

	
	@Override
	public String toString() {
		int r = red >= 0 ? red : (red + 0x100);
		int g = green >= 0 ? green : (green + 0x100);
		int b = blue >= 0 ? blue : (blue + 0x100);
		return String.format("#%02x%02x%02x", r, g, b);
	}

	
	public byte[] toByteArray() {
		byte[] arr = new byte[3];
		arr[0] = blue;
		arr[1] = green;
		arr[2] = red;
		return arr;
	}

}

② BMP类:

  对于BMP的文件格式分析详见这篇博文,写的很详细,我的项目就是参考了这篇博文:位图(bmp)文件格式分析。

package www.spd.pic;

import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BMP {

	//文件名
	String name;
	//整个BMP文件的大小
	int bfSize;
	//位图的宽度,单位是像素
	int biWidth;
	//位图的高度,单位是像素
	int biHeight;
	//位图全部像素占用的字节数,BI_RGB时可设为0
	int biSizeImage;
	//因为32位的Windows操作系统处理4个字节(32位)的速度比较快,所以BMP的每一行颜色占用的字节数规定为4的整数倍。
	//如果一行颜色有两个像素,共占用6字节,如果要补齐4*2=8字节,就要再加两个0字节。
	//经计算,appendBit = biWidth % 4;
	int appendBytes;
	//表示一行像素真正占多少字节,即本身要占的字节加上补齐字节
	int widthBytes;

	//图片的像素信息
	Color[][] pixelsMatrix;

	public BMP(String path) {
		this(new File(path));
	}

	
	public BMP(File file) {

		
		name = file.getName();
		Pattern p = Pattern.compile(".*\.bmp");
		Matcher m = p.matcher(name);
		if (!m.find()) throw new IllegalArgumentException("文件后缀不正确!!");

		
		byte[] arr = getByteArray(file);

		if (arr == null) throw new IllegalArgumentException("文件为空文件!!");

		
		int bfType = byteArrayToInteger(arr, 1, 0);
		if (bfType != 0x4d42) throw new IllegalArgumentException("文件受损!!");

		bfSize = byteArrayToInteger(arr, 0x5, 0x2);
		biWidth = byteArrayToInteger(arr, 0x15, 0x12);
		biHeight = byteArrayToInteger(arr, 0x19, 0x16);
		
		
		int biBitCount = byteArrayToInteger(arr, 0x1f, 0x1c);
		if (biBitCount != 24) throw new IllegalArgumentException("图片不是24位真色彩位图!!");

		biSizeImage = byteArrayToInteger(arr, 0x27, 0x24);
		appendBytes = biWidth % 4;
		widthBytes = biWidth * 3 + appendBytes;

		pixelsMatrix = new Color[biHeight][biWidth];

		
		for (int i = 0; i < biHeight; i++) {

			int pixelEnd = (biHeight - i - 1) * widthBytes + 0x36;

			for (int j = 0; j < biWidth; j++) {

				pixelsMatrix[i][j] = new Color(arr[pixelEnd + 2], arr[pixelEnd + 1], arr[pixelEnd]);
				pixelEnd += 3;

			}

		}

	}

	
	public BMP(Color color, String name, int width, int height) {

		this.name = name;
		biWidth = width;
		biHeight = height;
		appendBytes = biWidth % 4;
		widthBytes = biWidth * 3 + appendBytes;
		pixelsMatrix = new Color[biHeight][biWidth];

		
		for (int i = 0; i < biHeight; i++) {
			for (int j = 0; j < biWidth; j++) {
				pixelsMatrix[i][j] = color;
			}
		}

		biSizeImage = widthBytes * height;
		bfSize = biSizeImage + 0x36;

	}

	public BMP(String name, int width, int height) {
		this(new Color((byte)0xff, (byte)0xff, (byte)0xff), name, width, height);
	}

	public BMP(Color color, int width, int height) {
		this(color, "pic.bmp", width, height);
	}

	public BMP(int width, int height) {
		this("pic.bmp", width, height);
	}

	
	@Override
	public String toString() {
		return "BMP{" +
				"ntname="" + name +
				"", ntbfSize=" + bfSize +
				", ntbiWidth=" + biWidth +
				", ntbiHeight=" + biHeight +
				", ntbiSizeImage=" + biSizeImage +
				", ntappendBytes=" + appendBytes +
				", ntwidthBytes=" + widthBytes +
				"n}";
	}

	
	private static byte[] getByteArray(File file) {

		try(BufferedInputStream bis =
					new BufferedInputStream(
							new FileInputStream(file));
			ByteArrayOutputStream baos =
					new ByteArrayOutputStream()) {

			int len = -1;
			byte[] flush = new byte[1024];

			while ((len = bis.read(flush)) != -1) {
				baos.write(flush, 0, len);
				baos.flush();
			}

			return baos.toByteArray();

		} catch (FileNotFoundException e) {

			System.err.println("文件不存在!!");
			return null;

		} catch (IOException e) {

			System.err.println("IO操作出现异常!!");
			e.printStackTrace();
			return null;

		}

	}

	
	private int byteArrayToInteger(byte[] arr, int begin, int end) {

		int ans = 0;
		int temp;

		if (begin <= end) {
			for (int i = begin; i <= end; i++) {
				ans *= 0x100;
				temp = arr[i] >= 0 ? arr[i] : (arr[i] + 128);
				ans += temp;
			}
		}

		if (begin > end) {
			for (int i = begin; i >= end; i--) {
				ans *= 0x100;
				temp = arr[i] >= 0 ? arr[i] : (arr[i] + 128);
				ans += temp;
			}
		}

		return ans;

	}

	
	private byte[] integerToByteArray(int size, int num) {
		byte[] arr = new byte[size];
		int i = 0;
		while (num > 0) {
			byte temp = (byte) (num % 0x100);
			num /= 0x100;
			try {
				arr[i] = temp;
			} catch (IndexOutOfBoundsException e) {
				throw new IllegalArgumentException("数字数值大于2^"+size);
			}
			i++;
		}
		return arr;
	}

	
	public byte[] toByteArray() {
		try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

			baos.write("BM".getBytes());
			baos.write(integerToByteArray(4, bfSize));
			baos.write(new byte[4]);
			baos.write(integerToByteArray(4, 0x36));
			baos.flush();

			baos.write(integerToByteArray(4, 40));
			baos.write(integerToByteArray(4, biWidth));
			baos.write(integerToByteArray(4, biHeight));
			baos.write(integerToByteArray(2, 1));
			baos.write(integerToByteArray(2, 24));
			baos.write(new byte[4]);
			baos.write(integerToByteArray(4, biSizeImage));
			baos.write(new byte[16]);
			baos.flush();

			byte[] append = new byte[appendBytes];

			for (int i = biHeight - 1; i >= 0 ; i--) {

				for (int j = 0; j < biWidth; j++) {
					baos.write(pixelsMatrix[i][j].toByteArray());
				}

				baos.write(append);
				baos.flush();

			}

			return baos.toByteArray();

		} catch (IOException e) {

			System.err.println("IO操作出现异常!!");
			e.printStackTrace();
			return null;

		}
	}

	
	public void createFile() {

		byte[] arr = toByteArray();

		try (FileOutputStream fos = new FileOutputStream(name)) {
			fos.write(arr);
			fos.flush();
		} catch (IOException e) {
			System.err.println("将图像对象写入成图像时出线IO异常!!");
		}

	}

}

③ getPicByFunc类:

  从字面意义上来看:“从函数获得图像类”,它的下面有一个内部接口Functial,即可作为函数的,一个内部类Function,里面有一个Functial对象,和一个Color对象,表示的是一个带颜色的函数。

package www.spd.pic;

public class getPicByFunc {

	public static BMP getPic(Function func, int size) {
		return getPic("pic.bmp", func, size);
	}

	public static BMP getPic(String name, Function func, int size) {
		return getPic(name, new Function[]{func}, size);
	}

	public static BMP getPic(Function[] functions, int size) {
		return getPic("pic.bmp", functions, size);
	}

	
	public static BMP getPic(String name, Function[] functions, int size) {

		BMP pic = new BMP(name, size * 40, size * 40);
		
		
		for (int i = 0; i < size * 40; i++) {

			pic.pixelsMatrix[i][size * 20] = Color.BLACK;
			pic.pixelsMatrix[i][size * 20 - 1] = Color.BLACK;
			pic.pixelsMatrix[size * 20][i] = Color.BLACK;
			pic.pixelsMatrix[size * 20 - 1][i] = Color.BLACK;

			if (i % 20 == 0) {

				pic.pixelsMatrix[i][size * 20 + 1] = Color.BLACK;
				pic.pixelsMatrix[i][size * 20 + 2] = Color.BLACK;
				pic.pixelsMatrix[i][size * 20 - 2] = Color.BLACK;
				pic.pixelsMatrix[i][size * 20 - 3] = Color.BLACK;

				pic.pixelsMatrix[size * 20 + 1][i] = Color.BLACK;
				pic.pixelsMatrix[size * 20 + 2][i] = Color.BLACK;
				pic.pixelsMatrix[size * 20 - 2][i] = Color.BLACK;
				pic.pixelsMatrix[size * 20 - 3][i] = Color.BLACK;

			}

		}

		
		for (Function func : functions) {

			for (int i = 0; i < size * 40; i++) {
				for (int j = 0; j < size * 40; j++) {
					double x = i / 20.0f - size;
					double y = j /20.0f - size;
					if (func.func.func(x, y)) {
						pic.pixelsMatrix[size * 40 - 1 - j][i] = func.color;
					}
				}
			}

		}

		return pic;

	}

	public interface Functial {
		boolean func(double x, double y);
	}

	public static boolean equal(double a, double b) {
		double n = 0.05;
		return -n < (a - b) && (a - b) < n;
	}

	public static class Function {
		
		Functial func;
		Color color;

		public Function(Functial func, Color color) {
			this.func = func;
			this.color = color;
		}

		public Function(Functial func) {
			this.func = func;
			this.color = Color.BLACK;
		}
	}
	
}



  项目到这里就算完成了,让我们来测试一下。

三、项目测试

  写一个Main函数:

package www.spd;

import www.spd.pic.Color;

import static www.spd.pic.getPicByFunc.*;
import static java.lang.Math.*;

public class Main {

	@SuppressWarnings("all")
	public static void main(String[] args) {

		double tau = 0.3;
		int a = 4;

		getPic(new Function[]{
				new Function((x, y) -> equal(pow(x, 2) + pow(y, 2) + a * y, a * sqrt(pow(x, 2) + pow(y, 2))), Color.RED),
				new Function((x, y) -> equal(y, (1 / tau * sqrt(2 * PI)) * exp(-pow(x, 2) / 2 * pow(tau, 2))), Color.GREEN),
				new Function(new Circle(3, 3, 3), Color.BLUE),
				new Function(new Circle(-2, -2, 2), new Color((byte)0x66, (byte)0xcc, (byte)0xff))
				}, 20).createFile();

	}

	public static class Circle implements Functial {

		public final int x;
		public final int y;
		public final int radius;

		@Override
		public boolean func(double x, double y) {
			return equal(pow(x-this.x, 2) + pow(y-this.y, 2), pow(radius, 2));
		}

		public Circle(int x, int y, int radius) {
			this.x = x;
			this.y = y;
			this.radius = radius;
		}
	}

}

  测试运行结果:

  这张bmp格式的图片下面煞风景的有水印,我也不知道怎么去,又想去的可以试试用我做的项目,双层for循环读取像素,若发现有不是#ffffff也不是#0000ff、#00ff00、#ff0000、#66ccff的像素,就把它赋值为#ffffff,就能去水印了。

四、项目的缺点:

  我们来用我这个项目绘制一个抛物线试试:

  很明显,上面成了断点了。这很容易用数学推理出来原因。

  我这个项目生成的是位图而不是矢图,自然就会出现这种状况,解决方案就是生成矢图,但那样就没有意思了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/328387.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号