C/C++高級工程師 Android高級軟件工程師 IT集成工程師 音頻工程師 熟悉c,c++,java,c#,py,js,asp等多種語言 程序猿

置頂隨筆

gaudio是一個基于C/C++混合編程的跨平臺音頻庫,當前支持windows32操作系統和linux32位操作系統

修改記錄
1.2013.04.01
    初次發布
2.2013.04.10
    完成對wav格式采樣頻率8000-48000,采樣格式4,8,16,24,32的支持     
3.2013.05.01
    a.版本提升為1.4.0.8
    b.修改一個退出異常
    c.支持二源混音
    d.使用載入插件的方式提供對wav播放的支持
    e.增加對au格式的支持
    f.增加echo音效
    g.增加bassboost音效
    h.增加函數gaudio_address_get
    i.增加使用例子:echo/mixer/stream/boost
    j.把設置,獲取音源三維空間信息的函數調整為: gaudio_source_set_float3,gaudio_source_get_float3
    k.修改解碼器結構為回調模式
4.2013.05.10
    a.版本提升為1.6.8.0
    b.優化部分代碼
    c.增加speedchanger音效
    d.增加音頻翻轉(g168)
    e.增加音頻聲道交換(g168)
    f.增加聲道合并(g168)
    g.增加speedchanger/invert測試用例
    h.增加vc調用靜態鏈接庫libgaudio.lib
    i.增加調制音效和測試例子
    j.修改解碼器框架
    k.修改獲取音頻采樣編碼格式不正確的問題
    l.解決seek定位不準的問題
    m.增加音效鏈測試例子
    n.增加函數gaudio_set_long,gaudio_get_long
    o.修改stream例子
    p.支持壓縮mpc音頻格式
    q.支持ogg/vorbis格式
    r.修改獲取采樣格式錯誤的bug
    t.增加接口說明文檔    
5.2013.06.10
    a.版本提升為1.7.2.0
    b.gaudio_source_set_error_callback回調函數增加音源參數
    c.gaudio_source_set_finish_callback回調函數增加音源參數
    d.移除gaudio_get_version函數
    e.gaudio_effect_setcallback函數調整為gaudio_effect_set_callback
    f.使用插件式的音頻驅動模式 - gwinmm
    g.gaudio代碼優化
    h.增加音頻源碼率的獲取
    i.增加feature范例
    j.完善文檔
    k.增加對mp3的支持
    l.移除invert/modulator/bassboost例子
    m.增加balance
6.2013.07.07
    a.版本提升到1.8.0.2
    b.增加對交換文件aiff的支持
    c.修改音頻驅動插件實現
    d.增加移相器音效
    e.修改部分API接口使用的long為int32_t以方便移植
    f.增加code::blocks測試工程
    g.增加msvc2008測試工程
    h.增加函數接口gaudio_source_create_from_buffer2以播放raw音頻數據
    i.把各個音效參數提到單獨文件
    j.簡化wav解碼
    k.修改幾處內存泄漏
    l.增加音頻回錄功能,輸出格式MP2,MP3,APE,WV,AAC,WAV,AU,AIFF,VOC,CAF,OGG
    當前錄制信息:16位音頻,雙聲道,采樣頻率44100
    m.增加音頻回錄的例子recorder
    n.測試例子使用getopt和usage提示
    o.增加對tta格式的支持    
7.2013.07.28
    a.版本提升到1.9.8.6                   
    b.解決了wav,au,aiff播放進度不準的故障
    c.優化wav/au/aiff解碼性能        
    d.增加distortion音效              
    e.增加foldback distortion音效       
    f.增加distortion音效使用例子       
    g.增加聲音穿透力                      
    h.修改結構最大支持八聲道             
    i.增加portaudio插件驅動(win32&linux)  
    j.完成g168,bassbost的liux版本     
    k.完成wav,au音頻格式的linux版本      
    l.代碼增加部分注釋(未完成)            
    m.嘗試性支持linux操作系統             
    n.支持midi/mid音樂格式             
    o.解決了mixer混音退出報錯的問題
    p.skip id3v2    
8.2013.08.16
    a.版本提升到2.0.0.1                    
    b.變量宏增加AUDIO_ENUM前綴
    c.增加非標準插件gsndfile支持flac/ogg/au/wav/aiff/voc/caf/..基于(sndfile)
    d.改用mpg123解碼mp3
    e.支持FFT頻譜
9.2013.09.08
    a.版本提升到2.0.6.0
    b.修改CROSSFEED宏和相關    
    c.引入200號插件支持s3m/mod/it/xm音頻格式
    d.整理測試用例
    e.增加autowah音效
    f.增加驅動檢測
10.2015.12.10 版本2.2.1.0
支持常見音頻格式和音效,使用超級方便
下載在這里:/Files/gaimor/gaudio-sdk-2.2.1.0.zip

    
 
posted @ 2013-07-11 22:49 ccsdu2009 閱讀(5209) | 評論 (2)編輯 收藏

2019年8月14日

import QtQuick 2.11
import QtQuick.Controls 2.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import QtQuick.Window 2.11
import cplusplus 1.0

Rectangle
{
    id: base
    width:640
    height:480

    ColumnLayout
    {
        anchors.fill:parent
        anchors.margins: 6
        spacing: 4

        Rectangle
        {
            id:image
            Layout.fillWidth: true
            Layout.fillHeight: true
            color:"#cdcdc0"

            TextEdit
            {
                id:text
                anchors.centerIn: parent
                width:parent.width
                text:"請點擊下方按鍵"
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
                wrapMode: Text.WordWrap
                font.pointSize: 12
            }
        }

        RowLayout
        {
            Rectangle
            {
                Layout.fillWidth: true
            }

            Button
            {
                property int index: 0
                text:"點擊"

                onClicked:
                {
                    text.text = cplusplusObject.getString()
                }
            }

        }
    }
}

posted @ 2019-08-14 17:46 ccsdu2009 閱讀(1) | 評論 (0)編輯 收藏
 
ListView
        {
            id: view
            orientation: Qt.Horizontal
            Layout.fillWidth: true
            height:64
            //model: 180
            spacing: -24
            clip: true

            delegate: Rectangle
            {
                width: 50
                height: parent.height

                Image
                {
                    id:imageItem
                    width:64
                    height:64
                    anchors.centerIn: parent
                    source:getFileName(index*Math.floor(2560/180))
                    property int current: 0

                    onSourceChanged:
                    {
                        current = index;
                    }

                    MouseArea
                    {
                        id: mouseArea
                        anchors.fill: parent
                        onClicked:
                        {
                            var filename = getFileName(Math.floor(2560/180)*imageItem.current)
                            image.source = filename
                        }
                    }
                }

                function getFileName(index)
                {
                    return "images/"+index+".png"
                }
            }
        }
posted @ 2019-08-14 16:02 ccsdu2009 閱讀(3) | 評論 (0)編輯 收藏
 
import QtQuick 2.11
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3

Rectangle
{
    id
: base
    width:640
    height:480

    property int current: 0

    ColumnLayout
    {
        anchors.fill:parent
        anchors.margins: 6
        spacing: 4

        Image
        {
            id:image
            Layout.fillWidth: true
            Layout.fillHeight: true
            source:"2436.png"
        
}

        ProgressBar
        
{
            id
:progresBar
            visible: false
            Layout.fillWidth: true
            value:0.0
        
}

        Slider
        
{
            id
:slider1
            Layout.fillWidth: true
            orientation: Qt.Horizontal
            onValueChanged:
            {
                base.current = Math.floor(2560*value)
                var filename = "images/"+base.current+".png"
;
                image.source = filename
            
}
        }

        Timer
        
{
            interval
: 40
            running: true
            triggeredOnStart: true
;
            repeat
: true

            onTriggered:
            {
                base.current = base.current + 1
                if(base.current > 2560)
                    base.current = 0
;

                image.source = "images/" + base.current + ".png";
            
}
        }

        RowLayout
        
{
            Rectangle
            {
                Layout.fillWidth
: true
            
}

            Button
            
{
                text
:"預覽"

                onClicked:
                {
                    if(progresBar.visible)
                    {
                        progresBar.visible = false
;
                    
}
                    else
                    
{
                        progresBar.visible = true;
                    
}
                }
            }

            Button
            
{
                text
:"剪切"

                onClicked:
                {
                    if(progresBar.visible)
                    {
                        progresBar.visible = false
;
                    
}
                    else
                    
{
                        progresBar.visible = true;
                    
}
                }
            }
        }
    }
}
posted @ 2019-08-14 14:34 ccsdu2009 閱讀(2) | 評論 (0)編輯 收藏

2019年8月13日

#ifndef KEYWORD_HIGHLIGHTER_H
#define KEYWORD_HIGHLIGHTER_H
#include 
<QSyntaxHighlighter>
#include 
<QTextCharFormat>
#include 
<QRegularExpression>
#include 
<QTextDocument>

class KeyWordHighlighter final : public QSyntaxHighlighter
{
    Q_OBJECT
public:
    KeyWordHighlighter(QTextDocument
* parent = nullptr);
    
void setKeyWords(const QStringList& keywords);
protected:
    
void highlightBlock(const QString& text)override;
private:
    
struct HighlightingRule
    {
        QRegularExpression pattern;
        QTextCharFormat format;
    };

    QVector
<HighlightingRule> highlightingRules;
    QTextCharFormat keywordFormat;
};

#include "KeyWordHighLighter.h"

KeyWordHighlighter::KeyWordHighlighter(QTextDocument* parent):
QSyntaxHighlighter(parent)
{
}

void KeyWordHighlighter::setKeyWords(const QStringList& words)
{
    HighlightingRule rule;

    keywordFormat.setForeground(Qt::black);
    keywordFormat.setFontWeight(QFont::Bold);

    foreach(auto word,words)
    {
        rule.pattern = QRegularExpression(word);
        rule.format = keywordFormat;
        highlightingRules.append(rule);
    }
}

void KeyWordHighlighter::highlightBlock(const QString& text)
{
    foreach(auto rule,highlightingRules)
    {
        QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
        while(matchIterator.hasNext())
        {
            QRegularExpressionMatch match = matchIterator.next();
            setFormat(match.capturedStart(),match.capturedLength(),rule.format);
        }
    }
}
posted @ 2019-08-13 18:35 ccsdu2009 閱讀(5) | 評論 (0)編輯 收藏
 
#include <QStringList>
#include 
<QJsonArray>
#include 
<QJSonDocument>
#include 
<QJsonObject>
#include 
<QJsonValue>
#include 
<QFile>
#include 
<QDebug>
#include 
"test.h"

#define STR(o) #o
#define INSERT_ITEM(object,o) object.insert(STR(o),o);
#define INSERT_LIST(object,o)\
    {\
        auto array 
= QJsonArray::fromStringList(o);\
        
object.insert(STR(o),array);\
    }

struct Unit
{
    QString result;
    QString author;
    QString description;
    QString notes;

    QStringList key;
    
int minValue;
    QStringList items;
    QStringList attachment;

    QString toString()
    {
        QJsonObject 
object;
        INSERT_ITEM(
object,result)
        INSERT_ITEM(
object,author)
        INSERT_ITEM(
object,description)
        INSERT_ITEM(
object,notes)
        INSERT_LIST(
object,key)
        INSERT_ITEM(
object,minValue)
        INSERT_LIST(
object,items)
        INSERT_LIST(
object,attachment)

        QJsonDocument doc;
        doc.setObject(
object);
        
return doc.toJson(QJsonDocument::JsonFormat::Compact);
    }

    
bool loadFromFile(const QString& filename)
    {
        QFile file(filename);
        
if(!file.open(QIODevice::ReadOnly))
            
return false;

        QByteArray buffer 
= file.readAll();
        file.close();

        QJsonParseError error;
        QJsonDocument doc(QJsonDocument::fromJson(buffer,
&error));

        
if(error.error != QJsonParseError::NoError)
        {
            qDebug() 
<< "parse json file:"<<filename<< " failed!";
            
return false;
        }

        auto 
object = doc.object();
        
if(!object.contains("result"|| !object.contains("key"))
        {
            qDebug() 
<< "invalid json file:" << filename << " structure!";
            
return false;
        }

        result 
= object[STR(result)].toString();
        author 
= object[STR(author)].toString();
        description 
= object[STR(description)].toString();
        notes 
= object[STR(notes)].toString();

        minValue 
= object[STR(minValue)].toInt();

        auto fn 
= [](const QJsonArray& array)->QStringList
        {
            QStringList items;
            
foreach(auto item,array)
                items 
+= item.toString();
            
return items;
        };

        key 
= fn(object[STR(key)].toArray());
        items 
= fn(object[STR(items)].toArray());
        attachment 
= fn(object[STR(attachment)].toArray());
        
return true;
    }
};
 
void test()
{
    Unit unit;
    unit.attachment.append(
"acchemtn1");
    unit.attachment.append(
"acchemtn2");

    unit.key.append(
"key1");
    unit.author 
= "author";
    unit.description 
= "this is a remark";
    unit.items.append(
"item1");
    unit.items.append(
"item2");
    unit.items.append(
"item3");
    unit.minValue 
= 1;
    unit.notes 
= "notes";

    QFile file(
"file.json");
    file.open(QIODevice::WriteOnly);

    file.write(unit.toString().toLocal8Bit().data());

    file.close();

    qDebug() 
<< unit.toString();
}
posted @ 2019-08-13 14:43 ccsdu2009 閱讀(6) | 評論 (0)編輯 收藏

2019年8月12日

class VideoRenderer : public QObject, public QQuickFramebufferObject::Renderer, public QOpenGLFunctions
{
    Q_OBJECT
public:
    
explicit VideoRenderer(QQuickFramebufferObject* object);
    
~VideoRenderer();

    QOpenGLFramebufferObject
* createFramebufferObject(const QSize& size);
    
void render();
public slots:
    
void updateVideoFrame(AVFrame* frame);
    
void paint();
private:
    std::mutex mux;
    QGLShaderProgram program;
    GLuint yuv[
3= { 0 };
    GLuint textures[
3= { 0 };
    unsigned 
char* datas[3= { 0 };
    QSize videoSize;
    QQuickFramebufferObject
* fbo;
};

VideoRenderer::VideoRenderer(QQuickFramebufferObject
* object):
QObject(
object)
{
    fbo 
= object;
    initializeOpenGLFunctions();

    qDebug() 
<< program.addShaderFromSourceCode(QGLShader::Fragment, tString);
    qDebug() 
<< program.addShaderFromSourceCode(QGLShader::Vertex, vString);

    program.bindAttributeLocation(
"vertexIn", A_VER);
    program.bindAttributeLocation(
"textureIn", T_VER);
    
    qDebug() 
<< "program.link() = " << program.link();
    qDebug() 
<< "program.bind() = " << program.bind();

    
static const GLfloat ver[] = {
        
-1.0f,-1.0f,
        
1.0f,-1.0f,
        
-1.0f1.0f,
        
1.0f,1.0f
    };

    
static const GLfloat tex[] = {
        
0.0f1.0f,
        
1.0f1.0f,
        
0.0f0.0f,
        
1.0f0.0f
    };

    glVertexAttribPointer(A_VER, 
2, GL_FLOAT, 00, ver);
    glEnableVertexAttribArray(A_VER);

    glVertexAttribPointer(T_VER, 
2, GL_FLOAT, 00, tex);
    glEnableVertexAttribArray(T_VER);

    yuv[
0= program.uniformLocation("tex_y");
    yuv[
1= program.uniformLocation("tex_u");
    yuv[
2= program.uniformLocation("tex_v");

    mux.unlock();

    glGenTextures(
3, textures);
}

VideoRenderer::
~VideoRenderer()
{
    
if(datas[0])
    {
        
for(int i = 0; i < 3; i++)
            delete datas[i];
    }
}

void SaveAvFrame(const QString& file,AVFrame* avFrame)
{
    FILE 
*fDump = fopen(file.toLocal8Bit().data(), "ab");

    uint32_t pitchY 
= avFrame->linesize[0];
    uint32_t pitchU 
= avFrame->linesize[1];
    uint32_t pitchV 
= avFrame->linesize[2];

    uint8_t 
*avY = avFrame->data[0];
    uint8_t 
*avU = avFrame->data[1];
    uint8_t 
*avV = avFrame->data[2];

    
for (uint32_t i = 0; i < avFrame->height; i++) {
        fwrite(avY, avFrame
->width, 1, fDump);
        avY 
+= pitchY;
    }

    
for (uint32_t i = 0; i < avFrame->height / 2; i++) {
        fwrite(avU, avFrame
->width / 21, fDump);
        avU 
+= pitchU;
    }

    
for (uint32_t i = 0; i < avFrame->height / 2; i++) {
        fwrite(avV, avFrame
->width / 21, fDump);
        avV 
+= pitchV;
    }

    fclose(fDump);
}

void VideoRenderer::updateVideoFrame(AVFrame* frame)
{
    
if(!frame)
        
return;

    mux.
lock();

    
if (frame->width != videoSize.width() || frame->height != videoSize.height())
    {
        videoSize.setWidth(frame
->width);
        videoSize.setHeight(frame
->height);
        
if (datas[0])
        {
            
for (int i = 0; i < 3; i++)
            {
                delete datas[i];
                datas[i] 
= 0;
            }
        }

        datas[
0= new unsigned char[frame->width*frame->height];        //Y
        datas[1= new unsigned char[frame->width*frame->height / 4];    //U
        datas[2= new unsigned char[frame->width*frame->height / 4];    //V
    }

    
if (!datas[0])
    {
        datas[
0= new unsigned char[frame->width*frame->height];        //Y
        datas[1= new unsigned char[frame->width*frame->height / 4];    //U
        datas[2= new unsigned char[frame->width*frame->height / 4];    //V
    }

    
if (videoSize.width() == frame->linesize[0])
    {
        memcpy(datas[
0], frame->data[0], videoSize.width()*videoSize.height());
        memcpy(datas[
1], frame->data[1], videoSize.width()*videoSize.height() / 4);
        memcpy(datas[
2], frame->data[2], videoSize.width()*videoSize.height() / 4);
    }
    
else
    {
        
for (int i = 0; i < videoSize.height(); i++//
            memcpy(datas[0+ videoSize.width()*i, frame->data[0+ frame->linesize[0* i, videoSize.width());
        
for (int i = 0; i < videoSize.height() / 2; i++//U
            memcpy(datas[1+ videoSize.width() / 2 * i, frame->data[1+ frame->linesize[1* i, videoSize.width());
        
for (int i = 0; i < videoSize.height() / 2; i++//V
            memcpy(datas[2+ videoSize.width() / 2 * i, frame->data[2+ frame->linesize[2* i, videoSize.width());
    }


    mux.unlock();
    av_frame_free(
&frame);

    update();
}

void VideoRenderer::render()
{
    paint();
}

void VideoRenderer::paint()
{
    
if (videoSize.isEmpty())
        
return;

    mux.
lock();

    
//Y
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 
0, GL_RED, videoSize.width(), videoSize.height(), 0, GL_RED, GL_UNSIGNED_BYTE, 0);

    
//U
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 
0, GL_RED, videoSize.width() / 2, videoSize.height() / 20, GL_RED, GL_UNSIGNED_BYTE, 0);

    
//V
    glBindTexture(GL_TEXTURE_2D, textures[2]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 
0, GL_RED, videoSize.width() / 2, videoSize.height() / 20, GL_RED, GL_UNSIGNED_BYTE, 0);
 

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textures[
0]); // to y

    glTexSubImage2D(GL_TEXTURE_2D, 
000, videoSize.width(), videoSize.height(), GL_RED, GL_UNSIGNED_BYTE, datas[0]);
    glUniform1i(yuv[
0], 0);

    glActiveTexture(GL_TEXTURE0 
+ 1);
    glBindTexture(GL_TEXTURE_2D, textures[
1]); // 1 to u
    glTexSubImage2D(GL_TEXTURE_2D, 000, videoSize.width() / 2, videoSize.height() / 2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);
    glUniform1i(yuv[
1], 1);


    glActiveTexture(GL_TEXTURE0 
+ 2);
    glBindTexture(GL_TEXTURE_2D, textures[
2]); // 2 to v
    glTexSubImage2D(GL_TEXTURE_2D, 000, videoSize.width() / 2, videoSize.height() / 2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);

    glUniform1i(yuv[
2], 2);

    glDrawArrays(GL_TRIANGLE_STRIP, 
04);
    mux.unlock();

}
 
QOpenGLFramebufferObject
* VideoRenderer::createFramebufferObject(const QSize &size)
{
    QOpenGLFramebufferObjectFormat format;   
//當大小發生變化時,會調用此函數生成對應大小的FBO
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
    format.setSamples(
4);
    
return new QOpenGLFramebufferObject(size,format);
}
posted @ 2019-08-12 09:25 ccsdu2009 閱讀(3) | 評論 (0)編輯 收藏

2019年8月9日

#ifndef APPLICATION_H
#define APPLICATION_H
#include 
<QApplication>
#include 
<QSharedMemory>

class Application : public QApplication
{
    Q_OBJECT 
public:
    Application(
int argc,char** argv,const QString& app);
    
~Application();
public:
    
bool isRunning();
private:
    QSharedMemory sharedMemory;
};

#endif

#include "Application.h"

Application::Application(int argc,char** argv,const QString& app):
QApplication(argc,argv),
sharedMemory(app)
{
    if(!sharedMemory.isAttached())
        sharedMemory.create(app.size()+1);
}

Application::~Application()
{
}

bool Application::isRunning()
{
    return sharedMemory.attach();
}
posted @ 2019-08-09 14:36 ccsdu2009 閱讀(8) | 評論 (0)編輯 收藏

2019年8月5日

QML
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2

Column 
{
    width
:640
    height:400
    
    Image 
    { 
        id:image
        width:640
        cache: false
        source: "image://colors/red" 
    
}
    
    Connections
    
{
        target
: imagecontext
        onCallQmlRefeshImg:
        {
            image.source = ""
            image.source = "image://imageprovider"
            console.log("refresh.")
;
        
}
    }    
}
ImageProvider
class ColorImageProvider : public QQuickImageProvider
{
public:
    ColorImageProvider()
        : QQuickImageProvider(QQuickImageProvider::Pixmap)
    {
    }

    QPixmap requestPixmap(
const QString &id, QSize *size, const QSize &requestedSize) override
    {
        
int width = 100;
        
int height = 50;

        
if (size)
            
*size = QSize(width, height);
        QPixmap pixmap(requestedSize.width() 
> 0 ? requestedSize.width() : width,
            requestedSize.height() 
> 0 ? requestedSize.height() : height);
        pixmap.fill(QColor(id).rgba());
        
return pixmap;
    }
};

class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider::ImageProvider(ImageType type, Flags flags 
= Flags()) :
        QQuickImageProvider(type, flags)
    {
    }
    
    
~ImageProvider(){}

    QImage ImageProvider::requestImage(
const QString &id, QSize *size, const QSize &requestedSize)
    {
        
return image;
    }

    QImage image;
};

ImageContext
class ImageContext : public QObject
{
    Q_OBJECT
public:
    ImageContext(QObject
* parent = 0);
    ImageProvider
* m_imageProvider = nullptr;
public slots:
    
void setImage(const QImage& image);
signals:
    
void callQmlRefeshImg();
};
ImageContext::ImageContext(QObject* parent):
QObject(parent)
{
    m_imageProvider 
= new ImageProvider(QQuickImageProvider::Image);
}

void ImageContext::setImage(const QImage& image)
{
    m_imageProvider
->image = image;
    emit callQmlRefeshImg();
}

注冊和相應
    qml->engine()->addImageProvider(QLatin1String("colors"),new ColorImageProvider);
    ImageContext
* context = new ImageContext(this);
    qml
->engine()->rootContext()->setContextProperty("imagecontext",context);
    qml
->engine()->addImageProvider(QLatin1String("imageprovider"),context->m_imageProvider);

    qml
->setSource(QUrl("image.qml"));

    QDir dir(
"E:/MyVideoPlayer/Win32/Release/capture");

    QStringList files 
= dir.entryList(QDir::Files,QDir::SortFlag::Time | QDir::SortFlag::Reversed);
    qDebug() 
<< "files:" << files.size();
    
    connect(button, 
&QPushButton::clicked,[=]()
       {
           
static int current = 0;
           auto list 
= qml->rootObject()->childItems();
           
if(current == files.size())
               current 
= 0;

           QImage image;
           QString file 
= QString("E:/MyVideoPlayer/Win32/Release/capture/"+ files.at(current);
           qDebug() 
<< "loaded:" << image.load(file) << "," << file<<","<<current;
           context
->setImage(image);

           current
++;
       }
    );

posted @ 2019-08-05 11:37 ccsdu2009 閱讀(9) | 評論 (0)編輯 收藏

2019年6月18日

最近考慮開發一款兵棋軟件,名字都想好了,叫犀牛兵棋,打算支持四邊形地圖和六邊形地圖。

前者比較好說,后者在根據屏幕坐標計算格子坐標的時候,稍微有點麻煩。

先說下我們的坐標系是x軸向右,y軸向上,原點在左下角。

格子地圖坐標如下



根據格子坐標計算出對應世界坐標系的函數如下




QPointF GridCell6Manager::getWorldPosByCellCoordinate(
int x,int y)

{

if (x % 2 == 0)

return QPointF(1.5f*res*(x+1),

(
0.5*R3+R3*y)*res);

return QPointF(1.5f*res*(x + 1),

(R3 
+ y * R3)*res);

}



QPoint GridCell6Manager::getCellCoordinateByWorldPos(
int x,int y)

{

QPoint point(
-1,-1);

float xpos = x-res*0.5f;

float ypos = y/(R3*res) - 0.5f;

int yset[2= {std::floorf(ypos),std::ceilf(ypos)};

xpos 
/= (1.5*World::getInstance().getWorldResolution());

int xset[2= { std::floorf(xpos),std::ceilf(xpos)};

auto p00 
= getWorldPosByCellCoordinate(xset[0],yset[0]);

auto p01 
= getWorldPosByCellCoordinate(xset[0],yset[1]);

auto p10 
= getWorldPosByCellCoordinate(xset[1],yset[0]);

auto p11 
= getWorldPosByCellCoordinate(xset[1],yset[1]);

float d00 = distance2<float>(x,y,p00.x(),p00.y());

float d01 = distance2<float>(x,y,p01.x(),p01.y());

float d10 = distance2<float>(x,y,p10.x(),p10.y());

float d11 = distance2<float>(x,y,p11.x(),p11.y());

int i,j;

if(d00 < d01 && d00 < d10 && d00 < d11)

{

= xset[0];

= yset[0];

}

else if(d00 > d01 && d01 < d10 && d01 < d11)

{

= xset[0];

= yset[1];

}

else if(d10 < d00 && d10 < d01 && d10 < d11)

{

= xset[1];

= yset[0];

}

else

{

= xset[1];

= yset[1];

}

return QPoint(i,j);

}
其中res為格子邊長,R3為sqrt(3)常量

在這個基礎上就可以計算從世界坐標到格子坐標的轉換了



posted @ 2019-06-18 09:35 ccsdu2009 閱讀(82) | 評論 (0)編輯 收藏

2019年3月14日

#include <Windows.h>   
#include 
<wininet.h>   
#include 
<stdio.h>   
#include 
<string>   
#include 
<io.h>

using namespace std;

#pragma comment(lib, 
"wininet.lib")

const DWORD DWORD_MAX_CCH_OF_TEST_URL = 256;
const DWORD DWORD_MAX_CCH_OF_HOST_NAME = 128;
const DWORD DWORD_MAX_CCH_OF_URL_PATH = 256;

int breakpointDownload(const std::wstring& url, const std::wstring& folder, void(*cb)(double),std::wstring& name)
{
    
int index = url.find_last_of(L'/');
    std::wstring filename 
= url.substr(index + 1);
    index 
= filename.find_first_of(L'?');
    
if (index != std::wstring::npos)
        filename 
= filename.substr(0,index);

    
if (!folder.empty())
        filename 
= folder + L"\\" + filename;

    std::wstring tempfile 
= filename + L".dl";

    _wremove(filename.c_str());

    HINTERNET hInetOpen 
= NULL;
    HINTERNET hInetConnect 
= NULL;
    HINTERNET hInetRequest 
= NULL;
    HANDLE lhFile 
= NULL;
    
    URL_COMPONENTS ldCrackedURL;
    ZeroMemory(
&ldCrackedURL, sizeof(URL_COMPONENTS));
    ldCrackedURL.dwStructSize 
= sizeof(URL_COMPONENTS);                

    TCHAR szHostName[DWORD_MAX_CCH_OF_HOST_NAME] 
= { 0 };
    ldCrackedURL.lpszHostName 
= szHostName;
    ldCrackedURL.dwHostNameLength 
= DWORD_MAX_CCH_OF_HOST_NAME;         
    
    wchar_t szUrlPath[DWORD_MAX_CCH_OF_URL_PATH] 
= { 0 };
    ldCrackedURL.lpszUrlPath 
= szUrlPath;
    ldCrackedURL.dwUrlPathLength 
= DWORD_MAX_CCH_OF_URL_PATH;        

    
if (FALSE == InternetCrackUrl(url.c_str(),url.size(), 0&ldCrackedURL))
    {
        
return 0;
    }

    hInetOpen 
= InternetOpen(L"MSIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    
if (NULL == hInetOpen)
    {
        
return 0;
    }

    hInetConnect 
= InternetConnect(hInetOpen, ldCrackedURL.lpszHostName, ldCrackedURL.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 00);
    
if (NULL == hInetConnect)
    {
        
return 0;
    }
 
    lhFile 
= CreateFile(tempfile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    
if (lhFile == INVALID_HANDLE_VALUE)
    {
        
return 0;
    }

    LARGE_INTEGER ldFileSize;
    
if (FALSE == GetFileSizeEx(lhFile, &ldFileSize))
    {
        
return 0;
    }

    LONGLONG lllStartPos 
= 0;
    
if(0 == ldFileSize.QuadPart)
    {
    }
    
else
    {
        
if (INVALID_SET_FILE_POINTER == SetFilePointer(lhFile, 0, NULL, FILE_END))
        {
            
return 0;
        }

        lllStartPos 
= ldFileSize.QuadPart;
    }

    wchar_t lscRangeStartPosition[
30= { 0 };
    
if (0 != _i64tow_s((__int64)(lllStartPos), lscRangeStartPosition, sizeof(lscRangeStartPosition), 10))
    {
        
return 0;
    }

    wstring loAdditionalHeader 
= L"Range: bytes=";
    loAdditionalHeader 
+= lscRangeStartPosition;            
    loAdditionalHeader 
+= L"-\r\n";

    
const wchar_t* lplpszAcceptTypes[] = { L"*/*", NULL };
    hInetRequest 
= HttpOpenRequest(hInetConnect,L"GET", ldCrackedURL.lpszUrlPath,L"HTTP/1.1", NULL,lplpszAcceptTypes, 00);
    
if (NULL == hInetConnect)
    {
        
return 0;
    }

    
if (FALSE == HttpSendRequest(hInetRequest, loAdditionalHeader.c_str(), loAdditionalHeader.size(), NULL, 0))
    {
        
return 0;
    }

    DWORD ldwStatusCode;
    DWORD ldwCbOfStatusCode 
= sizeof(ldwStatusCode);
    
if (FALSE == HttpQueryInfo(hInetRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &ldwStatusCode, &ldwCbOfStatusCode, 0))
    {
        
return 0;
    }

    
if (416 == ldwStatusCode)        
    {
        _wrename(tempfile.c_str(), filename.c_str());
        name 
= filename;
        
return 1;
    }
    
else if (200 != ldwStatusCode && 206 != ldwStatusCode)  
    {
        
return 0;
    }

    DWORD dwFile 
= 10000;
    DWORD dwSize 
= sizeof(DWORD);
    
if (FALSE == HttpQueryInfo(hInetRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFile, &dwSize, 0))
    {
    }
    
else
        dwFile 
+= lllStartPos;

    BYTE lpbBufferToReceiveData[
2048];   
    DWORD ldwCbBuffer 
= 2048;
    DWORD ldwCrtCbReaded;            
    DWORD ldwCbWritten 
= 0;              
    
bool lbIsOk = false;

    LONGLONG lllCbAllRead 
= lllStartPos;
    
do
    {
        
if (FALSE == InternetReadFile(hInetRequest, lpbBufferToReceiveData, ldwCbBuffer, &ldwCrtCbReaded))
        {
            
break;
        }

        
if (ldwCrtCbReaded == 0)           
        {
            
break;
        }

        
if (FALSE == WriteFile(lhFile, lpbBufferToReceiveData, ldwCrtCbReaded, &ldwCbWritten, NULL) || ldwCbWritten != ldwCrtCbReaded)
        {
            
break;
        }

        ZeroMemory(lpbBufferToReceiveData, ldwCrtCbReaded);

        lllCbAllRead 
+= ldwCrtCbReaded;

        
double p = lllCbAllRead * 100.0 / dwFile;
        
if (p > 100)
            p 
= 100;
        
if (cb)
            cb(p);
    } 
while (true);

    
if (NULL != lhFile)
    {
        CloseHandle(lhFile);
    }

    
if (NULL != hInetRequest)
    {
        InternetCloseHandle(hInetRequest);
    }
    
if (NULL != hInetConnect)
    {
        InternetCloseHandle(hInetConnect);
    }
    
if (NULL != hInetOpen)
    {
        InternetCloseHandle(hInetOpen);
    }

    _wrename(tempfile.c_str(), filename.c_str());
    name 
= filename;
    
return 1;
}
posted @ 2019-03-14 16:31 ccsdu2009 閱讀(46) | 評論 (0)編輯 收藏
僅列出標題  皇室战争比赛视频2019