Bmp24Writer代码

import java.io._
object Bmp24Writer {
	//将加密的数据写入文件
    def writeEncryptedBmp(bmpPath: String, keys: Array[Int], 
    			shift: Int, times: Int, 
    			red: Array[Array[Int]], 
    			green: Array[Array[Int]], 
    			blue: Array[Array[Int]]) =  { 
    		val width = red(0).length    		
    		val fos = new FileOutputStream(bmpPath)  
    		val dos = new DataOutputStream(fos) 
  
    		writeBmp24(dos, red, green ,blue)
           
    		for(i <- 0 until width)
    		  print(s"${keys(i)} ")
    		println
    		println(s"times: $times, shift $shift")
    		
    		for(i <- 0 until width)
    			dos write(changeByte(keys(i)), 0, 4)
    		
    		dos write(changeByte(times), 0, 4)
    		dos write(changeByte(shift), 0, 4)

    		dos.flush
    		dos.close  
    		dos.close  
    }  
    //将解密后的数据写入文件
    def writeNormalBmp(bmpPath: String, 
    			red: Array[Array[Int]], 
    			green: Array[Array[Int]], 
    			blue: Array[Array[Int]]) =  { 
    		val fos = new FileOutputStream(bmpPath)  
    		val dos = new DataOutputStream(fos)
    		
    		writeBmp24(dos, red, green ,blue)
          
    		dos.flush
    		dos.close  
    		fos.close 
    }  
    //写bmp图片的信息头和文件头还有位图数据
    def writeBmp24(dos: DataOutputStream, 
    		    red: Array[Array[Int]], 
    		    green: Array[Array[Int]], 
    		    blue: Array[Array[Int]]) = {
    		val width = red(0).length
    		val height = red.length
    		
    		//14字节的文件头
    		//代表BM
    		val bfType = 0x424d.toShort  
    		 // bmp文件的大小(2—5字节)
    		val bfSize = 54 + width * height * 3
    		// 位图文件保留字,必须为0(6-7字节)
    		val bfReserved1 = 0   
    		// 位图文件保留字,必须为0(8-9字节)
    		val bfReserved2 = 0 
    		// 文件头开始到位图实际数据之间的字节的偏移量(10-13字节) 
    		val bfOffBits = 54
  
          
           dos writeShort bfType
           dos write(changeByte(bfSize), 0, 4)
           dos write(changeByte(bfReserved1), 0, 2)
           dos write(changeByte(bfReserved2), 0, 2)
           dos write(changeByte(bfOffBits), 0, 4)
  
           //40字节的信息头
    	   // 信息头所需的字节数(14-17字节) 
           val biSize = 40 
           // 位图的宽(18-21字节)  
           val biWidth = width
           // 位图的高(22-25字节)  
           val biHeight = height
           // 目标设备的级别,必须是1(26-27字节)
           val biPlanes = 1 
           // 每个像素所需的位数(28-29字节),必须是1位(双色)、
           // 4位(16色)、8位(256色)或者24位(真彩色)之一。  
           val biBitcount = 24
           // 位图压缩类型,必须是0(不压缩)(30-33字节)、
           //1(BI_RLEB压缩类型)或2(BI_RLE4压缩类型)之一。  
           val biCompression = 0
           // 实际位图图像的大小,即整个实际绘制的图像大小(34-37字节)  
           val biSizeImage = width * height
           // 位图水平分辨率,每米像素数(38-41字节)这个数是系统默认值  
           val biXPelsPerMeter = 0
           // 位图垂直分辨率,每米像素数(42-45字节)这个数是系统默认值  
           val biYPelsPerMeter = 0
           // 位图实际使用的颜色表中的颜色数(46-49字节),
           // 如果为0的话,说明全部使用了  
           val biClrUsed = 0
           // 位图显示过程中重要的颜色数(50-53字节),
           // 如果为0的话,说明全部重要  
           val biClrImportant = 0
            
           // 因为是大端存储,那么也就是说同样会大端输出。   
           // 所以首先调用方法将int数据转变为多个byte数据,
           // 并且按小端存储的顺序.
            dos write(changeByte(biSize), 0, 4)
            dos write(changeByte(biWidth), 0, 4)
            dos write(changeByte(biHeight), 0, 4)
            dos write(changeByte(biPlanes), 0, 2)
            dos write(changeByte(biBitcount), 0, 2)
            dos write(changeByte(biCompression), 0, 4)
            dos write(changeByte(biSizeImage), 0, 4)
            dos write(changeByte(biXPelsPerMeter), 0, 4)
            dos write(changeByte(biYPelsPerMeter), 0, 4)
            dos write(changeByte(biClrUsed), 0, 4)
            dos write(changeByte(biClrImportant), 0, 4)
    		
    	    // 因为是24位图,所以没有颜色表  
            // 通过遍历输入位图数据  
            // 这里遍历的时候注意,在计算机内存中位图数据
    	    // 是从左到右,从下到上来保存的,  
            // 也就是说实际图像的第一行的点在内存是最后一行  
            for(i <- height - 1 to 0 by -1){
            	for(j <- 0 to width - 1){
                    dos write(changeByte(blue(i)(j)), 0, 1)
                    dos write(changeByte(green(i)(j)), 0, 1)
                    dos write(changeByte(red(i)(j)), 0, 1) 
            	}
              }  

    }
      
    // 将一个int数据转为按小端顺序排列的字节数组 
    def changeByte(data: Int): Array[Byte] = 
    		Array(
			((data << 24) >> 24).toByte,
			((data << 16) >> 24).toByte, 
			((data << 8) >> 24).toByte,
			(data >> 24).toByte
	        )   
    
    // 将四个字节解析成int数据
     def ChangeInt(array2: Array[Byte], start: Int) = {  
    	val i = 
    	  ((array2(start) & 0xff) << 24) | ((array2(start - 1) & 0xff) << 16)  
    	val j = 
    	  ((array2(start - 2) & 0xff) << 8) | (array2(start - 3) & 0xff)     
       i | j 
    }  
    
    // 读取rgb数据
     def getInf(bis: BufferedInputStream, height: Int, width: Int) = {  
       
        val red = Array.ofDim[Int](height, width)    
        val green = Array.ofDim[Int](height, width)    
        val blue = Array.ofDim[Int](height, width)  
       
        // 计算系统在每行的填充的字节数
        val m = width * 3 % 4
        var skip_width = 0
        if(m != 0)
          skip_width = 4 - m
  
        for (i <- height - 1 to 0 by -1) {  
            for (j <- 0 to width - 1) {  
                    blue(i)(j) = bis.read 
                    green(i)(j) = bis.read 
                    red(i)(j) = bis.read
                    if (j == 0) {  
                        bis skip(skip_width) 
                    }  
            }  
        }  
        (red, green, blue)
    }  
  
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏深度学习思考者

Python学习(二) 正则表达式

Python正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。re 模块使 Python 语言拥有全部的正则表达式功...

1879
来自专栏机器学习算法与Python学习

python: 函数详解

def square(x): return x**2 >>> square <function square at 0x031AA230> >>> dir(sq...

4097
来自专栏专注数据中心高性能网络技术研发

[C++]C++面试知识总结

1.程序运行知识 1.1 内存布局和分配方式 C程序的内存布局如下: ? 静态存储区:存储全局变量和static变量,通常在程序编译期间已经分配好了。 BSS...

2864
来自专栏代码拾遗

Java 8 基础教程 - 默认方法

正如其名,在Java 8中,默认方法就是使用default关键字标记的定义在接口中的方法。如果子类不重写这些方法,那么在子类调用这些方法的时候会直接调用接口中的...

902
来自专栏机器学习和数学

[编程经验] Python正则表达式

Hello,大家好。又见面了,今天给大家介绍一下,正则表达式在Python中是如何使用的。这样说的原因是正则表达式并不是Python所独有的,而是自成体系,在很...

2504
来自专栏进击的君君的前端之路

正则表达式

1495
来自专栏Python研发

最全Python内置函数

判断真假,  True:真  ,  False:假,   把一个对象转换成bool值

1002
来自专栏Golang语言社区

Go语言的复合数据类型

Go语言的复合数据类型是基础数据类型的组合,主要包括四个数组,切片(slice),map和结构体。 数组和结构体的大小是固定大小的,数组的元素类型是固定的,结...

2635
来自专栏北京马哥教育

最全 Python3 函数知识点大全

23311
来自专栏数据科学学习手札

(数据科学学习手札48)Scala中的函数式编程

  Scala作为一门函数式编程与面向对象完美结合的语言,函数式编程部分也有其独到之处,本文就将针对Scala中关于函数式编程的一些常用基本内容进行介绍;

1124

扫码关注云+社区