663 lines
18 KiB
C++
663 lines
18 KiB
C++
#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;
|
||
}
|