PlotterHMI/bmp/bwbmp.cpp

663 lines
18 KiB
C++
Raw Permalink Normal View History

2024-02-06 06:19:53 +00:00
#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 | 100 |
--------------------------------------------------
| 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;
}