Bmp24Writer代码

Stella981
• 阅读 572
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)
    }  
  
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
java 中链表的实现
//数据类 class DATA2{String key;String name;int age;}//定义链表类class CLType{DATA2 nodedatanew DATA2();CLType nextNodenull;//下
Easter79 Easter79
3年前
springboot2.2和mybatis2.1的增删改查
直接结构图!(https://oscimg.oschina.net/oscnet/574820232583656659f583b60ba15706741.png)数据表CREATETABLE\user\(\id\int(32)NOTNULLAUTO\_INCREMENT,\user\_name\varc
Stella981 Stella981
3年前
Scala 谜题
在Scala中,List\String\和List\Int\之间并没有继承关系,但是下面的代码竟然可以通过编译并且顺利运行:objectTestextendsApp{valstrList:List\String\List("a","b","c")valstrToIntList:List\Int
Wesley13 Wesley13
3年前
MongoDB 数据类型
一.MongoDB之数据类型Object ID:Documents自动生成的\_id,插入数据时候会生成 \_id,唯一字段String:字符串,必须是utf8Boolean:布尔值,true或者falseInteger:整数(Int32Int64你们就知道有个Int就行了,一般我们用Int32)Doub
Stella981 Stella981
3年前
JVM 字节码指令表
字节码助记符指令含义0x00nop什么都不做0x01aconst\_null将null推送至栈顶0x02iconst\_m1将int型1推送至栈顶0x03iconst\_0将int型0推送至栈顶0x04iconst\_1将int型1推送至栈顶0x05ic
Wesley13 Wesley13
3年前
mysql select将多个字段横向合拼到一个字段
表模式:CREATE TABLE tbl_user (  id int(11) NOT NULL AUTO_INCREMENT,  name varchar(255) DEFAULT NULL,  age int(11) DEFAULT NULL,  PRIMARY KEY (id)
暗箭伤人 暗箭伤人
1年前
【www.ithunter.club】 20230922下午
不容易的2023年,我们一起努力【www.ithunter.club】(2023092208:00:00.8872062023092216:00:00.887206)1.人事招聘专员数名(可选远程或入职)2.招聘向坐标东京Yahoo、Shift、L