BMP位图转换:24bpp转1bpp — Java实现

16 篇文章 0 订阅
6 篇文章 0 订阅

24位BMP位图转点阵图,即24bpp转1bpp

基本概念

BPP:bits per pixel,每个像素的比特数。

场景

打印机打印二维码/图片:热敏打印机只可打印点阵图;
对图片质量要求低,降低内存消耗。

Java语言实现

package com.master.tools

import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.Log;
import java.io.IOException;

public class BmpConvert
{
  private BmpFileHeader fileHeader = new BmpFileHeader();
  private BmpInfoHerder infoHeader = new BmpInfoHerder();
  private RGBQUAD[] rgbQuadList = null;
  private byte[] data = null;

  public BmpConvert(Bitmap bitmap, short bitCount) throws IOException {
    if (bitmap == null) {
      return;
    }
    this.infoHeader.biSize = 40;
    this.infoHeader.biWidth = bitmap.getWidth();
    this.infoHeader.biHeight = bitmap.getHeight();
    this.infoHeader.biPlanes = 1;
    this.infoHeader.biBitCount = bitCount;
    this.infoHeader.biCompression = 0;
    this.infoHeader.biSizeImage = 0;
    this.infoHeader.bixPelsPerMeter = 0;
    this.infoHeader.biyPelsPerMeter = 0;
    this.infoHeader.biClrUsed = 0;
    this.infoHeader.biClrImportant = 0;
    if (this.infoHeader.biBitCount == 1) {
      this.rgbQuadList = new RGBQUAD[2];
      this.rgbQuadList[0] = new RGBQUAD();
      this.rgbQuadList[0].rgbBlue = 0;
      this.rgbQuadList[0].rgbGreen = 0;
      this.rgbQuadList[0].rgbRed = 0;
      this.rgbQuadList[0].rgbRed = 0;
      this.rgbQuadList[1] = new RGBQUAD();
      this.rgbQuadList[1].rgbBlue = -1;
      this.rgbQuadList[1].rgbGreen = -1;
      this.rgbQuadList[1].rgbRed = -1;
      this.rgbQuadList[1].rgbRed = 0;
    } else if (this.infoHeader.biBitCount == 4) {
      this.rgbQuadList = new RGBQUAD[16];
    } else if (this.infoHeader.biBitCount == 8) {
      this.rgbQuadList = new RGBQUAD[256];
    }
    int bmpWidth = ((this.infoHeader.biWidth + 7) /
        this.infoHeader.biBitCount / 8 + 3) / 4 * 4;
    int bufferSize = bmpWidth * this.infoHeader.biHeight;
    this.fileHeader.bfType = 19778;
    this.fileHeader.bfReserved1 = 0;
    this.fileHeader.bfReserved2 = 0;
    this.fileHeader.bfOffBits = (54 + this.rgbQuadList.length * 4);
    this.fileHeader.bfSize = (this.fileHeader.bfOffBits + bufferSize);
    this.infoHeader.biSizeImage = (this.fileHeader.bfSize - this.fileHeader.bfOffBits);
    this.data = new byte[this.fileHeader.bfSize];
    int writeSize = 0;

    writeSize += writeWord(this.data, writeSize, this.fileHeader.bfType);
    writeSize += writeDword(this.data, writeSize, this.fileHeader.bfSize);

    writeSize = writeSize +
        writeWord(this.data, writeSize,
            this.fileHeader.bfReserved1);

    writeSize = writeSize +
        writeWord(this.data, writeSize,
            this.fileHeader.bfReserved2);
    writeSize += writeDword(this.data, writeSize, this.fileHeader.bfOffBits);

    writeSize += writeDword(this.data, writeSize, this.infoHeader.biSize);
    writeSize += writeLong(this.data, writeSize, this.infoHeader.biWidth);
    writeSize += writeLong(this.data, writeSize, this.infoHeader.biHeight);
    writeSize += writeWord(this.data, writeSize, this.infoHeader.biPlanes);
    writeSize += writeWord(this.data, writeSize, this.infoHeader.biBitCount);

    writeSize = writeSize +
        writeDword(this.data, writeSize,
            this.infoHeader.biCompression);

    writeSize = writeSize +
        writeDword(this.data, writeSize,
            this.infoHeader.biSizeImage);

    writeSize = writeSize +
        writeLong(this.data, writeSize,
            this.infoHeader.bixPelsPerMeter);

    writeSize = writeSize +
        writeLong(this.data, writeSize,
            this.infoHeader.biyPelsPerMeter);
    writeSize += writeDword(this.data, writeSize, this.infoHeader.biClrUsed);

    writeSize = writeSize +
        writeDword(this.data, writeSize,
            this.infoHeader.biClrImportant);
    for (int n = 0; n < this.rgbQuadList.length; n++)
    {
      writeSize = writeSize +
          writeByte(this.data, writeSize,
              this.rgbQuadList[n].rgbBlue);

      writeSize = writeSize +
          writeByte(this.data, writeSize,
              this.rgbQuadList[n].rgbGreen);

      writeSize = writeSize +
          writeByte(this.data, writeSize,
              this.rgbQuadList[n].rgbRed);

      writeSize = writeSize +
          writeByte(this.data, writeSize,
              this.rgbQuadList[n].rgbReserved);
    }
    int[] pixels = new int[this.infoHeader.biWidth *
        this.infoHeader.biHeight];
    bitmap.getPixels(pixels, 0, this.infoHeader.biWidth, 0, 0,
        this.infoHeader.biWidth, this.infoHeader.biHeight);
    int j = 0;
    int nRealCol = this.infoHeader.biHeight - 1;
    int blockSize = 8;
    int maxW = (this.infoHeader.biWidth + blockSize - 1) / blockSize;

    tick[1] = System.currentTimeMillis();
    for (; j < this.infoHeader.biHeight; nRealCol--) {
      int colStart = writeSize + nRealCol * bmpWidth;
      for (int wRow = 0; wRow < maxW; wRow++) {
        int startNum = blockSize * wRow;
        for (int n = 0; (n < blockSize) && (
            startNum + n < this.infoHeader.biWidth);
            n++) {
          int clr = pixels[
              (startNum + n + j *
                  this.infoHeader.biWidth)];
          int gray = getGreyLevel(clr, 1.0F);
          if (gray > 127) {
            int cz = 1;
            int tmpIndex = colStart + wRow;
            byte[] tmpBytes = this.data;
            tmpBytes[tmpIndex] = ((byte)(tmpBytes[tmpIndex] + (byte)(cz << 7 - n)));
          }
        }
      }
      j++;
    }
  }

  public byte[] getData() {
    return this.data;
  }

  public int getWidth() {
    return this.infoHeader.biWidth;
  }

  public int getHeight() {
    return this.infoHeader.biHeight;
  }

  public int getBitCount() {
    return this.infoHeader.biBitCount;
  }

  private int writeWord(byte[] stream, int start, int value) throws IOException
  {
    byte[] b = new byte[2];
    b[0] = ((byte)(value & 0xFF));
    b[1] = ((byte)(value >> 8 & 0xFF));
    System.arraycopy(b, 0, stream, start, 2);

    return 2;
  }

  private int writeDword(byte[] stream, int start, long value) throws IOException
  {
    byte[] b = new byte[4];
    b[0] = ((byte)(int)(value & 0xFF));
    b[1] = ((byte)(int)(value >> 8 & 0xFF));
    b[2] = ((byte)(int)(value >> 16 & 0xFF));
    b[3] = ((byte)(int)(value >> 24 & 0xFF));
    System.arraycopy(b, 0, stream, start, 4);

    return 4;
  }

  private int writeLong(byte[] stream, int start, long value) throws IOException
  {
    byte[] b = new byte[4];
    b[0] = ((byte)(int)(value & 0xFF));
    b[1] = ((byte)(int)(value >> 8 & 0xFF));
    b[2] = ((byte)(int)(value >> 16 & 0xFF));
    b[3] = ((byte)(int)(value >> 24 & 0xFF));
    System.arraycopy(b, 0, stream, start, 4);

    return 4;
  }

  private int writeByte(byte[] stream, int start, byte value) throws IOException
  {
    stream[start] = value;
    return 1;
  }

  public static int getGreyLevel(int pixel, float intensity) {
    float alpha = Color.alpha(pixel);
    if (alpha < 50.0F) {
      return 255;
    }
    float red = Color.red(pixel);
    float green = Color.green(pixel);
    float blue = Color.blue(pixel);
    float parcial = red + green + blue;
    parcial = (float)(parcial / 3.0D);
    int gray = (int)(parcial * intensity);
    if (gray > 255) {
      gray = 255;
    }
    return gray;
  }

  public class BmpFileHeader
  {
    public short bfType;
    public int bfSize;
    public short bfReserved1;
    public short bfReserved2;
    public int bfOffBits;

    public BmpFileHeader()
    {
    }
  }

  public class BmpInfoHerder
  {
    public short biSize;
    public int biWidth;
    public int biHeight;
    public short biPlanes;
    public short biBitCount;
    public int biCompression;
    public int biSizeImage;
    public int bixPelsPerMeter;
    public int biyPelsPerMeter;
    public int biClrUsed;
    public int biClrImportant;

    public BmpInfoHerder()
    {
    }
  }

  public class RGBQUAD
  {
    public byte rgbBlue;
    public byte rgbGreen;
    public byte rgbRed;
    public byte rgbReserved;

    public RGBQUAD()
    {
    }
  }
}

使用示例
BmpConvert bmpConvert = new BmpConvert(srcBtimap, (short)1);
byte[] bmpData = bmpConvert.getData();

bmpData为转换后像素深度为1的BMP位图数据,写入文件即可。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将24位位图转换成8位位图的过程中,需要用到调色板。调色板是一个包含256种颜色的表格,每个颜色都由三个8位组成的RGB值来表示。具体的转换步骤如下: 1. 创建一个空白的8位位图,并设置它的宽度和高度与原始24位位图相同。 2. 创建一个调色板,其中包含256种颜色。可以使用ColorPalette类来创建调色板。 3. 遍历原始24位位图的每个像素,将它的RGB值转换成一个0到255之间的整数,然后将该整数作为调色板中对应颜色的索引,将索引值写入新的8位位图中。 4. 将调色板与新的8位位图相关联,使用Bitmap类的SetPixel和GetPixel方法可以完成这一步操作。 5. 最后保存新的8位位图即可。 下面是一个C#代码示例,可以将24位位图转换成8位位图: ```csharp public static Bitmap ConvertTo8bpp(Bitmap bmp) { // 创建一个新的8位位图 Bitmap newBmp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format8bppIndexed); // 创建调色板 ColorPalette pal = newBmp.Palette; for (int i = 0; i < 256; i++) { pal.Entries[i] = Color.FromArgb(i, i, i); } newBmp.Palette = pal; // 遍历原始位图的每个像素,并将RGB值转换成索引 for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { Color color = bmp.GetPixel(x, y); int index = (int)(0.299 * color.R + 0.587 * color.G + 0.114 * color.B); newBmp.SetPixel(x, y, Color.FromArgb(index, index, index)); } } return newBmp; } ``` 在这个示例中,使用了YUV颜色空间的转换公式将RGB值转换成了索引。可以根据具体需求使用不同的转换公式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值