奇迹暖暖年轻的春游3.:[JAVA]读取BMP图像,
来源:百度文库 编辑:偶看新闻 时间:2024/05/04 17:47:32
http://www.tanei.com/thread-845-1-1.html1 程序功能
1.1 读取24位的bmp格式的图像
1.2 对图像进行过滤,只显示RGB中的一个通道以及显示成灰度图像
1.3 将图像保存为JPG格式的图像
2 实现过程
2.1 读取BMP格式的图像
2.1.1 图像信息类
由于BMP格式的图像前54个字节都是用来存储图像信息,包括图像宽度、高度、大小等等,因此可以构建图像信息类来读取并存储图像的信息。
public class ImageHead
{
private int width;
private int height;
private int bitcount;
private int size;
public ImageHead(FileInputStream stream)
{
try
{
byte bh[] = new byte[bfhead];
byte bi[] = new byte[bfinfo];
stream.read(bh, 0, bfhead);
stream.read(bi, 0, bfinfo);
//图像宽度
width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
| ( ( (int) bi[6] & 0xff) << 16)
| ( ( (int) bi[5] & 0xff) << 8)
| (int) bi[4] & 0xff;
//图像高度
height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
| ( ( (int) bi[10] & 0xff) << 16)
| ( ( (int) bi[9] & 0xff) << 8)
| (int) bi[8] & 0xff;
//图像位数
bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
//图像大小
size = ( ( (int) bi[23] & 0xff) << 24)
| ( ( (int) bi[22] & 0xff) << 16)
| ( ( (int) bi[21] & 0xff) << 8)
| (int) bi[20] & 0xff;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
}
复制代码
2.1.2 构建位数组
由于像素使用的字节若不是4的倍数,则会自动扩大,由此产生空白。因此我们需要在一开始计算出空白的大小,即
int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
复制代码
由此构建数组如下
byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
复制代码
2.1.3 读取BMP格式的图像
使用stream.read(brgb, 0, (img.width + blank) * 3 * img.height);读入图像后使用toolkit生成图像:
Toolkit kit = Toolkit.getDefaultToolkit();
image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
复制代码
2.2 过滤图像,单通道显示
2.2.1 RGBImageFilter类派生
JAVA中存在用于过滤图像的专用类RGBImageFilter,我们只需要对其进行派生即可。
2.2.2 红绿蓝单通道显示
对于每一个像素单元,由三个字节存储RGB三色,还有一个字节用于存储透明度。四个字节的排序为 透明度-红-绿-蓝,由于是16进制并且透明度不改变,因此可以用形如0xffffffff过滤器与色素相与得到指定通道。
红色:0xffff0000
绿色:0xff00ff00
蓝色:0xff0000ff
2.2.3 灰度显示
与单通道显示不同的是,灰度显示本质上是红绿蓝三通道为同一值,从而让灰度存在255阶。
简单的方法是直接选出某一通道,例如红色,覆盖掉其他通道的颜色值从而使得图像显示成灰色。然而这样选取的问题在于,对于一幅红色为0或255的图像,无论蓝色绿色为何,过滤后的图像只会是白色或黑色。
比较好的一种算法是:红色值*0.3+绿色值*0.59+蓝色值*0.11,将得到的值赋予每个通道从而得到灰度值。此种算法的优点在于综合了各个通道,从而避免极端情况。
int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);
2.3 存储为JPG格式
存储为JPG格式我们使用了JAVA的API接口ImageIO实现。由于要使用ImageIO只能将内存中的缓存图像写入文件,因此要先生成缓存图像BufferedImage将图像“画”到其中:
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
复制代码
最后使用ImageIO写入
ImageIO.write(bi, "jpg", imgFile);
复制代码
自己写的ImageIO类
public class MyImageIO implements IImageIO
{
private static int bfhead = 14;
private static int bfinfo = 40;
public class ImageHead
{
private int width;
private int height;
private int bitcount;
private int size;
public ImageHead(FileInputStream stream)
{
try
{
byte bh[] = new byte[bfhead];
byte bi[] = new byte[bfinfo];
stream.read(bh, 0, bfhead);
stream.read(bi, 0, bfinfo);
width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
| ( ( (int) bi[6] & 0xff) << 16)
| ( ( (int) bi[5] & 0xff) << 8)
| (int) bi[4] & 0xff;
height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
| ( ( (int) bi[10] & 0xff) << 16)
| ( ( (int) bi[9] & 0xff) << 8)
| (int) bi[8] & 0xff;
bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
size = ( ( (int) bi[23] & 0xff) << 24)
| ( ( (int) bi[22] & 0xff) << 16)
| ( ( (int) bi[21] & 0xff) << 8)
| (int) bi[20] & 0xff;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
}
public Image myRead(String filePath)
{
try
{
Image image;
FileInputStream stream = new FileInputStream(filePath);
ImageHead img = new ImageHead(stream);
int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
int data[] = new int[img.height * img.width];
byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
if (img.bitcount == 24)
{
stream.read(brgb, 0, (img.width + blank) * 3 * img.height);
int nindex = 0;
for (int j = 0; j < img.height; j++)
{
for (int i = 0; i < img.width; i++)
{
data[img.width * (img.height - j - 1) + i] =
(255 & 0xff) << 24
| ( ( (int) brgb[nindex + 2] & 0xff) << 16)
| ( ( (int) brgb[nindex + 1] & 0xff) << 8)
| (int) brgb[nindex] & 0xff;
nindex += 3;
}
nindex += blank;
}
}
Toolkit kit = Toolkit.getDefaultToolkit();
image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
return image;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
return (Image)null;
}
public Image myWrite(Image image, String filePath)
{
try
{
File imgFile = new File(filePath + ".jpg");
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
ImageIO.write(bi, "jpg", imgFile);
return image;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
return image;
}
}
复制代码
ImageProcess 图像处理,包括RGB单通道颜色以及灰度
public class ImageProcessor implements IImageProcessor
{
public Image showChanelR(Image sourceImage)
{
RedFilter filter = new RedFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
public Image showChanelG(Image sourceImage)
{
GreenFilter filter = new GreenFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
public Image showChanelB(Image sourceImage)
{
BlueFilter filter = new BlueFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
public Image showGray(Image sourceImage)
{
GrayFilter filter = new GrayFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
class RedFilter extends RGBImageFilter
{
public RedFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
return (rgb & 0xffff0000);
}
}
class GreenFilter extends RGBImageFilter
{
public GreenFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
return (rgb & 0xff00ff00);
}
}
class BlueFilter extends RGBImageFilter
{
public BlueFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
return (rgb & 0xff0000ff);
}
}
class GrayFilter extends RGBImageFilter
{
public GrayFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);
return (rgb & 0xff000000)+(gray<<16)+(gray<<8)+gray;
}
}
}
复制代码
1.1 读取24位的bmp格式的图像
1.2 对图像进行过滤,只显示RGB中的一个通道以及显示成灰度图像
1.3 将图像保存为JPG格式的图像
2 实现过程
2.1 读取BMP格式的图像
2.1.1 图像信息类
由于BMP格式的图像前54个字节都是用来存储图像信息,包括图像宽度、高度、大小等等,因此可以构建图像信息类来读取并存储图像的信息。
public class ImageHead
{
private int width;
private int height;
private int bitcount;
private int size;
public ImageHead(FileInputStream stream)
{
try
{
byte bh[] = new byte[bfhead];
byte bi[] = new byte[bfinfo];
stream.read(bh, 0, bfhead);
stream.read(bi, 0, bfinfo);
//图像宽度
width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
| ( ( (int) bi[6] & 0xff) << 16)
| ( ( (int) bi[5] & 0xff) << 8)
| (int) bi[4] & 0xff;
//图像高度
height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
| ( ( (int) bi[10] & 0xff) << 16)
| ( ( (int) bi[9] & 0xff) << 8)
| (int) bi[8] & 0xff;
//图像位数
bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
//图像大小
size = ( ( (int) bi[23] & 0xff) << 24)
| ( ( (int) bi[22] & 0xff) << 16)
| ( ( (int) bi[21] & 0xff) << 8)
| (int) bi[20] & 0xff;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
}
复制代码
2.1.2 构建位数组
由于像素使用的字节若不是4的倍数,则会自动扩大,由此产生空白。因此我们需要在一开始计算出空白的大小,即
int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
复制代码
由此构建数组如下
byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
复制代码
2.1.3 读取BMP格式的图像
使用stream.read(brgb, 0, (img.width + blank) * 3 * img.height);读入图像后使用toolkit生成图像:
Toolkit kit = Toolkit.getDefaultToolkit();
image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
复制代码
2.2 过滤图像,单通道显示
2.2.1 RGBImageFilter类派生
JAVA中存在用于过滤图像的专用类RGBImageFilter,我们只需要对其进行派生即可。
2.2.2 红绿蓝单通道显示
对于每一个像素单元,由三个字节存储RGB三色,还有一个字节用于存储透明度。四个字节的排序为 透明度-红-绿-蓝,由于是16进制并且透明度不改变,因此可以用形如0xffffffff过滤器与色素相与得到指定通道。
红色:0xffff0000
绿色:0xff00ff00
蓝色:0xff0000ff
2.2.3 灰度显示
与单通道显示不同的是,灰度显示本质上是红绿蓝三通道为同一值,从而让灰度存在255阶。
简单的方法是直接选出某一通道,例如红色,覆盖掉其他通道的颜色值从而使得图像显示成灰色。然而这样选取的问题在于,对于一幅红色为0或255的图像,无论蓝色绿色为何,过滤后的图像只会是白色或黑色。
比较好的一种算法是:红色值*0.3+绿色值*0.59+蓝色值*0.11,将得到的值赋予每个通道从而得到灰度值。此种算法的优点在于综合了各个通道,从而避免极端情况。
int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);
2.3 存储为JPG格式
存储为JPG格式我们使用了JAVA的API接口ImageIO实现。由于要使用ImageIO只能将内存中的缓存图像写入文件,因此要先生成缓存图像BufferedImage将图像“画”到其中:
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
复制代码
最后使用ImageIO写入
ImageIO.write(bi, "jpg", imgFile);
复制代码
自己写的ImageIO类
public class MyImageIO implements IImageIO
{
private static int bfhead = 14;
private static int bfinfo = 40;
public class ImageHead
{
private int width;
private int height;
private int bitcount;
private int size;
public ImageHead(FileInputStream stream)
{
try
{
byte bh[] = new byte[bfhead];
byte bi[] = new byte[bfinfo];
stream.read(bh, 0, bfhead);
stream.read(bi, 0, bfinfo);
width = ( ( (int) bi[7] & 0xff) << 24) //width of source file
| ( ( (int) bi[6] & 0xff) << 16)
| ( ( (int) bi[5] & 0xff) << 8)
| (int) bi[4] & 0xff;
height = ( ( (int) bi[11] & 0xff) << 24) //heigth of source file
| ( ( (int) bi[10] & 0xff) << 16)
| ( ( (int) bi[9] & 0xff) << 8)
| (int) bi[8] & 0xff;
bitcount = ( ( (int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
size = ( ( (int) bi[23] & 0xff) << 24)
| ( ( (int) bi[22] & 0xff) << 16)
| ( ( (int) bi[21] & 0xff) << 8)
| (int) bi[20] & 0xff;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
}
}
public Image myRead(String filePath)
{
try
{
Image image;
FileInputStream stream = new FileInputStream(filePath);
ImageHead img = new ImageHead(stream);
int blank = ((img.size / img.height) - img.width * 3)/(3 * img.width);
int data[] = new int[img.height * img.width];
byte brgb[] = new byte[ (img.width + blank) * 3 * img.height];
if (img.bitcount == 24)
{
stream.read(brgb, 0, (img.width + blank) * 3 * img.height);
int nindex = 0;
for (int j = 0; j < img.height; j++)
{
for (int i = 0; i < img.width; i++)
{
data[img.width * (img.height - j - 1) + i] =
(255 & 0xff) << 24
| ( ( (int) brgb[nindex + 2] & 0xff) << 16)
| ( ( (int) brgb[nindex + 1] & 0xff) << 8)
| (int) brgb[nindex] & 0xff;
nindex += 3;
}
nindex += blank;
}
}
Toolkit kit = Toolkit.getDefaultToolkit();
image = kit.createImage(new MemoryImageSource(img.width, img.height, data, 0, img.width));
return image;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
return (Image)null;
}
public Image myWrite(Image image, String filePath)
{
try
{
File imgFile = new File(filePath + ".jpg");
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
ImageIO.write(bi, "jpg", imgFile);
return image;
}
catch (Exception e)
{
e.printStackTrace(System.out);
}
return image;
}
}
复制代码
ImageProcess 图像处理,包括RGB单通道颜色以及灰度
public class ImageProcessor implements IImageProcessor
{
public Image showChanelR(Image sourceImage)
{
RedFilter filter = new RedFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
public Image showChanelG(Image sourceImage)
{
GreenFilter filter = new GreenFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
public Image showChanelB(Image sourceImage)
{
BlueFilter filter = new BlueFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
public Image showGray(Image sourceImage)
{
GrayFilter filter = new GrayFilter();
Toolkit kit = Toolkit.getDefaultToolkit();
Image newimg = kit.createImage(new FilteredImageSource(sourceImage.getSource(), filter));
return newimg;
}
class RedFilter extends RGBImageFilter
{
public RedFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
return (rgb & 0xffff0000);
}
}
class GreenFilter extends RGBImageFilter
{
public GreenFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
return (rgb & 0xff00ff00);
}
}
class BlueFilter extends RGBImageFilter
{
public BlueFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
return (rgb & 0xff0000ff);
}
}
class GrayFilter extends RGBImageFilter
{
public GrayFilter()
{
canFilterIndexColorModel = true;
}
public int filterRGB(int x, int y, int rgb)
{
int gray = (int)(((rgb & 0x00ff0000)>>16)*0.3 + ((rgb & 0x0000ff00)>>8)*0.59 + (rgb & 0x000000ff)*0.11);
return (rgb & 0xff000000)+(gray<<16)+(gray<<8)+gray;
}
}
}
复制代码
vc 读取bmp图像尺寸
如何压缩bmp图像?
BMP图像界面
如何上传BMP图像
怎样上传BMP图像?
在java中如何读取图像rgb并输出,希望能给个完整的程序
怎么用BMP图像转成JPEG图像
怎么把BMP图像改成JPEG图像
如何把BMP图像转变成JPG图像
BMP图像和JPEC图像是怎么回事?
怎样把BMP图像转变成jpg图像
BMP图像怎样编程JPEG图像
BMP 图像 转换为 JPEG 图像
BMP 图像 怎么转换成 JPEG 图像
怎样把BMP 图像改变成JPEG 图像?
Bmp图像有什么有点?
单色bmp图像如何制作?
bmp格式图像是什么呀
到哪里上传bmp图像?
BMP图像大小的计算?
vb中的bmp文件数据如何读取!当图像宽度不是4的倍数时,2色图,16色图,256色图如何读图像数据!
怎么把GIF 图像,JPEG 图像转化成bmp图像
图像的读取和保存
怎样把BMP图像转变为文本文档