`
不打伞的蘑菇
  • 浏览: 15538 次
社区版块
存档分类
最新评论

自定义画图板实现与系统bmp图片的打开保存

阅读更多
 
 
 
 

 

 

    在这个项目中,我们利用的是swing开发做出的一个画图板的界面。在界面上实现了画图和保存的功能。但是由于自定义的保存方式导致只能用自定义的打开方式来打开,也就是说,我们用自定义画图板创建的图片别人根本打不开。-_-||

    所以为了与国际接轨,与系统接轨,我们必须要使用系统的打开和保存方式来处理一张图片。以下用bmp格式为例。

    因为bmp图片的保存格式是开源的,我们能简单的知道系统画图板是怎么保存一个bmp格式的图片的。这个网上百度可以搜到。

典型的BMP 图像文件由四部分组成:   

 ① BMP文件头 (14 字节     

   BMP文件头数据结构含有 BMP 文件的类型、文件大小和位图起始位置等信息其结构定义如下

   

 

int bfType; // 位图文件的类型,必须为 ' B '' M '两个字母 (0-1字节 )   
int bfSize; // 位图文件的大小,以字节为单位 (2-5 字节 )   
int bfReserved1; // 位图文件保留字,必须为 0(6-7 字节 )    
int  bfReserved2; // 位图文件保留字,必须为 0(8-9 字节 )   
int  bfOffBits; // 位图数据的起始位置,以相对于位图 (10-13 字节 ) 

 

② 位图信息头(40 字节   

  BMP 位图信息头数据用于说明位图的尺寸等信息。

 

  

int Size; // 本结构所占用字节数 (14-17 字节 )  
int image_width; // 位图的宽度,以像素为单位 (18-21 字节 )   
int image_heigh; // 位图的高度,以像素为单位 (22-25 字节 )  
int Planes; // 目标设备的级别,必须为 1(26-27 字节 )   
int biBitCount;// 每个像素所需的位数,必须是 1(双色), 4(16 色 ) , 8(256 色 ) 或 24(// 真彩色 ) 之一  (28-29 字节)
int biCompression; // 位图压缩类型,必须是 0( 不压缩 ), 1(BI_RLE8 压缩类型 ) 或// 2(BI_RLE4 压缩类型 ) 之一  (30-33 字节 )
int SizeImage; // 位图数据的大小,以字节为单位 (34-37 字节 )   
int biXPelsPerMeter; // 位图水平分辨率,每米像素数 (38-41 字节 )   
int biYPelsPerMeter; // 位图垂直分辨率,每米像素数 (42-45 字节 )   
int biClrUsed;// 位图实际使用的颜色表中的颜色数 (46-49 字节 )   
int biClrImportant;// 位图显示过程中重要的颜色数 (50-53 字节 )

 

  3、调色板 ,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24 位的 BMP )就不需要调色板。所以,想当然,我选的是不需要调色板的24位的。所以下面做保存的时候直接跳过啦。  

 

class  BITMAPINFO {   
BITMAPINFOHEADER bmiHeader; // 位图信息头   
RGBQUAD bmiColors[1]; // 颜色表   
} 

 

      4、位图数据 ,这部分的内容根据BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB ,而其他的小于 24 位的使用调色板中颜色索引值。

 

准备完成,下面是写代码阶段。

 

首先得swing界面中添加画布和菜单栏,对画布实现鼠标监听器,对菜单项实现事件监听器。然后在画布监听器中,实现鼠标按下,拖动,释放的方法,写的简陋,就只实现了这三个方法。在这个监听器中,我们把鼠标对画布的操作保存在缓存中,使用int数组保存一张图片中所有的像素点,在监听器的构造方法中初始化这个画图为白色。

public static int array[][]; //定义数组保存图片的像素点
   public DrawListener(JPanel panel){
      This.panel=panel;
      Dimension dim=panel.getPreferredSize();
      array=new int[dim.height][dim.width];
      for(int i=0;i<array.length;i++){
          for(int j=0;j<array[i].length;j++){
          //画布初始化,设置画布为白色
          array[i][j]=Color.WHITE.getRGB();
          }
      }
}

 

在鼠标监听器里面,鼠标按下拖动的方法里面可以画连续的线段,可是,当你把画图板最小化在重新打开时你会发现你先前画的线条都没有了。这个怎么解决呢?办法是把这张图片的像素已经保存在电脑缓存中,在释放的方法里面把画布中的像素点保存在int数组当中,然后在每一次重新调用这个面板的时候(比如最小化后再打开就是一次重新调用)重绘这个画布中的像素点。如下面的代码所示:

public void mouseReleased(MouseEvent e) {
		//当鼠标释放的时候保存
		Point p=panel.getLocationOnScreen();
		Dimension dim=panel.getPreferredSize();
		Rectangle rect=new Rectangle(p,dim);
		BufferedImage img=robot.createScreenCapture(rect);
		array=new int[img.getHeight()][img.getWidth()];
		for(int i=0;i<array.length;i++){
				for(int j=0;j<array[i].length;j++){
                              //遍历图片的宽高,把图片的像素点保存在int数组中,图片的宽高和数组的下表是相反的。
				array[i][j]=img.getRGB(j, i);
			}
		}
	}

 

 

 

public void paint(Graphics g) {
			super.paint(g);
			for(int i=0;i<DrawListener.array.length;i++){
				for(int j=0;j<DrawListener.array[i].length;j++){
					g.setColor(new Color(DrawListener.array[i][j]));
                                      //重新绘制保存好的int数组中的像素。
				        g.drawLine(j, i, j, i);
			}
		}
	}

 

此时,自定义的画图板实现了简陋的绘画的功能了,接下来就遇到一开始说的问题了,画完之后的如何保存到硬盘中,并且让系统的画图软件也能打开我们保存的图片呢?实际上,我们在电脑上看到的图片真的是一张图片吗?不是的,它只是一组数据的集合。只是画图软件能知道怎么把这组数据还还原成一张图片显示在画图板中而已。

接下来,以bmp24位保存格式为例。

首先是如何打开一个bmp格式的图片,这个先在自己系统的画图板中画好,并以bmp24位的格式保存。而从前面我们已经能够知道它是怎么个保存方法了。只要读取到我们所需要的图片的高度和宽度还有每一个点的像素点就能在自定义的画图板中把图片显示出来了。

 

 

FileInputStream  fis=new FileInputStream(file1);
			fis.skip(18);
			int width=changeInt(fis);//跳过不需要的,读取宽度和高度
			int height=changeInt(fis);
			fis.skip(28);
                       //跳过,直接读取位图数据。
			DrawListener.array=new int[height][width];
			int t=0;
			if(width*3%4>0){
				t=4-width*3%4;
			}
			for(int i=height-1;i>=0;i--){
				for(int j=0;j<width;j++){
                               //调用自定义方法,得到图片的像素点并保存到int数组中
					int c=readColor(fis);
					DrawListener.array[i][j]=c;
				}
				fis.skip(t);
			}
			fis.close();
                       //刷新,重绘面板,打开系统保存的图片。
			panel.setPreferredSize(new Dimension(width, height));
			SwingUtilities.updateComponentTreeUI(panel);

 

       //由于读取的是字节,把读取到的4个byte转化成1个int
       public int changeInt(FileInputStream ips) throws IOException{
		int t1=ips.read() & 0xff;
		int t2=ips.read() & 0xff;
		int t3=ips.read() & 0xff;
		int t4=ips.read() & 0xff;
		int num=(t4<<24)+(t3<<16)+(t2<<8)+t1;
		System.out.println(num);
		return num;
	}
       //24位的图片是1个像素3个字节。
	public int readColor(FileInputStream ips) throws IOException{
		int b=ips.read() & 0xff;
		int g=ips.read() & 0xff;
		int r=ips.read() & 0xff;
		int c=(r<<16)+(g<<8)+b;
		return c;
	}

 

     以上就完成打开的操作了,保存图片比打开图片复杂一点,不过也只要你依据正确的存储方式把数据存储起来系统的画图板就能识别你保存的数据打开你的图片了。部分代码如下。

              if("savebmp".equals(commend)){
			FileOutputStream fos=new FileOutputStream(file2);
			savebmpTop(fos);
			savebmpInfo(fos);
			savebmpDate(fos);
			fos.flush();
			fos.close();
		}

 

          public void savebmpTop(OutputStream ops) throws Exception{
		ops.write('B');
		ops.write('M');
		int height=DrawListener.array.length;
		int width=DrawListener.array[0].length;
		int size=14+40+height*width*3+(4-width*3%4)*height;
		//位图文件的大小				
                size=14+40+hight*width*3+(4-width*3%4)*255
		writeInt(ops,size);
		writeShort(ops,(short) 0);
		writeShort(ops,(short) 0);
		writeInt(ops,54);
	}

 

       public void savebmpInfo(OutputStream ops) throws Exception{
		int height=DrawListener.array.length;
		int width=DrawListener.array[0].length;
		writeInt(ops,40);
		writeInt(ops,width);
		writeInt(ops,height);
		writeShort(ops, (short) 1);
		writeShort(ops, (short) 24);
		writeInt(ops,0);
		writeInt(ops,height*width*3+(4-width*3%4)*height);
		writeInt(ops,0);
		writeInt(ops,0);
		writeInt(ops,0);
		writeInt(ops,0);
	}

 

      public void savebmpDate(OutputStream ops) throws Exception{
		int height=DrawListener.array.length;
		int width=DrawListener.array[0].length;
		int m=0;
		if(width*3%4>0){
			m=4-width*3%4;
		}
		for(int i=height-1;i>=0;i--){
			for(int j=0;j<width;j++){
				int t=DrawListener.array[i][j];
				writeColor(ops,t);
			}
			for(int k=0;k<m;k++){
			ops.write(0);
		        }
		}
	}

 

        public void writeInt(OutputStream ops,int t) throws Exception{
		int a=(t>>24)&0xff;
		int b=(t>>16)&0xff;
		int c=(t>>8)&0xff;
		int d=t&0xff;
		ops.write(d);
		ops.write(c);
		ops.write(b);
		ops.write(a);
	}
	public void writeColor(OutputStream ops,int t) throws Exception{
		int b=(t>>16)&0xff;
		int c=(t>>8)&0xff;
		int d=t&0xff;
		ops.write(d);
		ops.write(c);
		ops.write(b);
	}
	public void writeShort(OutputStream ops,short t) throws Exception{
		int c=(t>>8)&0xff;
		int d=t&0xff;
		ops.write(d);
		ops.write(c);
	}

 

至此,整个保存bmp24位格式的代码就写完了,虽然只是部分代码,但还是感觉很多啊╮(╯▽╰)╭。每次我都是写完之后才感觉整个项目的难度系数不大。本项目就是系统是C语言的存储的字节使用Java处理起来有点小复杂而已。掌握了整个bmp格式的数据结构其实很容易实现。

1
1
分享到:
评论

相关推荐

    仿XP画图板

    5. **文件操作**:保存和打开图像文件是画图板的重要功能。JAVA提供了文件I/O流,使得开发者能够读写BMP、PNG等图像文件格式。 6. **颜色选择器**:实现颜色选择器可能需要自定义组件或使用已有的库,允许用户选取...

    C#画图板程序

    - **颜色选择器**:用户可以选择填充和线条颜色,这通常通过调用系统对话框或自定义颜色选择界面实现。 - **线条宽度调整**:用户可以改变画笔的宽度,程序需要提供相应的设置选项。 7. **设计模式**: - **命令...

    GDI+画图板程序

    本项目是一个使用GDI+编写的画图板程序,对于想要学习GDI+基础和实践操作的人来说,这是一个很好的起点。 GDI+的主要功能包括: 1. **图形绘制**:GDI+提供了丰富的绘图工具,如线条、曲线、矩形、椭圆、多边形等...

    VB画图板 用户图形界面设计

    7. **保存和加载**:为了保存用户的画作,开发者可能实现了保存(SaveFileDialog)和加载(OpenFileDialog)功能,将图片以位图(.bmp)或JPEG等格式保存到硬盘,并能重新打开继续编辑。 8. **控件布局**:使用布局...

    C# Winform画图板

    8. **图片的打开与保存**: - 使用`OpenFileDialog`控件让用户选择要打开的图片文件,然后通过`Image.FromFile`加载图片到`PictureBox`控件。 - `SaveFileDialog`控件用于保存用户的绘图作品,可以将其保存为BMP、...

    用EVC4.0开发的画图板

    本篇文章将详细探讨如何使用EVC4.0来开发一个简单的画图板程序,该程序具备打开和保存BMP图像文件的能力。 首先,让我们了解EVC4.0。EVC4.0是针对Microsoft Windows CE和Pocket PC等嵌入式平台的C++编译器和开发...

    bmp格式图片转换为raw格式

    本篇文章将深入探讨如何使用C++将BMP(Bitmap)格式的图片转换为RAW纯数据格式。BMP是一种常见的位图格式,通常用于存储数字图像,而RAW格式则保存了相机传感器捕获的原始数据,通常用于专业摄影后期处理。 BMP格式...

    C++画图板 画图工具

    在这个场景中,"C++画图板 画图工具"是一个基于MFC实现的图形用户界面应用程序,专门用于绘画和图形编辑。 首先,我们来深入了解一下MFC。MFC库包含了类和函数,它们提供了对Windows操作系统的核心服务、窗口、控件...

    仿照win的简易画图板

    7. **保存与打开**:保存功能将用户的绘图数据以图像文件格式(如BMP、JPEG或PNG)存储,而打开功能则能加载已有的图像文件,继续编辑。这涉及到文件I/O操作和图像编码解码技术。 8. **透明效果**:虽然这个简易...

    模拟windows画图板程序

    5. 图像保存/加载:集成文件对话框,支持常见的图像格式(如BMP、JPEG、PNG等),实现文件的保存和打开。 6. 剪贴板操作:实现复制、剪切和粘贴功能,利用Windows的剪贴板API。 在编码过程中,我们需要遵循面向...

    画图板(C#源码)(有点像Windows画图)

    《C#实现简易画图板:GraphicalCS详解》 在计算机编程领域,尤其是图形用户界面(GUI)的开发中,模拟系统自带功能是常见的学习和实践方式。本篇文章将详细探讨一个用C#编写的简易画图板项目,这个项目名为...

    画图板小程序

    5. **保存和加载**:用户应能保存他们的作品以便后续编辑或分享,这就需要实现文件保存和打开功能,可能采用常见的图像文件格式如BMP或PNG。 6. **缩放和平移**:为了查看画布的不同部分,程序应该提供缩放和平移...

    C# 实现画图软件

    在本文中,我们将深入探讨如何使用C#编程语言来实现一个基本的画图软件,该软件包括调色板、铅笔、圆形、矩形绘制以及保存功能。C#是一种广泛用于开发桌面应用、游戏和Web服务的强大语言,其丰富的类库和强大的.NET...

    【原创】C#高仿mspaint画图板程序【源码】

    5. **保存和加载图像**:为了保存用户的画作,程序需要支持将当前画布的内容导出为图片文件,如BMP、PNG或JPEG格式。同时,也应提供加载图片的功能,让用户可以在已有的图像上继续编辑。 6. **其他工具**:除了基本...

    C#编写的画图板

    - 添加“保存”和“打开”按钮,使用`SaveFileDialog`和`OpenFileDialog`对话框,分别实现将绘图保存为图片文件(如BMP、PNG)和加载图片到绘图板的功能。 6. **撤销/重做功能** - 为了实现撤销和重做功能,可以...

    osx 画图板 Paintbrush 2.1.2

    《osx 画图板 Paintbrush 2.1.2:Mac OS X 上的高效绘图工具》 在数字化的世界里,绘图软件是创意人士不可或缺的工具之一。Windows操作系统中的“画图”软件虽然简单易用,但在功能上可能无法满足专业或进阶用户的...

    XP系统附件之画图工具

    另外,画图工具的文件兼容性也很强,它可以打开和保存常见的图像格式,如BMP、JPG、PNG等,方便用户与其他软件进行数据交换。同时,由于画图工具是Windows系统自带的附件,用户无需额外安装,只需打开就能使用,非常...

    Java实现简易画图程序.doc

    - 尝试打开保存的图像文件以及非图像文件类型(如txt文件)。 - **测试结果**: - 保存的图像文件能够正确打开并在画板上显示。 - 尝试打开非图像文件时能够正确提示错误信息。 #### 七、总结 本项目不仅涵盖了...

    winows自带画图工具

    8. 图片导入与导出:可以打开和保存各种常见的图像格式,如BMP、JPG、PNG等。 9. 滤镜效果:虽然有限,但还是有一些基础的滤镜可供应用,如模糊、锐化等。 10. 快捷操作:通过菜单栏或快捷键实现各种功能,提高...

Global site tag (gtag.js) - Google Analytics