605 lines
16 KiB
C++
605 lines
16 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 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;
|
||
}
|
||
|
||
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 * pBitDat = (unsigned char *)(m_bwDdat.data() + pHead->bitDatOffset);
|
||
|
||
const unsigned char * pTmpDat;
|
||
|
||
if (dir == -1)
|
||
{
|
||
pBitDat += widthBytes * (height -1);
|
||
}
|
||
|
||
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++;
|
||
// if(j+i*widthBytes > 12879)
|
||
// {
|
||
// qDebug()<<j+i*widthBytes<<" "<<tmpdat;
|
||
// }
|
||
|
||
//mod = 0x80;
|
||
mod = 0x01;
|
||
|
||
if((width - k) <= 8)
|
||
{
|
||
tmpdat = tmpdat >> (8 - (width - k ));
|
||
}
|
||
|
||
//for (mod = 0x80; (mod != 0) && (k < width); k++, mod /= 2)
|
||
for (mod = 0x01; (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;
|
||
pmod *= 2;
|
||
}
|
||
|
||
if (pcount == 0) // 够一个位图
|
||
{
|
||
tgtdat &= 0x3f;
|
||
m_prDdat.append(tgtdat); // 添加
|
||
//qDebug()<<m_prDdat.size()<<tgtdat;
|
||
tgtdat = 0x00;
|
||
}
|
||
}
|
||
}
|
||
if (pcount == 0 && count1 != 0) //
|
||
{
|
||
while (count1 != 0)
|
||
{
|
||
if (count1 <= 6)
|
||
{
|
||
psta = 0x00; // 位图模式
|
||
tgtdat = psta;
|
||
//pmod = 0x20;
|
||
pmod = 0x01;
|
||
pcount = 6;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if (count1 > 64)
|
||
{
|
||
nums = 64;
|
||
}
|
||
else
|
||
{
|
||
nums = count1;
|
||
}
|
||
|
||
psta = 0x40;
|
||
tgtdat = psta;
|
||
tgtdat |= (nums & 0x3f);
|
||
m_prDdat.append(tgtdat); // 添加
|
||
//qDebug()<<m_prDdat.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;
|
||
m_prDdat.append(tgtdat); // 添加
|
||
//qDebug()<<m_prDdat.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)
|
||
else if (count0 >= 64)
|
||
{
|
||
nums = (int)(count0/10);
|
||
muti = 10;
|
||
psta = 0x80;
|
||
}
|
||
else
|
||
{
|
||
nums = count0;
|
||
muti = 1;
|
||
psta = 0xC0;
|
||
}
|
||
|
||
tgtdat = psta;
|
||
tgtdat |= (nums & 0x3f);
|
||
m_prDdat.append(tgtdat); // 添加
|
||
//qDebug()<<m_prDdat.size()<<tgtdat;
|
||
count0 -= nums * muti;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (psta == 0 && pcount != 0) // 不满一个位图的数据(小于6)
|
||
{
|
||
pcount = 0;
|
||
tgtdat &= 0x3f;
|
||
m_prDdat.append(tgtdat); // 添加
|
||
tgtdat = 0x00;
|
||
}
|
||
|
||
// 下一行
|
||
pBitDat += widthBytes * dir;
|
||
}
|
||
|
||
delete []countBuff;
|
||
|
||
// m_prDdat.append((char*)); // 添加文件头
|
||
|
||
// int size = m_prDdat.size();
|
||
// for(int p = 0; p < size; p++)
|
||
// {
|
||
// unsigned char ch = m_prDdat[p];
|
||
// qDebug()<<p<<" "<<ch;
|
||
// }
|
||
|
||
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();
|
||
QFileInfo file(m_fileName);
|
||
QString name = file.filePath().remove("."+file.suffix());
|
||
|
||
QFile bfile(name);
|
||
bfile.open(QFile::ReadOnly);
|
||
barr = bfile.readAll();
|
||
BitmapHead * pHead = (BitmapHead *)(barr.data());
|
||
|
||
int widthBytes = (int)((pHead->biWidth + 31) / 32) * 4;
|
||
m_rbwDdat.append((char*)pHead,sizeof(BitmapHead));
|
||
|
||
if (m_prDdat.isEmpty() == 1)
|
||
{
|
||
qDebug() << "pr dat empty";
|
||
return -1;
|
||
}
|
||
|
||
unsigned char sdat = 0;
|
||
int count0,count1,flag;
|
||
count0 = count1 = 0;
|
||
flag = -1;
|
||
|
||
int size = m_prDdat.size();
|
||
for(int i = 0; i < size; i++)
|
||
{
|
||
// if(i > 3250)
|
||
// {
|
||
// int a = 0;
|
||
// a = 1;
|
||
// }
|
||
count0 = count1 = 0;
|
||
flag = -1;
|
||
|
||
sdat = m_prDdat[i];
|
||
|
||
if((sdat & 0xC0) == 0xC0) // 连续0
|
||
{
|
||
count0 = sdat & 0x3f;
|
||
flag = 0;
|
||
}
|
||
else
|
||
{
|
||
if((sdat & 0x40) == 0x40) // 连续1
|
||
{
|
||
count1 = sdat & 0x3f;
|
||
flag = 1;
|
||
}
|
||
else if((sdat & 0x80) == 0x80) // 连续10个0
|
||
{
|
||
count0 = (sdat & 0x3f ) * 10;
|
||
flag = 0;
|
||
}
|
||
else // 原始数据
|
||
{
|
||
//每行扫描时最后一个像素为原始数据时原始数据个数
|
||
int pcount = 6;
|
||
int val = arrdat.size() % pHead->biWidth;
|
||
int cnt = pHead->biWidth - val;
|
||
int cnt1 = abs(pHead->biWidth - (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 char abyte = 0;
|
||
unsigned int cnt = 0;
|
||
for(unsigned int n = 0; n < pHead->biHeight; n++)
|
||
{
|
||
for(int j = 0; j < widthBytes; j++)
|
||
{
|
||
abyte = 0;
|
||
for(int i = 0; i < 8; i++)
|
||
{
|
||
int idx = n*pHead->biWidth+j*8+i;
|
||
//qDebug()<<"idx"<<idx;
|
||
unsigned char ch = arrdat[idx] << i;
|
||
//qDebug()<<"ch"<<ch;
|
||
|
||
cnt = j*8 + i;
|
||
if(cnt < pHead->biWidth)
|
||
{
|
||
abyte |= ch;
|
||
}
|
||
else if(cnt == pHead->biWidth)
|
||
{
|
||
abyte = abyte << (8 - i);
|
||
}
|
||
else if(cnt >= ((pHead->biWidth/8)*8+8))
|
||
{
|
||
abyte = 0;
|
||
}
|
||
else
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
|
||
//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;
|
||
}
|