Java--图形像素原理

图形像素原理

每张图片都可以表示为由像素值组成的矩阵。

分辨率决定单位面积的像素个数

像素矩阵:像素点的值 – 颜色表达

RGB图像又称为真彩图像,它使用R、G、B 3个分量标识一个像素的颜色,R、G、B分别代表红、绿、蓝3种不同的基础颜色,通过3基色可以合成出任意颜色。所以对一个尺寸nxm的彩色图像来说,MATLAB中则存储为一个nxmx3 的多维数据数组,其中数组中的元素定义了图像中每一个像素的红、绿、蓝颜色值。图形文件格式把RGB图像存储为24位的图像,红、绿、蓝分量分别占用8位,因而理论上可以有2^24种颜色。

R G B:

0-255 256个 8bit 256 256 256

像素值的存储

1.创建一个二维数组来表示像素组成的矩阵

把三个byte 存入一个int

RGB

0000 0000 32位

1000 0000 24位 R

1000 0000 16位 G

1000 0000 低八位 B

0表示黑色 255 表示白色

Java的位移运算

为什么二进制1000等于-8

在这里插入图片描述

也就是说,对于4位整数1000,最高位为1符号位,说明是一个负数。那么它的计算方式是:

  • -1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 0 * 2^0=-8+0+0+0=-8

再例如二进制的1111,按照这个计算方式结果是:

  • -1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 1 * 2^0=-8+4+2+1=-1

Java中的int类型占32位,因此能表示的范围为-2^31 ~ 2^31-1,

int类型的十进制范围表示为:-2147483648~2147483647

int类型的二进制表示范围为: 10000000 00000000 00000000 00000000 ~ 01111111 11111111 11111111 11111111

左移<<

在这里插入图片描述

二进制数向左移动k位,丢弃最高的k位,并在有右边补k个0

01111111 11111111 11111111 11111111左移一位,符号位变成1,低位用0填充

所以结果位11111111 11111111 11111111 11111110,通过补码编码得出结果为-2

10000000 00000000 00000000 00000000左移一位,符号位变为0,代表正数,低位同样用0填充,结果位00000000 00000000 00000000 00000000,因此结果为0

右移>>

在这里插入图片描述

  • 算术右移到方式比较微妙,二进制右移动k位,丢弃低k位,并在高k位补最高位的值。其目的是为了负数的运算

    如下:算术右移动后,高位原本是几就用几补充

    • 01111111 11111111 11111111 11111111 算术右移1位
    • 00111111 11111111 11111111 11111111
    • 10000000 00000000 00000000 00000000 算术右移1位
    • 11000000 00000000 00000000 00000000

    可以看到十进制无论是正还是负数,逻辑右移一位相当于除以二。
    在这里插入图片描述

    首先我们要都知道, &表示按位与,只有两个位同时为1,才能得到1, 0x代表16进制数,0xff表示的数二进制1111 1111 占一个字节.和其进行&操作的数,最低8位,不会发生变化.

    我们只关心二进制的机器数而不关注十进制的值,那么byte &0xff只是对其最低8位的复制,通常配合逻辑或 ‘’|’'使用,达到字节的拼接

 int vaule = ((255 & 0XFF) << 24) | ((red & 0XFF) << 16) | ((green & 0XFF) << 8) | ((blue & 0XFF) << 0);

此时代码终于看懂了

改进分析

package Image;

import jdk.management.resource.internal.inst.FileOutputStreamRMHooks;

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

/**
 * 1: 讲清楚图形像素原理
 * 2: 位移运算 以及位运算
 * 3: 完成像素图 - 基础效果 尝试比如调色板实现
 */
public class ImagePad extends JFrame {
    public static int[][] res;
    public static int width;
    public static int height;

    public ImagePad() {
        setTitle("像素画");
        setSize(100 + width, height);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        //ranDom(g);
       draWing(g);
    }

    public static void ranDom(Graphics g) {
        Color color = new Color(255, 255, 255);
        g.setColor(color);
        g.fillRect(100, 100, 500, 500);
        Random random = new Random();
        random.nextInt(256);// [0 bound)
        // 随机一个数组的像素值
        int[][] cloloArr = new int[500][500];
        for (int i = 0; i < 500; i++) {
            for (int j = 0; j < 500; j++) {
                int red = random.nextInt(256);
                int green = random.nextInt(256);
                int blue = random.nextInt(256);
                int vaule = ((255 & 0XFF) << 24) | ((red & 0XFF) << 16) | ((green & 0XFF) << 8) | ((blue & 0XFF) << 0);
                cloloArr[i][j] = vaule;
            }
        }
        for (int i = 0; i < 500; i++) {
            for (int j = 0; j < 500; j++) {
                Color color1 = new Color(cloloArr[i][j]);
                g.setColor(color1);
                g.fillRect(100 + i, 100 + j, 1, 1);
            }
        }
        for (int i = 0; i < 500; i++) {
            for (int j = 0; j < 500; j++) {
                int value = cloloArr[i][j];
                int red = (value >> 16) & 0xFF;
                int green = (value >> 8) & 0xFF;
                int blue = (value >> 0) & 0xFF;
                int gray = (red + green + blue) / 5;
                Color color1 = new Color(red / 2, green / 2, blue / 2);
                g.setColor(color1);
                g.fillRect(610 + i, 100 + j, 1, 1);
            }
        }
    }

    public static void draWing(Graphics gr) {
        File file = new File("D:\\壁纸\\1.jpg");
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        width = bi.getWidth();
        height = bi.getHeight();
        res = new int[width][height];
        int minx = bi.getMinX();
        int miny = bi.getMinY();
        for (int i = minx; i < width; i++) {
            for (int j = miny; j < height; j++) {
                int pixel = bi.getRGB(i, j);
                res[i][j] = pixel;
            }
        }
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                int value = res[i][j];
                int red = (value >> 16) & 0xFF;
                int green = (value >> 8) & 0xFF;
                int blue = (value >> 0) & 0xFF;
                int gray=(red+green+blue)/3;
                Color color1 = new Color(red/3,green/3,blue);
                Color color2 = new Color(gray,gray,gray);
               gr.setColor(color1);
                //gr.setColor(color2);

                gr.fillRect(minx + i, miny + j, 1, 1);
            }
        }
    }

    public static void main(String[] args) {
        new ImagePad();
    }
}

分析

    int value = res[i][j];
    int red = (value >> 16) & 0xFF;
    int green = (value >> 8) & 0xFF;
    int blue = (value >> 0) & 0xFF;
    int gray=(red+green+blue)/3;
    Color color1 = newColor(red/3,green/3,blue);
    Color color2 = new Color(gray,gray,gray);

原图:在这里插入图片描述
当new Color(red/2,green/2,blue/2)

效果如下:在这里插入图片描述
当new Color(red/3,green/3,blue/3)

效果如下:在这里插入图片描述
当int gray=(red+green+blue)/3;
效果如下:在这里插入图片描述
当int gray=(red+green+blue)/6;
效果如下:在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值