#include "datafiledst.h"


DataFileDst::DataFileDst()
{
    m_colorNum = 0;//颜色数
    m_pColor = NULL;//颜色rgb值
    m_beadSequinTable.clear();
    m_beadSequinTable.resize(BEADSEQUINTYPE);
    memset(m_beadSequinTable.data(),0,m_beadSequinTable.size());
    m_beadSequinMap.clear();
    m_beadSequinMap.resize(BEADSEQUINTYPE);
    memset(m_beadSequinMap.data(),0,m_beadSequinMap.size());
}

DataFileDst::~DataFileDst()
{
}

void DataFileDst::initColor(int cnum, QRgb *pColor)
{
    m_colorNum = cnum;//颜色数
    m_pColor = pColor;//颜色rgb值
    qDebug()<<"m_colorNum"<<m_colorNum;
}

void DataFileDst::clear()
{
    m_fileFullPathName.clear(); // 文件路径
    m_fileData.clear();         // 文件数据内容
    m_embAbsData.clear();          // 转换后的数据
}

void DataFileDst::initFile(const QString &fullPathName)
{
    clear();
    QFileInfo file(fullPathName);
    if (file.exists() && file.isFile())
    {
        m_fileFullPathName = fullPathName;
        m_fileName = fullPathName;
        qDebug()<<"m_fileFullPathName 1"<<m_fileFullPathName;
    }
    else
    {
        qDebug() << "Init file failed path =" << m_fileFullPathName;
    }
}

void DataFileDst::loadFile()
{
    QFile rdfile(m_fileFullPathName);
    if(!rdfile.open(QIODevice::ReadOnly))
    {
        qDebug() << "open file fail when read, path =" << m_fileFullPathName;
        return;
    }

    m_fileData = rdfile.readAll();

    rdfile.close();

    return;
}

void DataFileDst::saveFile()
{
    QFile wrfile(m_fileFullPathName);
    if(!wrfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qDebug() << "open file fail when wirte, path =" << m_fileFullPathName;
        return;
    }
    else
    {
        wrfile.write(m_fileData);
#ifdef Q_OS_LINUX
        system("sync");
#endif
        wrfile.close();
    }

    return;
}

// 文件所在目录
QString DataFileDst::getFileFullPath()
{
    QFileInfo file(m_fileFullPathName);
    return file.absoluteFilePath();
}

// 文件名称（包括扩展名）
QString DataFileDst::getFileFullName()
{
    QFileInfo file(m_fileFullPathName);
    return file.fileName();
}

// 文件名称（不包括扩展名）
QString DataFileDst::getFileName()
{
    QFileInfo file(m_fileFullPathName);
    return file.completeBaseName();
}

// 文件扩展名
QString DataFileDst::getFileSuffix()
{
    QFileInfo file(m_fileFullPathName);
    return file.suffix();
}

int DataFileDst::getStitchNums()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->itemNums;
}

int DataFileDst::getColorNums()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->colorNum;
}
//测试fileid用，目前这个函数没用到
int DataFileDst::getFileid()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->fileid;
}
int DataFileDst::getDatWidth()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return (pDstHead->maxX - pDstHead->minX);
}

int DataFileDst::getDatHeight()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return (pDstHead->maxY - pDstHead->minY);
}

int DataFileDst::getMaxX()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->maxX;
}

int DataFileDst::getMinX()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->minX;
}

int DataFileDst::getMaxY()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->maxY;
}

int DataFileDst::getMinY()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->minY;
}

int DataFileDst::getJumpNeedleNum()
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }

    DataDs16FileHead * pDstHead = (DataDs16FileHead *)((m_embAbsData.data()));
    return pDstHead->jumpNeedleNum;
}

// 设置珠片码对应表
int DataFileDst::setBeadSequinTable(u8 * val)
{
    if(val == NULL)
    {
        return -1;
    }

    memcpy(m_beadSequinTable.data(),(char*)val,m_beadSequinTable.size());
    return 0;
}

// 得到有效珠片码的位图
int DataFileDst::getBeadSequinMap(QByteArray & map)
{
    if(m_embAbsData.size() <= 0)
    {
        return 0;
    }
    map.append(m_beadSequinMap);

    return 0;
}

// 转换为绝对坐标数据，同时得到最大最小值
void DataFileDst::convertDataToAbs()
{
    QByteArray ds4Data;//相对坐标
    m_embAbsData.clear();

    loadFile();     // 如果数据未读取，重新读取

    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        qDebug("dst size less then headsize");
        return;
    }
    //    int dstHeadSize = sizeof(DstHead);
    //    qDebug()<<"dstHeadSize"<<dstHeadSize;

    size -= sizeof(DstHead);
    int stepsize = size/sizeof(DstStep);
    if (stepsize <= 0)
    {
        qDebug("dst data size err");
        return;
    }

    DstHead * pDstHead = (DstHead *)((m_fileData.data()));
    DstStep * dstDataBeg = (DstStep *)((m_fileData.data() + sizeof(DstHead)));
    DstStep * dstDataPtr = dstDataBeg;

    //qDebug()<<"Ds4Item begin";
    // 绝对坐标数据
    DataDs16FileHead dhead;
    memset(&dhead, 0, sizeof(DataDs16FileHead));

    Ds4Item * pData = new Ds4Item[stepsize*2];
    if (pData == NULL)
    {
        qDebug("new DsAbsItem failed, size=%d", stepsize);
        return;
    }

    Ds4Item ds4Item;
    Ds4Item bds4Item;   // 上一针数据
    u8  bctrl,jctrl,ctrl;

    int dxy;
    int rslt;
    int colornum = 1;
    u32 jumpNum = 0;    // 连续跳针的个数
    u32 jumpNeedleNum = 0;

    bctrl = 0;
    u32 openSequin = 0;     // 开关亮片码状态
    u32 zeroJump = 0;       // 空跳个数

    //int predr,curdr;
    //predr = curdr = 0.0;
    // 得到最大最小值, 同时转换为相对坐标数据
    int i = 0;
    int stepidx = 0;

    do
    {
        if (i < stepsize)
        {
            rslt = changeDstStep(dstDataPtr, ds4Item);//三字节针步转换

            if (rslt >= 0)
            {
                ctrl = ds4Item.ctrl;
                dxy = ((ds4Item.dx == 0) && (ds4Item.dy == 0))? 0:1;
                jctrl = ctrl;       // 跳针属性临时寄存

                if (ctrl == DATA_EMB)
                {// 运针
                    if (i == 0)
                    {// 第1针特殊处理
                        if (dxy == 0)
                        {// 第1针为空针转换为跳针，为了避免第1针锁针添加失败
                            ctrl = DATA_JUMP;
                            ds4Item.ctrl = DATA_JUMP;
                        }
                        else
                        {
                            { // 第1针为入针则向后扫描，如果第二针也是运针，则将第1针入针转换为跳针
                                DstStep * ndstDataPtr = dstDataPtr;
                                Ds4Item nds4Item;   // 下一针数据

                                ndstDataPtr++;
                                rslt = changeDstStep(ndstDataPtr, nds4Item);    //三字节针步转换

                                if (rslt != 0)
                                {
                                    break;
                                }

                                if (nds4Item.ctrl == DATA_EMB)
                                {
                                    ctrl = DATA_JUMP;
                                    ds4Item.ctrl = DATA_JUMP;
                                }
                            }

                            { // 第1针为入针则向后扫描，如果有连续的3个以上跳针(或1个以上空跳)，则将第1针入针转换为跳针
                                int count = 0;
                                DstStep * ndstDataPtr = dstDataPtr;
                                Ds4Item nds4Item;   // 下一针数据

                                do
                                {
                                    ndstDataPtr++;
                                    rslt = changeDstStep(ndstDataPtr, nds4Item);    //三字节针步转换

                                    if (rslt != 0)
                                    {
                                        break;
                                    }

                                    if (nds4Item.ctrl == DATA_JUMP)
                                    {
                                        count++;
                                        if ((nds4Item.dx == 0) && (nds4Item.dy == 0))
                                        {
                                            count += 2;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }

                                    if (count >= 3)
                                    {
                                        break;
                                    }
                                }while(1);

                                if (count >= 3)
                                {
                                    ctrl = DATA_JUMP;
                                    ds4Item.ctrl = DATA_JUMP;
                                }
                            }
                        }
                    }
                    else if (((i == 1) && (sqrt(ds4Item.dx*ds4Item.dx+ds4Item.dy*ds4Item.dy) >= 60)) ||   // 第2针时,如果当前针位移大于6mm,下1针是运针,当前针转换为跳针
                             (bctrl == DATA_CHGND) ||        // 上1针为换色码时,如果下1针是运针,则当前针改为跳针
                             (jumpNum >= 2) ||               // 前面连续2个以上跳针时,如果当前针和下一针是运针,则当前针改为跳针
                             0 )
                    {
                        DstStep * ndstDataPtr = dstDataPtr;
                        Ds4Item nds4Item;   // 下一针数据

                        ndstDataPtr++;
                        rslt = changeDstStep(ndstDataPtr, nds4Item);    //三字节针步转换

                        if (rslt == 0)
                        {
                            if (nds4Item.ctrl == DATA_EMB)
                            {
                                ctrl = DATA_JUMP;
                                ds4Item.ctrl = DATA_JUMP;
                            }
                        }
                    }

                    if (zeroJump != 0)
                    {// 处理珠片码
                        bds4Item.ctrl = DATA_EMB;
                        bds4Item.attr |= (zeroJump & 0x1f);
                        m_beadSequinMap[(zeroJump & 0x1f)] = 1;     // 位图有效
                        memcpy(&(pData[stepidx]), &bds4Item, sizeof(Ds4Item));
                        stepidx++;
                        zeroJump = 0;
                    }

                    if ((ctrl == DATA_EMB) || (dxy == 1))
                    {// 保存针步
                        memcpy(&(pData[stepidx]), &ds4Item, sizeof(Ds4Item));
                        stepidx++;
                    }
                }
                else if (ctrl == DATA_CHGND)
                {// 换色
                    if (zeroJump != 0)
                    {
                        bds4Item.ctrl = DATA_EMB;
                        bds4Item.attr |= (zeroJump & 0x1f);
                        m_beadSequinMap[(zeroJump & 0x1f)] = 1;     // 位图有效
                        memcpy(&(pData[stepidx]), &bds4Item, sizeof(Ds4Item));
                        stepidx++;
                        zeroJump = 0;
                    }

                    if (bctrl == DATA_CHGND)     // 上一针也为换色码
                    {
                        ctrl = DATA_PAUSE;  // 将此换色码改为暂停码
                        ds4Item.ctrl = ctrl;
                    }

                    {// 保存换色(暂停)针步
                        memcpy(&(pData[stepidx]), &ds4Item, sizeof(Ds4Item));
                        stepidx++;
                    }

                    if (ctrl == DATA_CHGND)
                    {
                        colornum++;
                    }

                    if (ctrl == DATA_CHGND)
                    {// 换色后插入毛巾高度码:DATA_TOWELHIGH
                        ds4Item.ctrl = DATA_TOWELHIGH;
                        memcpy(&(pData[stepidx]), &ds4Item, sizeof(Ds4Item));
                        stepidx++;
                    }
                }
                else if (ctrl == DATA_JUMP)
                {// 跳针
                    if (openSequin == 0)
                    {// 不在开关状态码过程中
                        if (dxy != 0)
                        {// 非空跳
                            jumpNeedleNum++;
                            memcpy(&(pData[stepidx]), &ds4Item, sizeof(Ds4Item));
                            stepidx++;
                        }
                    }
                    else
                    {// 开关亮片码中 判断珠片码
                        if (dxy != 0)
                        {// 非空跳
                            if (zeroJump != 0)
                            {// 保存前一次的珠片码
                                bds4Item.ctrl = DATA_EMB;
                                bds4Item.attr |= (zeroJump & 0x1f);
                                m_beadSequinMap[(zeroJump & 0x1f)] = 1;     // 位图有效
                                memcpy(&(pData[stepidx]), &bds4Item, sizeof(Ds4Item));
                                stepidx++;
                                zeroJump = 0;
                            }

                            memcpy(&bds4Item, &ds4Item, sizeof(Ds4Item));   // 保存当前珠片信息
                            zeroJump = 1;
                        }
                        else
                        {
                            zeroJump++;
                        }
                    }
                }
                else if (ctrl == DATA_OPEN_SEQUIN)
                {// 开关亮片功能码
                    if (openSequin == 0)
                    {
                        openSequin = 1;     // 进入开关亮片状态
                        zeroJump = 0;
                    }
                    else
                    {
                        if (zeroJump != 0)
                        {// 保存前一次的珠片码
                            bds4Item.ctrl = DATA_EMB;
                            bds4Item.attr |= (zeroJump & 0x1f);
                            m_beadSequinMap[(zeroJump & 0x1f)] = 1;     // 位图有效
                            memcpy(&(pData[stepidx]), &bds4Item, sizeof(Ds4Item));
                            stepidx++;
                            zeroJump = 0;
                        }

                        openSequin = 0;     // 退出开关亮片状态
                    }
                }
                else if (ctrl == DATA_END)
                {// 结束码
                    memcpy(&(pData[stepidx]), &ds4Item, sizeof(Ds4Item));
                    stepidx++;
                    break;
                }
                else // 未定义
                {
                }

                if ((openSequin == 0) &&     // 开关亮片状态:关
                        (jctrl == DATA_JUMP) &&  // 原始数据是跳针
                        1)
                {// 连续跳针的个数
                    jumpNum++;
                }
                else
                {
                    jumpNum = 0;
                }

                bctrl = jctrl;
            }

            dstDataPtr++;
            i++;
        }
        else
        {
            break;
        }
    }while(1);


    //qDebug()<<"Ds4Item end";
    /*
    for (i=0;i<BEADSEQUINTYPE;i++)
    {// 测试,临时赋值
        if (m_beadSequinMap.at(i) == 1)
        {
            qDebug()<<"m_beadSequinTable["<< (int)(i) <<"] = "<<(int)(m_beadSequinTable.at(i));
        }
    }
    */
    //再将相对坐标转换为绝对坐标---开始
    ds4Data.clear();
    ds4Data.append((char *)pData, stepidx*sizeof(Ds4Item));//相对坐标字节数组
    u32 fileID = 0;
    fileID = calcCheckSum32((u8 *)(ds4Data.data()) , ds4Data.length());		// 原始数据累加校验和

    QByteArray absItemAry;
    absItemAry.clear();

    DsAbsItem absItem;
    memset(&absItem,0,sizeof(DsAbsItem));

    u8 ctrlByte;
    u8 attrByte;
    u8 actionByte;
    int ddx, ddy;

    m_maxX = S32_MIN;
    m_maxY = S32_MIN;
    m_minY = S32_MAX;
    m_minX = S32_MAX;

    Ds4Item * pDs4Data = (Ds4Item *)(ds4Data.data());
    Ds4Item * ds4DataPtr = pDs4Data;

    int begX = pDstHead->startX;//起始点
    int begY = pDstHead->startY;
    int begR = 0;

    s32 ax = 0;     //起始点
    s32 ay = 0;
    s32 ar = 0;

    int ds4StepSize = ds4Data.size()/sizeof(Ds4Item);

    for (int i = 0; i < ds4StepSize; i++)
    {
        // 读入一个针步数据
        ctrlByte = ds4DataPtr->ctrl;
        attrByte = ds4DataPtr->attr;
        if ((attrByte & 0x1f) != 0)
        {
            actionByte = m_beadSequinTable.at((int)(attrByte & 0x1f));
        }
        else
        {
            actionByte = 0;
        }
        ddx = ds4DataPtr->dx * DATAFACTOR;
        ddy = ds4DataPtr->dy * DATAFACTOR;

        if ((attrByte & 0x80) != 0)
        {
            ddx *= -1;
        }
        if ((attrByte & 0x40) != 0)
        {
            ddy *= -1;
        }
        ddx *= DST_EMB_DATADIRX;        // X向数据坐标与下位机坐标系统的差异
        ddy *= DST_EMB_DATADIRY;        // Y向数据坐标与下位机坐标系统的差异

        ax += ddx;
        ay += ddy;
        //ar = atan2(ddy,ddx) * 10000;
        double tar = atan2(ddy,ddx);
        ar = (tar * 10000+0.5*(tar>0?1:-1));

        //中间数据
        absItem.ctrl = ctrlByte;
        absItem.attr = 0;
        if (actionByte != 0)
        {
            if (actionByte == 0x10)
            {// 叠片码特殊处理
                absItem.action = ((u16)(0x03)<<8) + 0x20;    // 根据参数将珠片码中对应的动作转为亮片和散数数据
            }
            else
            {
                absItem.action = ((u16)(actionByte)<<8) + 0x20;    // 根据参数将珠片码中对应的动作转为亮片和散数数据
            }
        }
        else
        {
            absItem.action = 0;
        }
        absItem.ax = ax;
        absItem.ay = ay;
        absItem.ar = ar;

        if (ax > m_maxX)
        {
            m_maxX = ax;
        }
        if (ax < m_minX)
        {
            m_minX = ax;
        }
        if (ay > m_maxY)
        {
            m_maxY = ay;
        }
        if (ay < m_minY)
        {
            m_minY = ay;
        }

        absItemAry.append((char*)&absItem,sizeof(DsAbsItem));

        ds4DataPtr++;
    }

    //qDebug()<<"DsAbsItem end";

    //再将相对坐标转换为绝对坐标---结束

    //qDebug()<<"dhead begin";
    // 文件头转换
    QString name = getFileFullName();
    int namelen = name.size();
    if (namelen > HEAD_NAME_STR_LEN)
    {
        namelen = HEAD_NAME_STR_LEN;
    }
    QByteArray array = name.toLocal8Bit().data();
    int asize = array.length();
    memcpy(dhead.fileName, array, asize);   // 文件名称
    dhead.dataSize = ds4StepSize*sizeof(DsAbsItem);   // 数据字节数
    dhead.itemNums = ds4StepSize;                    // 数据项个数
    dhead.bytesPerItem = sizeof(DsAbsItem);           // 每项占的字节数
    dhead.bytesPerBlk = MAX_EXDP_LEN;               // 数据内容划分块大小
    dhead.dataChecksum = calcCheckSum32((u8 *)(absItemAry.data()) , dhead.dataSize);		// 数据累加校验和
    dhead.checkCrc = calcCrc16((u8 *)(&dhead), HEAD_FIX_INFO_LEN);          // 前面6个字段的CRC校验，（6个字段分别为：文件名称，字节数，项个数，每项字节数，每块字节数，数据累加和的CRC校验值）
    dhead.fileid = fileID;
    //qDebug()<<"dhead 1";

    dhead.anchorX = 0;  // 定位点坐标X
    dhead.anchorY = 0;  // 定位点坐标Y
    dhead.beginX = begX;                // 数据起点坐标X
    dhead.beginY = begY;                // 数据起点坐标Y，
    dhead.beginR = begR;                // 数据起点坐标R，
    dhead.minX = m_minX;
    dhead.maxX = m_maxX;
    dhead.minY = m_minY;
    dhead.maxY = m_maxY;                // 轮廓范围，使用重新计算之后的值
    dhead.jumpNeedleNum = jumpNeedleNum;// 跳针数
    dhead.colorNum = colornum;          // 颜色数
    //dsr头文件中的以何种工作机头定点
    dhead.begHead = pDstHead->begWorkHead;

    dhead.offsetEn = pDstHead->offsetEn;    //两个结构体不一样，所以参数在结构体存的位置不影响
    dhead.offsetX = pDstHead->offsetX;
    dhead.offsetY = pDstHead->offsetY;
    //dst的花版
    //dhead.patternType = 1;
    //qDebug()<<"m_maxX"<<m_maxX<<"m_minX"<<m_minX;
    //qDebug()<<"m_maxY"<<m_maxY<<"m_minY"<<m_minY;

    // 色序表
    //qDebug()<<"dhead 2";
    checkDefaultSwitchTable(colornum);      // 检查默认换色表
    memcpy(dhead.switchTable, pDstHead->switchTable, EMB_BF_SW_ND);

    //qDebug()<<"dhead 3";
    // 保存文件头到数组中
    m_embAbsData.append((char *)(&dhead), sizeof(DataDs16FileHead));

    //qDebug()<<"dhead 4";
    // 保存数据到数组中
    //qDebug()<<"ds4StepSize"<<ds4StepSize;

    m_embAbsData.append(absItemAry);
    delete []pData;

    //qDebug()<<"dhead end";

    return;
}

void DataFileDst::writePointToFile(u8 type, int x, int y, int st,u8 workHead)
{
    if(st == 0){}
    if(m_fileData.size() <= 0)
    {
        return;
    }

    DstHead * pDstHead = (DstHead *)((m_fileData.data()));
    if(type == START_POINT)
    {
        pDstHead->begWorkHead=workHead;
        pDstHead->startX = x;
        pDstHead->startY = y;
    }

    QFile wfile(m_fileFullPathName);
    if(!wfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qDebug() << "open file fail when read, path =" << m_fileFullPathName;
        return;
    }

    wfile.write(m_fileData);
#ifdef Q_OS_LINUX
    system("sync");
#endif
    wfile.close();
}

//将fcg里的 偏移点XY写在dst头文件里
void DataFileDst::writeOffsetXYMoveToFile(s32 EnFlag,s32 offsetX,s32 offsetY)
{
    if(m_fileData.size() <= 0)
    {
        return;
    }

    DstHead * pDstHead = (DstHead *)((m_fileData.data()));

    pDstHead->offsetEn = EnFlag;
    pDstHead->offsetX = offsetX;
    pDstHead->offsetY = offsetY;


    QFile wfile(m_fileFullPathName);
    if(!wfile.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qDebug() << "open file fail when read, path =" << m_fileFullPathName;
        return;
    }

    wfile.write(m_fileData);
#ifdef Q_OS_LINUX
    system("sync");
#endif
    wfile.close();
}

int DataFileDst::checkDstFile()
{
    loadFile();     // 如果数据未读取，重新读取

    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        qDebug("dsr size less then headsize");
        return -1;
    }

    size -= sizeof(DstHead);
    int stepsize = size/sizeof(DstStep);
    if (stepsize <= 0)
    {
        qDebug("dst data size err");
        return -1;
    }

    if (stepsize > PATTERN_LARGE_NEEDLES)//128万针
    {
        qDebug("dsr data size big");
        return -2;
    }

    return stepsize;
}

//-----------------------------------------------------------------------

//补光增加
QColor DataFileDst::getBrightAdd(QColor embcolor)
{
    QColor backColor;

    float rgbR = embcolor.red();//R值
    float rgbG = embcolor.green();//G值
    float rgbB = embcolor.blue();//B值

    float Y = 0.257 * rgbR + 0.504 * rgbG + 0.098 * rgbB + 16;
    float U = (-0.148) * rgbR - 0.291 * rgbG + 0.439 * rgbB +128;
    float V = 0.439 * rgbR - 0.368 * rgbG + 0.071 * rgbB + 128;

    Y = Y + 100;

    int R = 1.164*Y + 1.596 * V - 222.9;
    int G = 1.164*Y - 0.392 * U - 0.823 * V+ 135.6;
    int B = 1.164*Y + 2.017 * U- 276.8 ;

    if(R > 255)
    {
        R = 255;
    }
    else if (R < 0)
    {
        R = 0;
    }

    if(G > 255)
    {
        G = 255;
    }
    else if (G < 0)
    {
        G = 0;
    }

    if(B > 255)
    {
        B = 255;
    }
    else if (B < 0)
    {
        B = 0;
    }

    backColor.setRgb(R , G , B);

    return backColor;
}

//补光减少
QColor DataFileDst::getBrightDec(QColor embcolor)
{
    QColor backColor;

    float rgbR = embcolor.red();//R值
    float rgbG = embcolor.green();//G值
    float rgbB = embcolor.blue();//B值

    float Y = 0.257 * rgbR + 0.504 * rgbG + 0.098 * rgbB + 16;
    float U = (-0.148) * rgbR - 0.291 * rgbG + 0.439 * rgbB +128;
    float V = 0.439 * rgbR - 0.368 * rgbG + 0.071 * rgbB + 128;

    if( Y > 100.0)
    {
        Y = Y - 100.0;
    }
    else
    {
        Y = 16;
    }

    int R = 1.164*Y + 1.596 * V - 222.9;
    int G = 1.164*Y - 0.392 * U - 0.823 * V+ 135.6;
    int B = 1.164*Y + 2.017 * U- 276.8 ;

    if(R > 255)
    {
        R = 255;
    }
    else if (R < 0)
    {
        R = 0;
    }

    if(G > 255)
    {
        G = 255;
    }
    else if (G < 0)
    {
        G = 0;
    }

    if(B > 255)
    {
        B = 255;
    }
    else if (B < 0)
    {
        B = 0;
    }

    backColor.setRgb(R , G , B);

    return backColor;
}

// 生成预览文件
int DataFileDst::createPreviewImage(QImage * pImg, int saveflag, int penwidth, int gradientFlag, int reDraw)
{
#if(1)
    if(reDraw == 0)//图片存在则不重画
    {
        // 图片是否存在，存在则返回
        QString previewPath = getFileFullPathName() + ".preview.png";
        QFile imageFile(previewPath);
        if (imageFile.exists())
        {
            return 0;
        }
    }
#endif

    int newimgflag = 0;
    QImage * pImage;
    int width, height;
    if (pImg == NULL)
    {
        width = DST_PREVIEW_WIDTH;
        height = DST_PREVIEW_HEIGHT;
        pImage = new QImage(width, height, IMAGE_TYPE);
        newimgflag = 1;
    }
    else
    {
        pImage = pImg;
    }

    width = pImage->width();
    height = pImage->height();
    if (width <= DST_PREVIEW_SIDE*2 || height <= DST_PREVIEW_SIDE*2)
    {
        if (pImage != NULL && newimgflag == 1)
        {
            delete pImage;
        }
        qDebug("preview img too small");
        return -1;
    }

    memset(pImage->bits(), 0x00, pImage->byteCount());

    QPainter painter(pImage);
    QColor backcolor(255, 255, 255, 0);         // 透明背景
    QColor backColor1;
    QColor backColor2;

    // 背景
    QPen pen;
    pen.setWidth(penwidth);
    pen.setColor(backcolor);
    painter.setPen(pen);
    painter.setBrush(backcolor);
    painter.drawRect(0, 0, width, height);

    // 图形
    //qDebug()<<"convertDataToAbs defore";
    convertDataToAbs();     // 转换为绝对坐标数据
    //qDebug()<<"convertDataToAbs end";

#define SEG2_1  0.1
#define SEG2_2  1.0

    // absdat数据
    int size = m_embAbsData.size();
    if (size <= (int)sizeof(DataDs16FileHead))
    {
        qDebug("2 data less then head size");
        return -1;
    }
    DataDs16FileHead * pAbsHead = (DataDs16FileHead *)(m_embAbsData.data());
    int datasize = size - sizeof(DataDs16FileHead);
    if (datasize <= 0)
    {
        qDebug("absdat dataBegin err");
        return -1;
    }
    int stepsize = datasize/sizeof(DsAbsItem);
    if (stepsize <= 0)
    {
        qDebug("absdat data size err");
        return -1;
    }
    DsAbsItem * pData = (DsAbsItem *)(m_embAbsData.data() + sizeof(DataDs16FileHead));
    DsAbsItem * absDataPtr = pData;
    //--------

    // 图形显示区域
    int dpminx = DST_PREVIEW_SIDE;
    int dpmaxx = width - DST_PREVIEW_SIDE;
    int dpminy = DST_PREVIEW_SIDE;
    int dpmaxy = height - DST_PREVIEW_SIDE;

    // 计算缩放系数
    double factor, temp;
    if ((dpmaxx - dpminx) <= 0 || (dpmaxy - dpminy) <= 0)
    {
        return -1;
    }

    factor = (double)(fabs(m_maxX - m_minX)) / (dpmaxx - dpminx);      // 按x计算的缩放系数
    temp =   (double)(fabs(m_maxY - m_minY)) / (dpmaxy - dpminy);      // 按x计算的缩放系数

    if (temp >= factor)     // 使用较大的缩放系数
    {
        factor = temp;
    }

    // 计算显示参数，按照图形的实际位置显示（数据坐标零点对应图形中心）
    int dpx = (int)((dpminx+dpmaxx)/2 - ((m_maxX+m_minX)/factor)/2);
    int dpy = (int)((dpminy+dpmaxy)/2 - ((m_maxY+m_minY)/factor)/2);

    // 显示花样图形
    u8 ctrlByte;
    int dx;
    int dy;
    int colorIdx;
    int oldcolor;

    double datposx, datposy;
    int curx, cury, prex, prey;

    datposx = pAbsHead->beginX;
    datposy = pAbsHead->beginY;

    curx = (datposx) / factor + dpx;
    cury = (datposy) / factor + dpy;

    if (DST_SHOWDIRX == -1)
    {
        curx = (width)-curx;
    }
    if (DST_SHOWDIRY == -1)
    {
        cury = (height)-cury;
    }

    absDataPtr = pData;
    colorIdx = 0;
    oldcolor = -1;
    s16 jumpFlag = 0;//遇到跳针的标志

    for (int i = 0; i < stepsize; i++)
    {
        // 读入一个针步数据
        ctrlByte = absDataPtr->ctrl;

        if ( ctrlByte == DATA_EMB  ||
             0 )
        {
            prex = curx;
            prey = cury;

            dx = absDataPtr->ax;
            dy = absDataPtr->ay;

            datposx = dx;
            datposy = dy;

            curx = (datposx) / factor + dpx;
            cury = (datposy) / factor + dpy;

            if (DST_SHOWDIRX == -1)
            {
                curx = (width)-curx;
            }
            if (DST_SHOWDIRY == -1)
            {
                cury = (height)-cury;
            }

            if (oldcolor != colorIdx)
            {
                int cidx = pAbsHead->switchTable[colorIdx % EMB_BF_SW_ND];
                int cnum = m_colorNum;
                cnum /= sizeof(QRgb);
                if (cnum > EMB_BF_SW_ND)
                {
                    cnum = EMB_BF_SW_ND;
                }
                QColor embcolor;
                if (cnum != 0)
                {
                    cidx %= cnum;
                    QRgb * pColor = m_pColor;
                    if(pColor != NULL)
                    {
                        embcolor.setRgb(pColor[cidx]);
                    }
                    else
                    {
                        embcolor = QColor(Qt::green);
                    }
                }
                else
                {
                    embcolor = QColor(Qt::green);
                }

                pen.setColor(embcolor);
                painter.setPen(pen);
                oldcolor = colorIdx;

                if(gradientFlag == 1)//渐变色绘制
                {
                    backColor2 = getBrightDec(embcolor);
                    backColor1 = getBrightAdd(embcolor);
                }
            }

            if(gradientFlag == 1)//渐变色绘制
            {
                QLinearGradient gradient(prex, prey, curx, cury);

                //绣花跳针两针为一步，所以要将两针跳针每针分两段渐变，亮色部分拼接到一起
                //实现一针渐变的效果(可参考菱形图效果)
                if(jumpFlag == 1)
                {
                    jumpFlag = 2;
                    //两段渐变
                    gradient.setColorAt(SEG2_1,backColor1);
                    gradient.setColorAt(SEG2_2,backColor2);
                }
                else if (jumpFlag == 2)
                {
                    jumpFlag = 0;
                    //两段渐变
                    gradient.setColorAt(SEG2_1,backColor2);
                    gradient.setColorAt(SEG2_2,backColor1);
                }
                else
                {
                    gradient.setColorAt(0.1,backColor2);
                    gradient.setColorAt(0.5,backColor1);
                    gradient.setColorAt(1.0,backColor2);
                }

                painter.setRenderHint(QPainter::Antialiasing,true);
                QBrush brush(gradient);
                QPen npen(brush , penwidth);
                painter.setPen(npen);
            }

            if(i != 0)
            {
                painter.drawLine(prex, prey, curx, cury);
            }
        }


        //如果连续两步都是跳针，则过滤掉
        else if (ctrlByte == DATA_JUMP)
        {
            jumpFlag = 1;//跳针标志置为1

            DsAbsItem * JumpAbsDataPtr = pData;
            JumpAbsDataPtr = absDataPtr - 1;
            u8 beforectrlByte = JumpAbsDataPtr->ctrl;

            JumpAbsDataPtr = absDataPtr + 2;
            u8 nextctrlByte = JumpAbsDataPtr->ctrl;

            prex = curx;
            prey = cury;

            dx = absDataPtr->ax;
            dy = absDataPtr->ay;

            datposx = dx;
            datposy = dy;

            curx = (datposx) / factor + dpx;
            cury = (datposy) / factor + dpy;

            if (DST_SHOWDIRX == -1)
            {
                curx = (width)-curx;
            }
            if (DST_SHOWDIRY == -1)
            {
                cury = (height)-cury;
            }

            if (oldcolor != colorIdx)
            {
                int cidx = pAbsHead->switchTable[colorIdx % EMB_BF_SW_ND];
                int cnum = m_colorNum;
                cnum /= sizeof(QRgb);
                if (cnum > EMB_BF_SW_ND)
                {
                    cnum = EMB_BF_SW_ND;
                }
                QColor embcolor;
                if (cnum != 0)
                {
                    cidx %= cnum;
                    QRgb * pColor = m_pColor;
                    if(pColor != NULL)
                    {
                        embcolor.setRgb(pColor[cidx]);
                    }
                    else
                    {
                        embcolor = QColor(Qt::green);
                    }
                }
                else
                {
                    embcolor = QColor(Qt::green);
                }

                pen.setColor(embcolor);
                painter.setPen(pen);
                oldcolor = colorIdx;

                if(gradientFlag == 1)//渐变色绘制
                {
                    backColor2 = getBrightDec(embcolor);
                    backColor1 = getBrightAdd(embcolor);
                }
            }

            if(beforectrlByte == DATA_JUMP || nextctrlByte == DATA_JUMP)
            {
                //该针上下两针都是跳针则不画线
            }
            else
            {
                if(gradientFlag == 1)//渐变色绘制
                {
                    QLinearGradient gradient(prex, prey, curx, cury);
                    gradient.setColorAt(0.1,backColor2);
                    gradient.setColorAt(0.5,backColor1);
                    gradient.setColorAt(1.0,backColor2);

                    painter.setRenderHint(QPainter::Antialiasing,true);
                    QBrush brush(gradient);
                    QPen npen(brush , penwidth);
                    painter.setPen(npen);
                }

                if(i != 0)
                {
                    painter.drawLine(prex, prey, curx, cury);
                }
            }
        }
        ////

        else if (ctrlByte == DATA_CHGND)    // 换色
        {
            colorIdx++;
        }
        else
        {
            //    qDebug("other type=0x%x", ctrlByte);
        }

        absDataPtr++;
    }

    // 保存成文件
    QString preview = getFileFullPathName();
    if (saveflag != 0 && preview.isEmpty() == false)
    {
#if (1)
        preview += ".preview.png";
        pImage->save(preview, "png");
#endif
    }

    if (pImage != NULL && newimgflag == 1)
    {
        delete pImage;
    }

    return 0;
}

#define EMB_DST_DAT_DIRX    (-1)     // X向DST数据坐标和绝对数据坐标的差异
#define EMB_DST_DAT_DIRY    (1)      // Y向DST数据坐标和绝对数据坐标的差异

// 针步转换
int DataFileDst::changeDstStep(DstStep * pDststep, Ds4Item & ds4step)
{
    int dx, dy;
    u8 c1, c2, c3;
    u8 ctrl, attr;

    if (pDststep == NULL)
    {
        return -1;
    }

    c1 = pDststep->c1;
    c2 = pDststep->c2;
    c3 = pDststep->c3;

    dx = 0;
    dy = 0;

    if ((c1&0x08) != 0) {   dx -= 9;    }
    if ((c1&0x04) != 0) {   dx += 9;    }
    if ((c1&0x02) != 0) {   dx -= 1;    }
    if ((c1&0x01) != 0) {   dx += 1;    }
    if ((c2&0x08) != 0) {   dx -= 27;   }
    if ((c2&0x04) != 0) {   dx += 27;   }
    if ((c2&0x02) != 0) {   dx -= 3;    }
    if ((c2&0x01) != 0) {   dx += 3;    }
    if ((c3&0x08) != 0) {   dx -= 81;   }
    if ((c3&0x04) != 0) {   dx += 81;   }

    if ((c1&0x10) != 0) {   dy -= 9;    }
    if ((c1&0x20) != 0) {   dy += 9;    }
    if ((c1&0x40) != 0) {   dy -= 1;    }
    if ((c1&0x80) != 0) {   dy += 1;    }
    if ((c2&0x10) != 0) {   dy -= 27;   }
    if ((c2&0x20) != 0) {   dy += 27;   }
    if ((c2&0x40) != 0) {   dy -= 3;    }
    if ((c2&0x80) != 0) {   dy += 3;    }
    if ((c3&0x10) != 0) {   dy -= 81;   }
    if ((c3&0x20) != 0) {   dy += 81;   }

#if(0)
    switch (c3 & 0xF3)
    {
    case 0x03:     // 运针
        ctrl = DATA_EMB;
        break;
    case 0x43:     // 开关亮片码
        qDebug("Sequin switch, not support, c1=0x%x, c2=0x%x, c3=0x%x", c1, c2, c3);   // 不合法的DST
        return -2;
        break;
    case 0x83:     // 跳针
        ctrl = DATA_JUMP;
        break;
    case 0xC3:     // 换色
        ctrl = DATA_CHGND;
        break;
    case 0xF3:      // 结束
        if(dx == 0 && dy == 0)
        {
            ctrl = DATA_END;
        }
        break;
    default:
        if((c3 & 0x80) != 0x00)
        {
            if(dx == 0 && dy == 0)//空跳
            {
                ctrl = DATA_JUMP;
            }
            else
            {
                ctrl = DATA_OFFSET;
            }
        }
        else
        {
            ctrl = DATA_EMB;
        }
        break;
    }
#else
    if (c3 == 0xF3 && dx == 0 && dy == 0)
    {
        ctrl = DATA_END;            // 结束
    }
    else if ((c3&0xC3) == 0x03)     // 运针
    {
        ctrl = DATA_EMB;
    }
    else if ((c3&0xC3) == 0x83)     // 跳针
    {
        ctrl = DATA_JUMP;
    }
    else if ((c3&0xC3) == 0xC3)     // 换色
    {
        ctrl = DATA_CHGND;
    }
    else if ((c3&0xC3) == 0x43)     // 开关亮片码
    {
        ctrl = DATA_OPEN_SEQUIN;
    }
    else
    {
        ctrl = DATA_UNKNOW;
        qDebug("not know dst step, c1=0x%x, c2=0x%x, c3=0x%x", c1, c2, c3);   // 不合法的DST
        return -3;
    }
#endif

    // 添加针步
    attr = 0;

    dx *= EMB_DST_DAT_DIRX;      // X向显示坐标和数据坐标的差异
    dy *= EMB_DST_DAT_DIRY;      // Y向显示坐标和数据坐标的差异

    if (dx < 0) {   attr |= 0x80;   }
    if (dy < 0) {   attr |= 0x40;   }

    ds4step.ctrl = ctrl;
    ds4step.attr = attr;
    ds4step.dx = abs(dx);
    ds4step.dy = abs(dy);

    return 0;
}

// 检查并设置默认换色表
int DataFileDst::checkDefaultSwitchTable(int colornum)
{
    //loadFile();     // 如果数据未读取，重新读取

    int size = m_fileData.size();
    if (size <= (int)(sizeof(DstHead)))
    {
        qDebug("dst size less then headsize");
        return -1;
    }
    size -= sizeof(DstHead);
    int stepsize = size/sizeof(DstStep);
    if (stepsize <= 0)
    {
        qDebug("dst data size err");
        return -1;
    }

    DstHead * pDstHead = (DstHead *)((m_fileData.data()));

    int i;
    if (colornum < 1)
    {
        colornum = 1;
    }
    if (colornum > EMB_BF_SW_ND)
    {
        colornum = EMB_BF_SW_ND;
    }
    for (i = 0; i < colornum; i++)
    {
        if (pDstHead->switchTable[i] != 0x20)
        {
            break;
        }
    }
    if (i < colornum)  // 不全部是0x20, 可能设置过色序
    {
        for (i = 0; i < colornum; i++)
        {
            if (pDstHead->switchTable[i] != 0x00)
            {
                break;
            }
        }
    }

    if (i >= colornum && colornum > 1)  // 全部是0x20 或 全部是0, 未设置过色序
    {
        for (i = 0; i < colornum; i++)
        {
            pDstHead->switchTable[i] = i;     // 默认色序
        }
        saveFile();        // 保存文件
    }

    return 0;
}
