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 条评论
登录 后参与评论

相关文章

来自专栏跟着阿笨一起玩NET

c# 使用timer定时器操作,上次定时到了以后,下次还未执行完怎么处理

------解决方案-------------------------------------------------------- 开始的时候,禁用定时器,你...

2651
来自专栏WOLFRAM

向日葵中的数学之美

1833
来自专栏搞前端的李蚊子

Html5模拟通讯录人员排序(sen.js)

// JavaScript Document  var PY_Json_Str = ""; var PY_Str_1 = ""; var PY_Str_...

5896
来自专栏Petrichor的专栏

Dataset 列表:机器学习研究

In computer vision, face images have been used extensively to develop face recog...

1501
来自专栏码匠的流水账

聊聊spring cloud的HystrixAutoConfiguration

本文主要研究一下spring cloud的HystrixAutoConfiguration

972
来自专栏码匠的流水账

java9系列(五)Stack-Walking API

java9新增这个类的目的是提供一个标准API用于访问当前线程栈,之前只有Throwable::getStackTrace、Thread::getStackTr...

421
来自专栏linux驱动个人学习

高通Audio中ASOC的machine驱动

ASoC被分为Machine、Platform和Codec三大部分,其中的Machine驱动负责Platform和Codec之间的耦合以及部分和设备或板子特定的...

9764
来自专栏Golang语言社区

Knapsack problem algorithms for my real-life carry-on knapsack

I'm a nomad and live out of one carry-on bag. This means that the total weight o...

1142
来自专栏Pulsar-V

Save Camera Document

#pragma once #include "HCCamera.h" #include <time.h> #include <cstdio> #incl...

2828
来自专栏前端儿

Web 前端颜色值--字体--使用,整理整理

颜色值 CSS 颜色使用组合了红绿蓝颜色值 (RGB) 的十六进制 (hex) 表示法进行定义。对光源进行设置的最低值可以是 0(十六进制 00)。最高值是 2...

2282

扫码关注云+社区