PlotterHMI/bmp/bwbmp.cpp
2024-02-06 14:19:53 +08:00

663 lines
18 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "bwbmp.h"
#include <QFile>
#include <QDebug>
BWBmp::BWBmp()
{
}
int BWBmp::LoadBiBmp(QString filename)
{
m_bwDdat.clear();
m_prDdat.clear();
QFile file(filename);
int rslt = file.open(QFile::ReadOnly);
if (rslt == 0)
{
qDebug() << "open file error" << filename;
return -1;
}
m_bwDdat = file.readAll();
if (m_bwDdat.size() <= (int)sizeof(BitmapHead))
{
m_bwDdat.clear();
file.close();
qDebug() << "file size error, size=" << m_bwDdat.size();
return -2;
}
BitmapHead * pHead = (BitmapHead *)(m_bwDdat.data());
if ( (pHead->identifier != 0x4d42) ||
(pHead->bitDatOffset != 0x3E) ||
(pHead->biSize != 0x28) ||
(pHead->biPlanes != 0x01) ||
(pHead->biBitPerPixel != 0x01) ||
(pHead->biCompression != 0x00) ||
0 )
{
m_bwDdat.clear();
file.close();
qDebug() << "not bi bmp";
return -3;
}
file.close();
return 0;
}
int BWBmp::SavePrBmp(QString filename)
{
QFile file(filename);
int rslt = file.open(QFile::ReadWrite | QFile::Truncate);
if (rslt == 0)
{
qDebug() << "open file error" << filename;
return -1;
}
file.write(m_prDdat);
file.close();
return 0;
}
int BWBmp::Compress(int idx, int dir)
{
/*
为了减少喷墨绘图仪的数据传输量,对黑白位图数据进行压缩。
压缩算法如下:
每个墨盒的位图数据宽度为300像素高度不确定
每个字节分为两段
用属性+值 的方式表示
__________________________________________________
| bit7 bit6 | bit5 bit4 bit3 bit2 bit1 bit0 |
--------------------------------------------------
| 属性 | 值 |
--------------------------------------------------
| 0 0 | 原始数据 |
--------------------------------------------------
| 0 1 | 连续数据1的个数 |
--------------------------------------------------
| 1 0 | 连续10个数据0的个数 |
--------------------------------------------------
| 1 1 | 连续数据0的个数 |
--------------------------------------------------
*/
if (dir < 0)
{
dir = -1;
}
else
{
dir = 1;
}
m_prDdat.clear();
if (m_bwDdat.isEmpty() == 1)
{
qDebug() << "bit dat empty";
return -1;
}
QByteArray tmppr;
tmppr.clear();
BitmapHead * pHead = (BitmapHead *)(m_bwDdat.data());
int width = pHead->biWidth;
int height = pHead->biHeight;
int widthBytes = (int)((width + 31) / 32) * 4;
if (widthBytes <= 0 || height < 1 || width > 0x1000000)
{
qDebug() << "bit dat error";
return -2;
}
const unsigned char * pBitDatBeg = (unsigned char *)(m_bwDdat.data() + pHead->bitDatOffset);
const unsigned char * pTmpDat;
if (dir == -1)
{
pBitDatBeg += widthBytes * (height -1);
}
const unsigned char * pBitDat = pBitDatBeg;
int * countBuff = new int [width];
if (countBuff == NULL)
{
qDebug() << "no enough memory";
return -3;
}
memset(countBuff, 0, sizeof(int)*width);
unsigned char tmpdat, mod;
int datsta = -1;
int count0 = 0;
int count1 = 0;
int i, j, k, l;
for (i = 0; i < height; i++) // 行计数
{
pTmpDat = pBitDat;
int countIdx = 0;
count0 = 0;
count1 = 0;
for (j = 0, k = 0; (j < widthBytes) && (k < width); j++) // 行内扫描检测出每段连续0和1的个数
{
tmpdat = *pTmpDat++;
//qDebug()<<j+i*widthBytes<<" "<<tmpdat;
mod = 0x80;
if((width - k) <= 8)
{
// tmpdat = tmpdat >> (8 - (width - k ));
}
for (mod = 0x80; (mod != 0) && (k < width); k++, mod /= 2)
{
if ((tmpdat & mod) == 0)
{
if (datsta == 1)
{
count1 |= 0x80000000;
countBuff[countIdx] = count1;
countIdx++;
count1 = 0;
}
datsta = 0;
count0++;
}
else
{
if (datsta == 0)
{
countBuff[countIdx] = count0;
countIdx++;
count0 = 0;
}
datsta = 1;
count1++;
}
}
}
if (count0 != 0)
{
countBuff[countIdx] = count0;
countIdx++;
count0 = 0;
}
if (count1 != 0)
{
count1 |= 0x80000000;
countBuff[countIdx] = count1;
countIdx++;
count1 = 0;
}
int psta = 0;
int pcount = 0;
unsigned char tgtdat = 0, pmod = 0x20, nums;
for (l = 0; l < countIdx; l++) // 分析数据,生成压缩数据
{
if ((countBuff[l] & 0x80000000) != 0)
{
count1 = countBuff[l] & 0xfffffff;
while (count1 != 0)
{
if (psta == 0) // 当前状态是原始数据
{
if (pcount != 0)
{
while (count1 != 0 && pcount != 0)
{
tgtdat |= pmod;
pcount--;
count1--;
pmod *= 2;
}
if (pcount == 0) // 够一个位图
{
tgtdat &= 0x3f;
tmppr.append(tgtdat); // 添加
tgtdat = 0x00;
}
}
}
if (pcount == 0 && count1 != 0) //
{
while (count1 != 0)
{
if (count1 <= 6)
{
psta = 0x00; // 位图模式
tgtdat = psta;
pmod = 0x01;
pcount = 6;
break;
}
else
{
if (count1 > 64)
{
nums = 64;
}
else
{
nums = count1;
}
psta = 0x40;
tgtdat = psta;
tgtdat |= (nums & 0x3f);
tmppr.append(tgtdat); // 添加
//qDebug()<<tmppr.size()<<tgtdat;
count1 -= nums;
}
}
}
}
}
else
{
count0 = countBuff[l] & 0xfffffff;
while (count0 != 0)
{
if (psta == 0) // 当前状态是原始数据
{
if (pcount != 0)
{
while (count0 != 0 && pcount != 0)
{
tgtdat &= (~pmod);
pcount--;
count0--;
pmod *= 2;
}
if (pcount == 0) // 够一个位图
{
tgtdat &= 0x3f;
tmppr.append(tgtdat); // 添加
//qDebug()<<tmppr.size()<<tgtdat;
tgtdat = 0x00;
}
}
}
if (pcount == 0 && count0 != 0) //
{
while (count0 != 0)
{
if (count0 <= 6)
{
psta = 0x00; // 位图模式
tgtdat = psta;
pmod = 0x01;
pcount = 6;
break;
}
else
{
int muti = 1;
if (count0 >= 640)
{
nums = 64;
muti = 10;
psta = 0x80;
}
else if (count0 >= 64)
{
nums = (int)(count0/10);
muti = 10;
psta = 0x80;
}
else
{
nums = count0;
muti = 1;
psta = 0xC0;
}
tgtdat = psta;
tgtdat |= (nums & 0x3f);
tmppr.append(tgtdat); // 添加
//qDebug()<<tmppr.size()<<tgtdat;
count0 -= nums * muti;
}
}
}
}
}
}
if (psta == 0 && pcount != 0) // 不满一个位图的数据(小于6)
{
pcount = 0;
tgtdat &= 0x3f;
tmppr.append(tgtdat); // 添加
tgtdat = 0x00;
}
// 下一行
pBitDat += widthBytes * dir;
}
delete []countBuff;
// 添加文件头
CompBmpHead prHead;
memset(&prHead, 0, sizeof(CompBmpHead));
prHead.blkIdx = idx;
prHead.biHeight = pHead->biHeight;
prHead.biWidth = pHead->biWidth;
if (dir < 0)
{
prHead.compDir = 1;
}
else
{
prHead.compDir = 0;
}
unsigned int prsize = tmppr.size();
if (prsize >= pHead->biBitmapDatSize) // 压缩率不足
{
prHead.compType = 0; // 不压缩
prHead.datSize = pHead->biBitmapDatSize;
tmppr.clear();
pBitDat = pBitDatBeg;
for (i = 0; i < height; i++) // 行计数
{
tmppr.append((const char*)pBitDat, widthBytes);
pBitDat += widthBytes * dir;
}
}
else
{
prHead.compType = 1;
prHead.datSize = prsize;
}
m_prDdat.append((char*)(&prHead), sizeof(CompBmpHead));
m_prDdat.append(tmppr);
return 0;
}
int BWBmp::LoadPrBmp(QString filename)
{
m_fileName = filename;
m_rbwDdat.clear();
m_prDdat.clear();
QFile file(filename);
int rslt = file.open(QFile::ReadOnly);
if (rslt == 0)
{
qDebug() << "open file error" << filename;
return -1;
}
m_prDdat = file.readAll();
if (m_prDdat.size() <= 0)
{
file.close();
qDebug() << "file size error, size=" << m_prDdat.size();
m_prDdat.clear();
return -2;
}
file.close();
return 0;
}
int BWBmp::Unpress()
{
m_rbwDdat.clear();
QByteArray arrdat;
arrdat.clear();
QByteArray barr;
barr.clear();
int size = m_prDdat.size();
if (size < (int)sizeof(CompBmpHead))
{
qDebug() << "pr dat empty";
return -1;
}
CompBmpHead * pPrHead = (CompBmpHead *)(m_prDdat.data());
const unsigned char * pPrDdat = (unsigned char *)(m_prDdat.data() + sizeof(CompBmpHead));
size -= sizeof(CompBmpHead);
unsigned int biWidth = pPrHead->biWidth;
unsigned int biHeight = pPrHead->biHeight;
int widthBytes = (int)((biWidth + 31) / 32) * 4;
BitmapHead bmpHead;
memset(&bmpHead, 0, sizeof(BitmapHead));
bmpHead.identifier = 0x4d42; // BM
bmpHead.bitDatOffset = 0x3E;
bmpHead.biSize = 0x28;
bmpHead.biPlanes = 1;
bmpHead.biBitPerPixel = 1;
bmpHead.biCompression = 0;
bmpHead.biHResolution = 3780; // 水平分辨率, 像素/米
bmpHead.biVResolution = 3780; // 垂直分辨率, 像素/米
bmpHead.biColors = 2; // 颜色数
bmpHead.biImpColors = 2; // 重要颜色数
bmpHead.palette[0].color = 0x00ffffff;
bmpHead.palette[1].color = 0x00000000;
bmpHead.biWidth = biWidth; // 位图宽度,以像素为单位
bmpHead.biHeight = biHeight; // 位图高度,以像素为单位
bmpHead.biBitmapDatSize = widthBytes*biHeight; // 位图数据区的大小(字节数), 必须是4的整数倍
bmpHead.fileSize = bmpHead.bitDatOffset + bmpHead.biBitmapDatSize;
#define VAL_OUTBMP 0xff // 位图之外的默认数据
m_rbwDdat.append((char*)(&bmpHead), sizeof(BitmapHead));
unsigned char sdat = 0;
int count0,count1,flag;
count0 = count1 = 0;
flag = -1;
for(int i = 0; i < size; i++)
{
count0 = count1 = 0;
flag = -1;
sdat = pPrDdat[i];
if((sdat & 0xC0) == 0xC0) // 连续0
{
count0 = sdat & 0x3f;
if (count0 == 0)
{
count0 = 64;
}
flag = 0;
}
else
{
if((sdat & 0x40) == 0x40) // 连续1
{
count1 = sdat & 0x3f;
if (count1 == 0)
{
count1 = 64;
}
flag = 1;
}
else if((sdat & 0x80) == 0x80) // 连续10个0
{
count0 = (sdat & 0x3f ) * 10;
if (count0 == 0)
{
count0 = 640;
}
flag = 0;
}
else // 原始数据
{
//每行扫描时最后一个像素为原始数据时原始数据个数
int pcount = 6;
int val = arrdat.size() % biWidth;
int cnt = biWidth - val;
int cnt1 = abs((int)biWidth - ((int)widthBytes-1) * 8);
if(cnt >= cnt1)
{
pcount = 6;
}
else
{
if(cnt > 6)
{
pcount = 6;
}
else
{
pcount = cnt;
}
}
unsigned char sch = sdat & 0x3f; //够一个位图
unsigned char pmod = 0x01;
while (pcount != 0)
{
if((sch & pmod) != 0) // 为1
{
arrdat.append((char)0x01);
}
else // 为0
{
arrdat.append((char)0x00);
}
pcount--;
pmod *= 2;
}
continue;
}
}
int count = 0;
unsigned char ch = 0;
if(flag == 0)
{
count = count0;
ch = 0;
}
else if(flag == 1)
{
count = count1;
ch = 1;
}
for(int j = 0; j < count; j++)
{
arrdat.append(ch);
}
}
int num = 0;
unsigned int lst = ((biWidth/8)*8+8);
for(unsigned int n = 0; n < biHeight; n++)
{
for(int j = 0; j < widthBytes; j++)
{
unsigned int cnt = j*8;
unsigned char abyte = 0;
int idx = n*biWidth+j*8;
for(int i = 0; i < 8; i++, idx++, cnt++)
{
//qDebug()<<"idx"<<idx;
//qDebug()<<"ch"<<ch;
if (cnt < biWidth)
{
unsigned char ch = arrdat[idx];
if (ch != 0)
{
abyte |= (ch << (7-i));
}
}
else if(cnt >= lst)
{
abyte = VAL_OUTBMP; // 默认值
break;
}
else
{
abyte |= ((VAL_OUTBMP) >> (i)); // 默认值
break;
}
}
//if(abyte != 0)
{
//qDebug()<<num<<" "<<abyte;
}
m_rbwDdat.append(abyte);
num++;
}
}
return 0;
}
int BWBmp::SaveBiBmp(QString filename)
{
QFile file(filename);
int rslt = file.open(QFile::ReadWrite | QFile::Truncate);
if (rslt == 0)
{
qDebug() << "open file error" << filename;
return -1;
}
file.write(m_rbwDdat);
file.close();
return 0;
}
QByteArray BWBmp::getPrBmpDat()
{
return m_prDdat;
}