JAVA实现彩色图片转黑白图片 (ImageIO类)

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 *  ImageIO的测试类
 *
 */
public class Main {


    public static void main(String[] args) throws IOException {

        String originPath = "D:/colorTest/001.jpg";
        String outputPath = "D:/colorTest/test.jpg";

        //1、图片转黑白
        changeImageToNoneColor(originPath,outputPath,1);

    }

    /**
     * 图片根据通道转成黑白
     * @param originPath 原文件目录
     * @param outputPath 输出文件目录
     * @param channel 根据哪个通道转黑白 1:Red 2:Green 3:Blue
     * @throws IOException
     */
    public static void changeImageToNoneColor(String originPath, String outputPath, int channel) throws IOException {
        File file = new File(originPath);
        BufferedImage image = ImageIO.read(file);
        changeAllARGB(image,channel);//将传入的bufferedimage 只保留红色通道的信息
        ImageIO.write(image,"jpg",new File(outputPath));
    }
    /**
     *
     * @param image BufferedImaged对象
     * @return 一个Map Key是图像的像素行数,Value是图像的该行中每一点的ARGB值
     */
    public static Map<Integer, ArrayList> getAllARGB(BufferedImage image){
        Map<Integer, ArrayList> result = new HashMap<>();
        int width = image.getWidth();
        int height = image.getHeight();//height
        for(int i = 0; i < height; i++){
            ArrayList<int[]> list = new ArrayList();//用list记录每一行的像素
            for(int j = 0; j < width; j++){
                int[] transARGB = transARGB(image.getRGB(j, i),-1);
                list.add(transARGB);
            }
            result.put(i,list);
        }
        return result;
    }

    /**
     *
     * @param image
     * @return
     */
    public static void changeAllARGB(BufferedImage image, int channel){

        int width = image.getWidth();
        int height = image.getHeight();//height
        for(int i = 0; i < height; i++){
            ArrayList<int[]> list = new ArrayList();//用list记录每一行的像素
            for(int j = 0; j < width; j++){
                int[] transARGB = transARGB(image.getRGB(j, i),channel);//获取只显示指定通道图层
                //System.out.println("正在处理的像素点坐标 x:" + j + " y:" + i);
                image.setRGB(j,i,array2Integer(transARGB));
            }
        }
    }

    /**
     * int型rgb转换成数组格式 并保留指定的通道
     * @param rgb  int型的rgb值 通过BufferedImage的getRGB方法获取的
     * @param channel 通道标识 1:Red 2:Green 3:Blue other:保留所有通道
     * @return 返回的是int型数组,ARGB四个通道的值 [Alpha,Red,Green,Blue]
     */
    public static int[] transARGB(int rgb, int channel){
        String argb = Integer.toBinaryString(rgb);
        //分割及二进制转换
        Integer alpha = Integer.parseInt(argb.substring(0,8),2);
        Integer red = Integer.parseInt(argb.substring(8,16),2);
        Integer green = Integer.parseInt(argb.substring(16,24),2);
        Integer blue = Integer.parseInt(argb.substring(24,32),2);
        //定义数组
        int[] argbArr = {alpha,red,green,blue};
        //只保留某一个通道的信息  即把除了Alpha通道外的全部改成所选通道的值
        if (channel == 1){
            argbArr = new int[]{argbArr[0],argbArr[1],argbArr[1],argbArr[1]};
        }
        if (channel == 2){
            argbArr = new int[]{argbArr[0],argbArr[2],argbArr[2],argbArr[2]};
        }
        if (channel == 3){
            argbArr = new int[]{argbArr[0],argbArr[3],argbArr[3],argbArr[3]};
        }
        return argbArr;
    }

    /**
     * 获取图像的分辨率
     * @return width像素数 * height像素数
     */
    public static String getSize(BufferedImage image) {
        int height = image.getHeight();
        int width = image.getWidth();
        System.out.println("width = " + width);
        System.out.println("height = " + height);
        return width + " x " + height;
    }

    /**
     * 只用于此class的方法转换 把记录ARGB的数组转成int信息
     * @param arr
     * @return
     */
    public static int array2Integer(int[] arr){
        //System.out.println(Arrays.toString(arr));
        //利用Integer.toBinaryString转码时发现一个问题,只会从第一个1开始记录,例如0011100会被记为11100,而我需要的是8位代码
        String s1 = get8BitBinaryString(Integer.toBinaryString(arr[0]));
        String s2 = get8BitBinaryString(Integer.toBinaryString(arr[1]));
        String s3 = get8BitBinaryString(Integer.toBinaryString(arr[2]));
        String s4 = get8BitBinaryString(Integer.toBinaryString(arr[3]));
        String origin = s1 + s2 + s3 + s4;
        if(origin.startsWith("1")){
            //判断首位是否是1,如果是1,则按照补码计算
            String[] split = origin.split("");
            StringBuilder originCode = new StringBuilder("");
            for(int i = 0; i < split.length; i++){
                if(split[i].equals("1")){
                    originCode.append("0");
                }
                if(split[i].equals("0")){
                    originCode.append("1");
                }
            }
            //System.out.println(originCode);
            //循环结果 +1 即为原码
            int i = Integer.parseInt(originCode.toString(),2) + 1;
            System.out.println("-i = " + -i);
            return -i;
        }
        System.out.println(origin);
        return Integer.parseInt(origin, 2);
    }

    /**
     * 把参数转换为8位二进制代码
     * @param s
     * @return
     */
    public static String get8BitBinaryString (String s){
        if(s.length() == 8){
            return s;
        }else{
            int length = s.length();
            String zero = "";
            for (int i = 0; i < 8 - length; i++){/*通过循环判断前面要加几个零*/
                zero += "0";
            }
            return zero + s;
        }
    }

}

想实现一个通过JAVA把视频转成字符画视频的功能,作为一个小工具放在个人论坛上。

实现视频转成字符画视频首先要能把图片转成字符画“,思路就是先把图片解析成黑白图片 -- > 每个像素点用字符替代 -->生成一个字符画  首先这个图片解析成黑白就难到我了,查了下图像处理的相关API,发现了这个ImageIO类

然后搞了一个晚上搞出来这个小demo,搞的时候发现其实不用解析成黑白图片,read的时候直接把RGB像素变成字符输出就好了,但是黑白图片这个功能毕竟已经做了一半,就顺手记录下;

 

踩坑:

这个主要是调用API,坑不多,主要是两点

  • Integer.toBinaryString()如果参数是负数 那么return的就是补码 不能把这个数再通过Integer.parseInt()直接转成int,会报错
  • Integer.toBinaryString转码时,只会从第一个1开始记录,例如0011100会被记为11100,而我需要的是用来记录ARGB每个通道的值8位二进制数字(0~255),所以要处理下,目前这个处理方式性能很差,改天看看api里有没有专门处理二进制数的

放下转黑白前后的对比图

 
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值