日韩精品一区二区三区在线视频放-无码中文字幕V?一区二区-成年片免费观看视频-国内少妇人妻丰满av-国产精品中文字幕免费观看-亚洲成人久久一区二区三区-国内少妇偷人精品视频无缓冲-一区二区国产精品日本一区二区三区在线网

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

QOpenGLWidget大圖查看器:紋理上傳、MVP矩陣與光標(biāo)縮放

QOpenGLWidget大圖查看器:紋理上傳、MVP矩陣與光標(biāo)縮放 簡(jiǎn)介這份Qt示例工程面向具備一定C基礎(chǔ)、正在學(xué)習(xí)Qt與OpenGL圖形顯示的開(kāi)發(fā)者聚焦QImage圖片在QOpenGLWidget中的紋理上傳與交互變換問(wèn)題。壓縮包為rar格式共10個(gè)文件、約347KB以3個(gè)cpp和2個(gè)h源碼為核心配合ui界面、qrc資源、pro工程配置及jpg示例圖組成可直接參考的完整工程結(jié)構(gòu)。已有783人學(xué)習(xí)說(shuō)明其在圖像顯示類練習(xí)中具有一定參考價(jià)值。工程內(nèi)容覆蓋initializeGL與paintGL的初始化與繪制流程、紋理過(guò)濾和邊角模式設(shè)置以及通過(guò)模型視圖矩陣實(shí)現(xiàn)縮放、旋轉(zhuǎn)和平移的思路同時(shí)結(jié)合鼠標(biāo)、鍵盤輸入更新變換參數(shù)并控制重繪以保持交互流暢。讀者可據(jù)此理解QImage轉(zhuǎn)紋理、視口適配和交互變換的組織方式作為圖像查看器或圖形界面二次開(kāi)發(fā)的起點(diǎn)。1. QOpenGLWidget 貼圖這件事從 QLabel 換到 GL 畫布的那一步拿 QLabel 顯示圖片一開(kāi)始都很順直到你放進(jìn)去一張 8000×6000 的掃描件。滾輪一放大QPixmap 要重新做一次 CPU 插值幾十毫秒就過(guò)去了按住鼠標(biāo)拖動(dòng)主線程直接被堵住畫面一卡一頓松手才啪地跳到最終位置。做圖像標(biāo)注、圖紙預(yù)覽、看圖工具這類要長(zhǎng)時(shí)間盯細(xì)節(jié)的軟件這個(gè)體驗(yàn)基本沒(méi)法交付。換成 QOpenGLWidget 的思路其實(shí)很樸素讓 QImage 只走一次內(nèi)存到顯存的拷貝變成一張紋理之后所有縮放、旋轉(zhuǎn)、平移都只是改一個(gè) 4×4 矩陣?yán)锏膸讉€(gè)數(shù)重繪交給 GPU大圖縮放穩(wěn)定在一幀一次 draw call。這份源碼素材-template 拆的就是這個(gè)最小閉環(huán)四類操作背后只有一條數(shù)據(jù)鏈路和一組矩陣把這條鏈走通再加任何功能都是往上疊。適合剛接觸 Qt 與 OpenGL 的同學(xué)照著跑通也適合手上正有一個(gè) QLabel 看圖控件準(zhǔn)備換掉的開(kāi)發(fā)者。2. 工程骨架與數(shù)據(jù)鏈路一張 QImage 走到屏幕要過(guò)哪幾道關(guān)2.1 四個(gè)環(huán)節(jié)解碼、上傳、變換、繪制整條鏈路拆開(kāi)只有四步邊界清楚到可以用一句話描述QImage 在 CPU 側(cè)被規(guī)范化成 RGBA8888 并垂直翻轉(zhuǎn)通過(guò) glTexImage2D 上傳成 2D 紋理繪制時(shí)用一個(gè)正交投影矩陣把像素坐標(biāo)系映射到 NDC再把平移、旋轉(zhuǎn)、縮放疊成一個(gè)模型矩陣最后畫一個(gè)和圖片等尺寸的四邊形采樣紋理輸出。四個(gè)環(huán)節(jié)各自有獨(dú)立的失敗點(diǎn)這是排查時(shí)最省時(shí)間的一張地圖環(huán)節(jié)關(guān)鍵函數(shù)典型失敗表現(xiàn)解碼QImage::load / convertToFormat通道錯(cuò)位、透明區(qū)變黑上傳glGenTextures / glTexImage2D黑屏、斜條紋、越界讀變換QMatrix4x4 組裝縮放跑偏、旋轉(zhuǎn)不繞中心繪制glDrawArrays shader有頂點(diǎn)無(wú)像素、上下顛倒很多人第一次寫會(huì)把這四步揉在 paintGL 里結(jié)果一改縮放就得重新傳紋理幀率立刻掉到個(gè)位數(shù)。正確的切法是上傳只在換圖時(shí)發(fā)生一次paintGL 里只做變換和采樣。2.2 類結(jié)構(gòu)與目錄組織工程不需要很復(fù)雜一個(gè)畫布類吃下所有 GL 相關(guān)代碼主窗口只管 UI 和文件對(duì)話框這樣二次開(kāi)發(fā)時(shí)改動(dòng)面可控。目錄大致長(zhǎng)這樣ImageViewerGL/ ├── CMakeLists.txt ├── main.cpp ├── widgets/ │ ├── ImageCanvasWidget.h # 畫布本體GL 代碼全在這里 │ ├── ImageCanvasWidget.cpp │ ├── ImageViewerWindow.h # 主窗口打開(kāi)、復(fù)位、關(guān)于 │ └── ImageViewerWindow.cpp ├── shaders/ │ ├── image.vert │ └── image.frag └── resources.qrc # 把 shader 打成資源省掉運(yùn)行時(shí)路徑問(wèn)題Qt6 里 QOpenGLWidget 已經(jīng)從 Widgets 拆到了獨(dú)立模塊CMake 配置少寫一行就是鏈接報(bào)錯(cuò)find_package(Qt6 REQUIRED COMPONENTS Widgets OpenGLWidgets) add_executable(ImageViewerGL main.cpp widgets/ImageCanvasWidget.cpp widgets/ImageViewerWindow.cpp ) # 注意 OpenGLWidgets 是獨(dú)立組件只鏈 Widgets 會(huì)在 QOpenGLWidget 構(gòu)造函數(shù)上炸 target_link_libraries(ImageViewerGL PRIVATE Qt6::Widgets Qt6::OpenGLWidgets) set_target_properties(ImageViewerGL PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE )提示Qt5 用QT opengl就夠了Qt6 必須顯式找 OpenGLWidgets兩套 CMake 寫法不通用從舊工程遷移時(shí)優(yōu)先查這一行。畫布類的公開(kāi)接口刻意收得很窄外層只認(rèn)識(shí)三個(gè)方法加載圖片、復(fù)位視圖、設(shè)置背景色。內(nèi)部狀態(tài)全部私有這樣后面加標(biāo)注層、加 ROI 框選時(shí)外部邏輯不需要知道矩陣怎么算。2.3 初始化順序initializeGL 里到底該放什么QOpenGLWidget 的三個(gè)虛函數(shù)有嚴(yán)格調(diào)用時(shí)機(jī)initializeGL只在上下文第一次成功建立后調(diào)一次resizeGL在尺寸變化時(shí)調(diào)paintGL每幀調(diào)。順序錯(cuò)了就是典型黑屏——在initializeGL之前調(diào)任何gl開(kāi)頭的函數(shù)要么空指針要么靜默失敗。class ImageCanvasWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: explicit ImageCanvasWidget(QWidget *parent nullptr); ~ImageCanvasWidget() override; bool loadImage(const QString filePath); // 唯一換圖入口 void resetView(); // 復(fù)位縮放 1.0、旋轉(zhuǎn) 0、居中 void rotateBy(float degrees); // 相對(duì)旋轉(zhuǎn)供工具欄和快捷鍵調(diào) protected: void initializeGL() override; void resizeGL(int w, int h) override; void paintGL() override; void wheelEvent(QWheelEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; private: void uploadTexture(const QImage img); // QImage - GL 紋理只在換圖時(shí)調(diào) void rebuildQuad(); // 按圖片尺寸重建頂點(diǎn)緩沖 QMatrix4x4 buildMvp() const; // 投影 * 模型逐幀組裝 GLuint m_texture 0; QOpenGLShaderProgram m_program; QOpenGLBuffer m_vbo{QOpenGLBuffer::VertexBuffer}; QOpenGLVertexArrayObject m_vao; QImage m_image; // 保留原圖導(dǎo)出/重傳都靠它 QSize m_texSize; // 原圖尺寸算初始縮放用 float m_scale 1.0f; // 縮放系數(shù)1.0 表示 1 像素對(duì) 1 像素 float m_rotation 0.0f; // 旋轉(zhuǎn)角度單位度逆時(shí)針為正 QVector2D m_translation{0.0f, 0.0f}; // 平移量單位屏幕像素 QPointF m_lastPos; // 上一幀鼠標(biāo)位置拖拽用 bool m_dragging false; };繼承QOpenGLFunctions是為了拿到跨平臺(tái)的 GL 函數(shù)指針集合——Qt 幫你做了QOpenGLContext::getProcAddress那一套你不必再引 GLEW 或 glad這在只有 Widgets 依賴的項(xiàng)目里很省事。代價(jià)是只能用 OpenGL ES 2.0 / 2.1 這個(gè)基線如果你要用 compute shader 或幾何著色器就得換成QOpenGLExtraFunctions或者自己加載。initializeGL里的順序不能亂void ImageCanvasWidget::initializeGL() { // 1. Qt6 必須顯式初始化函數(shù)解析表少了這行后面所有 gl* 都是空指針 initializeOpenGLFunctions(); // 2. shader 編譯鏈接失敗必須立刻暴露不要靜默跳過(guò) if (!m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, kVertexShader) || !m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, kFragmentShader) || !m_program.link()) { qWarning(shader 編譯失敗: %s, qPrintable(m_program.log())); return; } // 3. VAO/VBO 只創(chuàng)建不填充頂點(diǎn)數(shù)據(jù)要等圖片尺寸確定后才能寫 m_vao.create(); m_vbo.create(); // 4. 固定管線那套混色狀態(tài)深色背景配半透明圖片時(shí)需要 glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }第 4 步的GL_BLEND是給帶 alpha 通道的 PNG 準(zhǔn)備的如果你只顯示不透明圖片這一行可以省。第 2 步的qWarning打印m_program.log()很關(guān)鍵——shader 編譯錯(cuò)誤不會(huì)拋異常只會(huì)在日志里留一行不打印出來(lái)就是純黑屏加一頭霧水。3. 核心渲染鏈路拆解紋理上傳、著色器與 MVP 矩陣3.1 QImage 轉(zhuǎn)紋理格式、對(duì)齊、翻轉(zhuǎn)三件事這是整個(gè)項(xiàng)目里最容易翻車的一段因?yàn)槿齻€(gè)坑全藏在兩行代碼里。QImage 的像素格式五花八門Format_ARGB32、Format_RGB888、Format_Grayscale8……OpenGL 只認(rèn)它自己那一套枚舉中間必須做一次格式收斂。選Format_RGBA8888是因?yàn)樗膬?nèi)存排布是 R、G、B、A 順序和GL_RGBA的期望完全一致不需要再做通道重排。void ImageCanvasWidget::uploadTexture(const QImage img) { // 1. 格式收斂RGBA8888 的內(nèi)存序和 GL_RGBA 嚴(yán)格對(duì)應(yīng)省掉通道交換 QImage normalized img.convertToFormat(QImage::Format_RGBA8888); // 2. 垂直翻轉(zhuǎn)QImage 原點(diǎn)在左上GL 紋理原點(diǎn)在左下這里翻一次 // 著色器里的 uv 就可以老老實(shí)實(shí)寫 (0,0)-(1,1)邏輯只留在一個(gè)地方 normalized normalized.mirrored(false, true); if (m_texture 0) { glGenTextures(1, m_texture); } glBindTexture(GL_TEXTURE_2D, m_texture); // 3. 行對(duì)齊寬度不是 4 的倍數(shù)時(shí)默認(rèn) 4 字節(jié)對(duì)齊會(huì)讀串行畫面呈斜條紋 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, normalized.width(), normalized.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, normalized.constBits()); // 4. 縮小時(shí)用 mipmap 三線性放大時(shí)用線性只用 GL_LINEAR 縮小會(huì)明顯閃爍 glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 5. 邊緣 clamp避免紋理采樣越界時(shí)出現(xiàn)半透明黑邊 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); m_texSize normalized.size(); m_image img; // 存原圖導(dǎo)出時(shí)不要再?gòu)?GPU 讀回來(lái) }參數(shù)逐個(gè)說(shuō)清楚GL_RGBA8是內(nèi)部格式8 位每通道夠用且顯存占用可控如果做醫(yī)療影像要 16 位精度這里換成GL_RGBA16同時(shí) QImage 那邊轉(zhuǎn)Format_RGBA64。glPixelStorei(GL_UNPACK_ALIGNMENT, 1)是必須的。寬度 3 的倍數(shù)、又不是 4 的倍數(shù)的圖比如 RGB888 的 1023 像素寬默認(rèn) 4 字節(jié)對(duì)齊會(huì)讓驅(qū)動(dòng)多讀幾個(gè)字節(jié)畫面直接變成斜著的色帶。這個(gè)現(xiàn)象非常迷惑因?yàn)閳D不大就完全正常圖一大就錯(cuò)。mirrored(false, true)和第二參數(shù)true是垂直鏡像。如果你不想在 CPU 側(cè)翻也可以在頂點(diǎn)數(shù)據(jù)里把 v 坐標(biāo)寫成1.0 - v但兩邊千萬(wàn)別都做否則畫面上下顛倒回來(lái)又顛倒回去最后看起來(lái)正常一換圖就露餡。紋理尺寸還有硬限制GL_MAX_TEXTURE_SIZE在老舊集顯上可能只有 8192 或 4096。超過(guò)這個(gè)尺寸glTexImage2D直接報(bào)GL_INVALID_VALUE畫面全黑。工業(yè)相機(jī)、衛(wèi)星圖、切片掃描這類動(dòng)輒兩萬(wàn)像素的材料很正常比較穩(wěn)妥的做法是分塊tile上傳或者先等比縮到合法尺寸再傳原圖留給導(dǎo)出用。3.2 頂點(diǎn)數(shù)據(jù)與著色器一張四邊形的完整定義幾何部分簡(jiǎn)單到不需要索引緩沖四個(gè)頂點(diǎn)畫一個(gè) triangle strip 就完事。頂點(diǎn)坐標(biāo)直接用圖片像素坐標(biāo)0,0 到 w,h這樣正交投影矩陣寫起來(lái)最直觀鼠標(biāo)坐標(biāo)也能直接參與運(yùn)算不用來(lái)回做歸一化換算。void ImageCanvasWidget::rebuildQuad() { const float w static_castfloat(m_texSize.width()); const float h static_castfloat(m_texSize.height()); // 布局x, y, u, v 交叉排列一次 allocate 搞定位置和紋理坐標(biāo) const GLfloat verts[] { 0.0f, 0.0f, 0.0f, 0.0f, // 左上 w, 0.0f, 1.0f, 0.0f, // 右上 0.0f, h, 0.0f, 1.0f, // 左下 w, h, 1.0f, 1.0f, // 右下 }; m_vao.bind(); m_vbo.bind(); m_vbo.allocate(verts, sizeof(verts)); m_program.bind(); // 參數(shù)含義location0類型 float起始偏移 0每頂點(diǎn) 2 分量跨距 4 個(gè) float m_program.enableAttributeArray(0); m_program.setAttributeBuffer(0, GL_FLOAT, 0, 2, 4 * sizeof(GLfloat)); // location1從第 3 個(gè) float 開(kāi)始2 分量跨距同上 m_program.enableAttributeArray(1); m_program.setAttributeBuffer(1, GL_FLOAT, 2 * sizeof(GLfloat), 2, 4 * sizeof(GLfloat)); m_program.release(); m_vbo.release(); m_vao.release(); }setAttributeBuffer的最后一個(gè)參數(shù)是 stride這里寫4 * sizeof(GLfloat)表示每隔 16 字節(jié)取下一個(gè)頂點(diǎn)。如果寫成 0讓驅(qū)動(dòng)自己推某些老驅(qū)動(dòng)會(huì)算錯(cuò)顯式寫死更保險(xiǎn)。location0 / 1是靠 shader 里的layout(location ...)硬綁定的兩邊必須對(duì)得上對(duì)不上就是純黑。兩個(gè) shader 保持最小// image.vert #version 330 core layout(location 0) in vec2 aPos; layout(location 1) in vec2 aTexCoord; uniform mat4 uMvp; out vec2 vTexCoord; void main() { vTexCoord aTexCoord; // 注意這里乘的是完整 MVP任何變換都在 CPU 側(cè)算好shader 不做二次加工 gl_Position uMvp * vec4(aPos, 0.0, 1.0); }// image.frag #version 330 core in vec2 vTexCoord; uniform sampler2D uTexture; out vec4 fragColor; void main() { fragColor texture(uTexture, vTexCoord); }片元著色器里不寫任何 if 和分支——GPU 最怕這個(gè)。如果你想加灰度化反色亮度對(duì)比度直接在texture()之后做一個(gè)mix或加減代價(jià)幾乎為零但如果寫if (vTexCoord.x 0.5)性能曲線會(huì)立刻變得難看。3.3 buildMvp平移、旋轉(zhuǎn)、縮放的合成順序矩陣這塊是玄學(xué)重災(zāi)區(qū)。QMatrix4x4 的乘法和數(shù)學(xué)課本一致但代碼里鏈?zhǔn)秸{(diào)用的順序和直覺(jué)是反的m.translate(); m.rotate(); m.scale();實(shí)際效果是先縮放、再旋轉(zhuǎn)、最后平移因?yàn)槊看握{(diào)用都在右乘新矩陣。設(shè)計(jì)意圖很明確圖片自己的坐標(biāo)系里先繞圖片中心縮放再繞圖片中心旋轉(zhuǎn)然后整體移動(dòng)到畫布中心并疊加用戶的平移量。所以順序必須是 translate → rotate → scale → 反向平移回原點(diǎn)。QMatrix4x4 ImageCanvasWidget::buildMvp() const { QMatrix4x4 proj; // y 軸向下bottom h, top 0和屏幕坐標(biāo)系一致 // 鼠標(biāo)坐標(biāo)可以直接當(dāng)世界坐標(biāo)用不需要再做 y 翻轉(zhuǎn) proj.ortho(0.0f, static_castfloat(width()), static_castfloat(height()), 0.0f, -1.0f, 1.0f); QMatrix4x4 mv; // 1. 把畫布中心 用戶平移量當(dāng)作圖片中心的落點(diǎn) mv.translate(width() * 0.5f m_translation.x(), height() * 0.5f m_translation.y()); // 2. 繞 Z 軸旋轉(zhuǎn)正數(shù)為逆時(shí)針 mv.rotate(m_rotation, 0.0f, 0.0f, 1.0f); // 3. 等比縮放 mv.scale(m_scale, m_scale); // 4. 把圖片自身中心挪到原點(diǎn) —— 少了這行縮放和旋轉(zhuǎn)會(huì)繞畫布左上角 // 表現(xiàn)就是放大時(shí)圖片往右下角飛出屏幕 mv.translate(-m_texSize.width() * 0.5f, -m_texSize.height() * 0.5f); return proj * mv; }第 4 行的反向平移是整個(gè)矩陣的靈魂。它的物理含義是把圖片坐標(biāo)系的中心挪到原點(diǎn)這樣第 2、3 步的旋轉(zhuǎn)和縮放天然繞中心發(fā)生。很多人圖省事把 scale 寫在 translate 前面代碼看起來(lái)只差一行運(yùn)行起來(lái)圖片就是繞著左上角放大越放越偏還以為是自己縮放算法寫錯(cuò)了。proj * mv的乘法順序也不能改投影矩陣在最左模型矩陣在右。寫成mv * proj的后果是畫面上什么都沒(méi)有且沒(méi)有任何報(bào)錯(cuò)。3.4 paintGL一幀的完整執(zhí)行順序void ImageCanvasWidget::paintGL() { glClearColor(0.13f, 0.14f, 0.16f, 1.0f); // 深灰底淺色圖邊緣更清楚 glClear(GL_COLOR_BUFFER_BIT); if (m_texture 0 || m_texSize.isEmpty()) { return; // 還沒(méi)加載圖片只清屏 } m_program.bind(); m_program.setUniformValue(uMvp, buildMvp()); m_program.setUniformValue(uTexture, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_texture); m_vao.bind(); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); m_vao.release(); m_program.release(); }逐行解釋關(guān)鍵點(diǎn)setUniformValue(uTexture, 0)里的 0 是紋理單元編號(hào)必須和glActiveTexture(GL_TEXTURE0)對(duì)上對(duì)不上就是采樣到一張空紋理畫面純黑。GL_TRIANGLE_STRIP用 4 個(gè)頂點(diǎn)畫兩個(gè)三角形比GL_TRIANGLES少傳兩個(gè)頂點(diǎn)雖然在這里省不了多少但習(xí)慣值得保留。整個(gè)paintGL里沒(méi)有任何glTexImage2D這是幀率能穩(wěn)住的前提。換圖時(shí)才調(diào)uploadTexturerebuildQuad然后update()一次。4. 交互層實(shí)現(xiàn)滾輪縮放、拖拽平移與旋轉(zhuǎn)的坐標(biāo)換算4.1 鼠標(biāo)事件分發(fā)與狀態(tài)管理三個(gè)鼠標(biāo)事件各管一攤互不打擾左鍵按下開(kāi)始拖拽左鍵移動(dòng)累加平移量滾輪改縮放系數(shù)右鍵拖拽改旋轉(zhuǎn)角。狀態(tài)用一個(gè)m_dragging布爾量 一個(gè)m_lastPos就能覆蓋不需要維護(hù)狀態(tài)機(jī)。void ImageCanvasWidget::mousePressEvent(QMouseEvent *e) { if (e-button() Qt::LeftButton) { m_dragging true; m_lastPos e-position(); // Qt6 用 position()Qt5 是 pos() setCursor(Qt::ClosedHandCursor); } QOpenGLWidget::mousePressEvent(e); } void ImageCanvasWidget::mouseMoveEvent(QMouseEvent *e) { if (!m_dragging || !(e-buttons() Qt::LeftButton)) { return; } const QPointF delta e-position() - m_lastPos; m_lastPos e-position(); // 平移量直接在屏幕像素空間累加和 ortho 的像素單位完全一致 // 中間不需要任何比例換算這也是選像素坐標(biāo)系的最大好處 m_translation QVector2D(static_castfloat(delta.x()), static_castfloat(delta.y())); update(); // 單幀請(qǐng)求重繪不要用 while 或 timer 去刷 } void ImageCanvasWidget::mouseReleaseEvent(QMouseEvent *e) { if (e-button() Qt::LeftButton) { m_dragging false; unsetCursor(); } QOpenGLWidget::mouseReleaseEvent(e); }e-position()返回的是邏輯像素DPI 無(wú)關(guān)而m_translation也是邏輯像素兩邊單位一致。如果你不小心一邊用了devicePixelRatio乘過(guò)的物理像素拖拽速度就會(huì)變成 2 倍或 0.5 倍高 DPI 屏上線普通屏上一切正?!@種問(wèn)題最難查因?yàn)殚_(kāi)發(fā)機(jī)往往是普通屏。4.2 以光標(biāo)為錨點(diǎn)的縮放最樸素的實(shí)現(xiàn)是滾輪一下m_scale * 1.15圍繞畫布中心放大。用起來(lái)會(huì)讓用戶很煩想看清楚畫面右上角的細(xì)節(jié)滾幾圈之后那塊內(nèi)容已經(jīng)跑到屏幕外面去了得不停拖回來(lái)。好用的看圖工具都做光標(biāo)錨定——放大時(shí)鼠標(biāo)指針下面那個(gè)像素點(diǎn)保持不動(dòng)。推導(dǎo)不復(fù)雜把屏幕坐標(biāo)到世界坐標(biāo)的映射寫成一行screen R · S · (world ? c) center t其中 R 是旋轉(zhuǎn)S 是縮放c 是圖片中心t 是平移量。要求縮放從 S 變到 S 之后同一個(gè) screen 對(duì)應(yīng)的 world 不變解出新的平移量t pivot · (1 ? k) t · k, 其中 k S/Spivot 鼠標(biāo)位置 ? 畫布中心落到代碼里只有六行void ImageCanvasWidget::wheelEvent(QWheelEvent *e) { const float steps e-angleDelta().y() / 120.0f; // 一格滾輪 120 if (qFuzzyIsNull(steps)) { return; } const float oldScale m_scale; // 1.15^steps往上滾放大往下滾縮小指數(shù)形式保證放大縮小完全對(duì)稱 m_scale std::clamp(oldScale * std::pow(1.15f, steps), 0.02f, 64.0f); // 錨定公式k 是新舊縮放比pivot 是鼠標(biāo)相對(duì)畫布中心的偏移 const float k m_scale / oldScale; const QPointF pos e-position(); const QVector2D pivot(static_castfloat(pos.x() - width() * 0.5), static_castfloat(pos.y() - height() * 0.5)); m_translation pivot * (1.0f - k) m_translation * k; update(); e-accept(); }幾個(gè)參數(shù)值得說(shuō)明std::pow(1.15f, steps)里的 1.15 是手感系數(shù)試過(guò) 1.1、1.2、1.31.15 在大圖上大概是滾三格看清楚一小塊的節(jié)奏再大就容易失控。std::clamp的上下限 0.02 和 64 是防呆——低于 0.02 時(shí)一張 10000 像素的圖只剩 200 像素寬用戶會(huì)以為圖沒(méi)了高于 64 時(shí)浮點(diǎn)精度開(kāi)始不夠用邊緣會(huì)出現(xiàn)抖動(dòng)。這兩個(gè)邊界值不是隨便定的是長(zhǎng)時(shí)間試出來(lái)的。還有一點(diǎn)容易忽略公式里的pivot用的是畫布中心而不是圖片中心。這里有個(gè)前提buildMvp里平移量的基準(zhǔn)點(diǎn)也是畫布中心兩邊必須統(tǒng)一。要是某天你把基準(zhǔn)改成圖片中心這個(gè)公式就得跟著重寫。4.3 拖拽旋轉(zhuǎn)與視圖復(fù)位旋轉(zhuǎn)不用太花哨右鍵橫向拖動(dòng)改角度加上一個(gè)鍵盤 R 鍵做 90° 步進(jìn)覆蓋絕大多數(shù)用法。void ImageCanvasWidget::setRotationFromDrag(qreal dx) { // 每拖 2 像素轉(zhuǎn) 1 度符號(hào)取反是因?yàn)槠聊?y 向下、逆時(shí)針為正 m_rotation std::fmod(m_rotation - static_castfloat(dx) * 0.5f, 360.0f); if (m_rotation 0.0f) { m_rotation 360.0f; // 歸一化到 [0, 360)避免數(shù)值越滾越大 } update(); } void ImageCanvasWidget::rotateBy(float degrees) { m_rotation std::fmod(m_rotation degrees, 360.0f); update(); } void ImageCanvasWidget::resetView() { m_scale 1.0f; m_rotation 0.0f; m_translation QVector2D(0.0f, 0.0f); update(); }std::fmod那一步是后悔藥。如果不做歸一化用戶按住右鍵轉(zhuǎn)十圈m_rotation就變成 3600浮點(diǎn)精度一點(diǎn)點(diǎn)累積轉(zhuǎn)回 0 度時(shí)畫面會(huì)有微小傾斜。歸一化之后最多只有 359 的誤差肉眼看不出來(lái)。復(fù)位按鈕也別只復(fù)位縮放——把旋轉(zhuǎn)和平移一起歸零否則用戶點(diǎn)了復(fù)位發(fā)現(xiàn)圖還是歪的體驗(yàn)很怪。5. 避坑與排查黑屏、倒像、斜條紋、泄漏這四類問(wèn)題5.1 環(huán)境與初始化類一進(jìn)來(lái)就是純黑現(xiàn)象程序能起來(lái)窗口也有但畫布區(qū)域一片黑什么都看不到日志里也沒(méi)有異常。原因絕大多數(shù)是initializeOpenGLFunctions()沒(méi)調(diào)或者 shaderlink()失敗后被靜默跳過(guò)。Qt6 里QOpenGLFunctions的函數(shù)指針要靠這個(gè)調(diào)用填充不調(diào)的話第一次glGenTextures就是空指針在部分平臺(tái)上直接崩在另一些平臺(tái)上靜默返回 0。另一個(gè)高頻原因是鏈接時(shí)只帶了Qt6::Widgets沒(méi)帶Qt6::OpenGLWidgets編譯期不報(bào)錯(cuò)運(yùn)行時(shí)構(gòu)造 QOpenGLWidget 才炸。解決把a(bǔ)ddShaderFromSourceCode和link()的返回值全部檢查失敗時(shí)用qWarning打印m_program.log()initializeGL第一行固定寫initializeOpenGLFunctions()。如果還是沒(méi)有輸出檢查QSurfaceFormat有沒(méi)有在QApplication構(gòu)造之前設(shè)置——setDefaultFormat必須在main里QApplication a(argc, argv);之前調(diào)之后調(diào)無(wú)效這是個(gè)經(jīng)典的時(shí)間窗口問(wèn)題。5.2 畫面表現(xiàn)類圖片上下顛倒或出現(xiàn)斜條紋現(xiàn)象 A圖能顯示但是上下倒著的文字也反了。原因 AQImage 原點(diǎn)在左上、GL 紋理原點(diǎn)在左下兩邊坐標(biāo)系不一致。如果只在uploadTexture里做了mirrored(false, true)卻又在頂點(diǎn)數(shù)據(jù)里把 v 坐標(biāo)寫成1.0 - v等于翻了兩次看起來(lái)又正了一旦換一種加載路徑比如從內(nèi)存 buffer 而不是文件只走其中一處翻轉(zhuǎn)立刻就顛倒。解決 A翻轉(zhuǎn)只做一次且固定在一個(gè)地方。這個(gè)項(xiàng)目的做法是統(tǒng)一在uploadTexture里翻頂點(diǎn) uv 永遠(yuǎn)寫(0,0)-(1,1)誰(shuí)改了翻轉(zhuǎn)邏輯必須同步檢查另一處?,F(xiàn)象 B圖片邊緣出現(xiàn)斜著的彩色條紋或者右下角有一片噪點(diǎn)。原因 BglPixelStorei(GL_UNPACK_ALIGNMENT, 1)沒(méi)寫驅(qū)動(dòng)按 4 字節(jié)對(duì)齊讀行寬度不是 4 的倍數(shù)的圖必然讀串行。解決 B上傳紋理前固定加一行g(shù)lPixelStorei(GL_UNPACK_ALIGNMENT, 1)。這個(gè)設(shè)置是全局狀態(tài)會(huì)一直保留但建議每次上傳前都設(shè)避免被別處改掉后踩坑。5.3 交互與數(shù)值類放大后圖片往角落跑現(xiàn)象滾輪放大幾次之后圖片不是圍繞光標(biāo)放大而是快速往右下角飛出去最后完全看不見(jiàn)或者拖拽時(shí)手感明顯黏跟手的距離對(duì)不上。原因buildMvp里少寫了最后那句反向平移mv.translate(-w/2, -h/2)縮放和旋轉(zhuǎn)就繞畫布左上角發(fā)生。拖拽黏的原因通常是單位不統(tǒng)一——e-position()返回邏輯像素而平移量如果按物理像素累加高 DPI 屏上速度就變成 2 倍。解決矩陣鏈的尾部必須補(bǔ)上把圖片中心移到原點(diǎn)這一步坐標(biāo)換算全程只用邏輯像素如果確實(shí)需要物理像素統(tǒng)一在resizeGL里乘一次devicePixelRatioF()別散落在各個(gè)事件處理里。檢查方法很簡(jiǎn)單把m_texSize打出來(lái)再打印一次鼠標(biāo)位置經(jīng)過(guò)buildMvp().inverted()映射后的世界坐標(biāo)看看是不是落在[0, w] × [0, h]里。5.4 性能與資源類連續(xù)換圖幾十次后卡死現(xiàn)象反復(fù)打開(kāi)不同的圖片內(nèi)存占用一路漲最后系統(tǒng)卡頓甚至進(jìn)程被殺或者大圖切換時(shí)有一秒多的白屏。原因glGenTextures每次換圖都新建紋理舊的沒(méi)glDeleteTextures顯存泄漏。另一種是每次paintGL都調(diào)glTexImage2D重新上傳一張 8000×6000 的 RGBA 圖每幀要拷 180MB 到顯存幀率自然崩。解決uploadTexture里先判m_texture ! 0就復(fù)用現(xiàn)有紋理 ID只在尺寸變化時(shí)重建paintGL里絕不重新上傳。如果是同一尺寸的圖頻繁刷新比如視頻幀用glTexSubImage2D替換整張glTexImage2D后者要重新分配顯存前者只覆蓋數(shù)據(jù)快一個(gè)數(shù)量級(jí)。析構(gòu)函數(shù)里記得makeCurrent()之后再glDeleteTextures直接刪會(huì)因?yàn)闆](méi)有當(dāng)前上下文而失敗。注意QOpenGLWidget在銷毀時(shí)上下文可能已經(jīng)失效~ImageCanvasWidget里刪紋理必須自己makeCurrent()Qt 不會(huì)幫你。6. 二次開(kāi)發(fā)從單圖查看器擴(kuò)到多圖層標(biāo)注器的改造思路這個(gè)畫布跑通之后最有價(jià)值的延伸是把它往多圖層方向改。單圖查看器的瓶頸在m_texture只有一個(gè)一旦要做底圖 標(biāo)注層 ROI 框選就得把紋理和矩陣抽成獨(dú)立的圖層結(jié)構(gòu)struct Layer { GLuint texture 0; QSize size; QMatrix4x4 localTransform; // 圖層自身的偏移/縮放相對(duì)畫布為恒等 float opacity 1.0f; bool visible true; }; QVectorLayer m_layers;改造的關(guān)鍵是把buildMvp拆成兩級(jí)投影矩陣proj全局一份每個(gè)圖層自己的模型矩陣單獨(dú)算繪制時(shí)proj * layer.localTransform逐個(gè)上傳。這樣拖拽平移只改全局的視圖矩陣單獨(dú)挪某個(gè)標(biāo)注框只改對(duì)應(yīng)圖層的localTransform互不干擾也不用重新上傳紋理。第二個(gè)常見(jiàn)需求是導(dǎo)出當(dāng)前視圖。不要用QPixmap::grabWidget那截的是窗口會(huì)被遮擋、被 DPI 縮放。正確做法是grabFramebuffer()它直接讀 FBO拿到的是純繪制內(nèi)容bool ImageCanvasWidget::exportView(const QString path) { makeCurrent(); // 讀 FBO 前必須綁定上下文 const QImage frame grabFramebuffer(); doneCurrent(); return frame.save(path); // 格式由后綴決定 }第三個(gè)方向是精度。如果做的是工業(yè)檢測(cè)、遙感、病理切片圖片動(dòng)輒兩萬(wàn)像素以上GL_MAX_TEXTURE_SIZE直接卡死。這時(shí)要么按 2048 或 4096 切塊每塊一張紋理按可視區(qū)域只畫可見(jiàn)的塊視錐裁剪要么把原始QImage拆成金字塔縮放級(jí)別切換時(shí)換用不同分辨率的紋理顯存占用能壓下來(lái)一大截。這兩條路的共同點(diǎn)是始終保留 CPU 側(cè)的原始 QImageGPU 上的紋理只是顯示用的副本任何需要精確像素的操作取色、測(cè)量、導(dǎo)出都回到原圖算不要從紋理讀回來(lái)。關(guān)于驗(yàn)證我的習(xí)慣是準(zhǔn)備一組刁鉆圖當(dāng)回歸樣本一張 1×1、一張 1023×769寬度不是 4 的倍數(shù)、一張帶 alpha 的 PNG、一張 20000×20000 的大圖、一張灰度圖。每次改完矩陣或者紋理上傳邏輯就把這五張挨個(gè)過(guò)一遍縮放拖到 0.05 和 30 兩個(gè)極端右鍵轉(zhuǎn)兩圈看有沒(méi)有抖動(dòng)、有沒(méi)有黑邊、邊緣有沒(méi)有斜紋。這套流程是被坑出來(lái)的血淚經(jīng)驗(yàn)——只測(cè)一張 4K 的彩色 JPG永遠(yuǎn)發(fā)現(xiàn)不了對(duì)齊和格式的問(wèn)題。從那以后我每次動(dòng)渲染相關(guān)的代碼都會(huì)在提交前把這組圖跑一遍寧可多花十分鐘也不想再收到大圖打開(kāi)是斜的這種沒(méi)有截圖、沒(méi)有復(fù)現(xiàn)步驟的反饋。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
久久久久久久9最新免费视频观看| 人妻精品一区二区在线| 日韩激情小说一区二区| 91色五月俺来也| 亚洲第一视频 欧美风情 日韩| WWW操逼| 亚洲中文字幕噜噜噜久久久| 美女t无毒不卡不卡| 久久久久成人亚洲国产| 国产中午字一暮区| 国产女人和拘做爰视频| 久9久9精品| 亚洲丨在线| 日韩无码精品综合久久| 中日无幕一二三四区| 男人综合网| 日本岛国黄色网址| 2020天天色综合| 日韩精品一区二区日韩| 国产精品。| 国产91 丝袜在线播放00-百度| 国产三区免费在线观看| 伊人久久亚洲色欲综合网站 | a男人的天堂久久一级A毛片| 99免费视频| 久久东京热成人| 93人人操人人| 五月天欧美色图| 天天干天天燥| 久色99999| 成人av福利在线观看| 精品视频日日夜夜| 免费A片三p视频| 天堂种子在线www网资源| 中文字幕久久亚州无码| 高跟丝袜AV专区国产| 97视频新免费| 亚洲乱码尤物193YW| 国产人妻精品一区二区三区秋霞 | 91超碰人人操| 91狠狠综合久久| 激情五月婷婷| 九九九久久久| 天天色怡春院| 亚洲av无码成人精品国产| AV中文字幕三四五| 夜夜精品视频| 少妇天堂网络| 国产aⅴ无码片毛片一级网站| 久极品在线观看| 综合av社区| 97天天综合网| 九九性爱网| 中国和日本人色哪个不下载能放| 婷婷色香| 乱伦图一区| 人妻激情在线视频| 天天爽夜夜操| a片 xxxx受爽视频| 亚洲精品一区二区免费在线观看| 国产97色在线| 乱伦熟妇一区二区| 色偷偷超碰亚洲| 中文字幕五区| 亚洲男人久久综合天堂| 久久区| 免费看污网址| 五月天婷婷小说| 日韩操p| 天堂麻豆天美| 天堂蜜桃无码视频一区二区| 围产精品一区二区三区视频播放| 777超碰| 欧美影音在线| 极品丝袜无码| 国产乱码精品一区二区三区四川| 欧美性爱第一页久久| 亚洲 欧美 小说| 精品久久人妻成人网| 97久久国产| 久久久久密臀一区二区| 国产黄色av大片网站| 少妇一区二区三区| 丝袜美腿91| 春色校园综合网| 首页中文字幕中文字幕免费| 日韩免费中文字幕视频| 桑老女人九区| 2017大香蕉国产精品久久| 在线啊v一区| 成人性爱免费播放| 97超碰香蕉| 加勒比海成人视频网| 色九九九九久| 久久一区二区三区入口| 国产黄色影片在线观看| 国产成人亚洲精品无| 99国内熟女露脸视频| 久操操| 国产熟女完整版中字 | 97色在线| 欧美中文字幕日韩在线| 91N综合网| 97热视频在线观看| 天美精品一区二区三区四区在线观看 | 热99re69精品8在线播放| 亚欧美综合网。| 国产suv精品一区二区四区999| 99久久精品国产高潮| 琪琪精品免费一区二区三区 | www.91理论| 人妻三级在线中文字幕| 色妇综合网| 中文字幕1区2区| 91美女视频。| 日本不卡一二区| 热热色色综合| AV在线播放网址| 亚洲天堂美臀在线| 日韩大香蕉精品在线视频| 国产精品久久久777| 免费看污网站| 亚洲蜜臀懂色| 欧美第一页| 夜夜综合| www久久精品| 激情久久日韩精品中文字幕麻豆| 96国产污污污丝袜| 亚洲人妻久久久| 欧美日韩人妻精品一区二区三区| 免费看日产一区二区三区| 日韩色图 一区二区| 男人的天堂激情| 五月天激情小说| 五月天婷婷久久| 亚洲一区二区三区欧美日韩| 国内精品伊人久久久久影院会| 成人精品一区二区91毛片不卡| 天久久久噜噜噜久久国产精品爽爽| 2020中文字幕在线| 亚洲 欧美 日本 国内 首页| 精品欧美日韩在线观看| 久久久国产护士丝袜美腿一| 午夜操一视频一区| 亚洲国产天堂| 欧美天天干| 天天欧美| 91国产操逼视频| 男人天堂东京热| 日韩人妻无码不卡网站| 热99这里有精品综合久久| 欧美性第1页| 天天综合,91入口| 亚洲色图日韩丝袜制服一区二区五月在线| 精品国产乱码久久久久久免费| 人妻少妇精品无码专区二区密桃 | 亚洲黄网在哪免费看| 天天干夜夜操网| 亚欧性爱在线无码| 殴美色网| 青青草无码视频| 啊啊啊水好多| 91人妻少妇| 91久久免费视频互動交流| 97色97干| 999亚洲国产视频| 欧亚性爱啪啪| 黄污污污污| 91蜜臀在线久久久久| 大香蕉在线86| 97就爱干| 男人的天堂三级| 亚州中文字幕超碰97| 精品国产片亚洲一区| www.狠狠干.coom | 国产精品视频在线观看| 无码动漫av中文字幕| 国产精品一区二区三区,亚洲综合 性开放中文AV高清无码免费看 | 制服中出中文人人精品| 久久久久久久久久久久97| av毛片aaaaa免费看| 久久黄色视频一区二区三区| 丁香六月激情综合| 热久久九九热| 后入人妻无码| 日本羞羞的视频在线播放| 国产高清无码一区三区二区| 亚洲色久| 九九精品美女高溯喷水| 欧美高潮| av爱爱爱| 97资源制服丝袜| 国产25页| 91亚洲情色| 不卡av在线中文字幕| 人人操AV| 精国久久一区二区三区98| 亚洲 在线| 丁香六月东京热| 九九玖玖精品| av天堂加勒比| 51一区二区三区| 97久精品| 久久久久女教师免费一区 | 国产丝袜一区二区三区| 国产精品黑人一区二区三区| 凹凸视频特色日本特黄| 10000部十八禁看电影| 亚洲天天自拍| 日本欧美国内在线| 亚洲色图欧美另类在线| 熟人人妻少妇精品久久| 超碰成人国产| 天天操人人操骚逼网站| 精品中文字幕第一页| 吻戏激情性巴克| 久偷拍| 欧美色综合网| 日本国产成人亚洲精品无码| 另类欧美| 久久久久久久亚洲Av无码| 欧美无圣光在线| 日韩AV噜噜噜一区二区三区四区| 久久91视频| 丰满少妇人妻久久久久久| 日本道日本道中文字幕日本道最新日本道在线观看 | 黄页视频网站野外| 久久理论字幕视频| 亚洲欧美另类小说| 五月婷婷基地| 97在线亚洲| 亚洲制服aⅴ中文字幕| 思思99热| 亚洲啪啪综合?v一区综合精品区| 99亚洲精品| 99超碰网| 91九色首页| 中出20p| 日韩丝袜二区| 97在线欧| 日韩欧美字幕亚洲一区二区| 色偷综合| 玖玖玖玖精品国产剧情| 91日产欧美| 日本黄色大片一级视频免费麻豆| 97精品第3页| 久久久久久9| 69超碰综合| 97欧美综合| 成人短视频在线观看| 国产精品亚洲四五区在线观看| 极品出轨视频网站| 成功精品影院| 东京热一区二区中文字幕| 91精品电影18| 黄色香蕉视频网站一区| 亚洲永久AV无码精品秋霞| 91av一区二区在线观看| 91 综合 色| 男女做爰猛烈动高潮A片免费应用| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 欧美72网页| 欧美日韩亚洲一区二区在线观看| 加勒比色综合| 伊人久久青青草| 色香AV| 91 丝袜在线| 乳欲人妻办公室奶水| 国产精品久久久久久夜夜夜夜| 国产人妖视频一区在线观看| 亚欧操逼片在线观看 | 久久机热| 手机av天堂久久久久| 欧洲在线性爱视频| 大香蕉 222| 欧美不卡在线一区二区| 人澡逼| 九九热最新| 色汉综合| 天美传媒在线一区| 午夜一区| 香蕉欧美| 二级毛片| 亚洲AV无码天美传媒一区| 国产精品又黄又猛又粗| 97视频在线免费播放| 亚洲成人久久美女| 精品国模无码| 国产区在线| 美腿色图| 天天日B夜夜干B时时操B| 好涩综合| 天天色怡春院| 精品一区二区啪啪啪| 免费国产视频| 超碰视97中文| 熟妇一区二区三区| 激情网五月天| 亚欧成人中文字幕一区| 超碰97中文| 最新9久久久9免费视频| av九九| 国产精品探花色| yy少妇精品久久| av中文在线| 亚瑟国产精品久久无码| 亚州一区二区| 亚洲欧美变态| 躁躁日曰躁2020| 天天日天天干天天整| 国产一线二线三线av| 欧美成人色| 色婷婷六月| www.亚洲黄色| 美女性91| 在线五区| 美国三级日本三级久久99| 亚洲日韩av一区二区三区百合| 久久久成人国产精品无码| 亚洲影院365| 国产91 丝袜在线播放| 日韩欧美中文字| 人人爱夜夜爱| 亚洲欧美精品一区天堂久久 | 欧美成人一区二区三区在线播放| 精品成人动漫一区二区| 天天日天天操天天射河南省| 欧日韩一二三f区| 久久久禁| 一区二区 电影 亚洲| 亚洲av夫妻操穴网| 国产成人精品亚洲日本| 久久av成人无码免费| 91第一页| 精品国产乱码久久久影院| 99只有精品| 四虎永久在线精品免费网址 | 日日骚av| 成人一级二级| 婷婷伊人一区| 97干在线看| 久操大香蕉手机视频在线看| 久99视频| 黄污污污污| 自拍偷拍 日韩无码| 91东京热男人的天堂| 国产精品一区二区三区四区五区| 久久日韩肥臀| 久久爱97| 久久久久久综合久久伊人蜜月| 黄色交缠性感爆操91国产精品免费一区二区三区 | 美女爽爽爽刺痛洞洞| 亚洲色图 欧美热图 清纯唯美 另类自拍| 五月天婷婷激情| 99热超碰在线| 婷婷久草一区二区三区| 另类综合另类| 操人妻丝袜高跟| 91久久久久久久久久久| 亚洲色图欧美色图制服丝袜| 久久av网| 欧美色图人妻| 女生看匆91网站| 男人的天堂com| 久草色在线观看| 国产精品对白自产拍| 色五月激情AV在线| 精品无码一区二区| 唐山老熟妇露脸啪啪叫| 干超碰碰熟女| 久久亚洲中文字幕视频| A一区片| 免费自拍三级综合| 日韩黄色一区二区三区| 深田咏美亚洲精品福利社| 国产a级午夜毛片| 91在线无码精品秘 软件| 久久精品色欧美aⅴ一区二区| 亚洲夜夜欢无码一区二区| 激情综合五月| xxx亚洲午夜天堂| 五月天综合网| 人妻色情天天操| 97干综合网| 97色欧洲| 欧美精品成人一区二区在线观看| 久久免费99精品久久久久久| yellow网站免费观看日韩高清无码| 欧美一区二区三区蜜桃| 婷婷九月| 色爱综合网欧美| 中文子幕一二三| 女优大全 - 91n| 深夜福利黄片| 日韩欧美一级特黄大片| 1024久久高清视频| 久久同城AV| 丝袜美腿操av| 国产精品爱欲| 亚洲制服欧美另类内射| 91丨九色丨东北熟女| 一区二区偷拍拍视频| 欧美成人9797| 人妻免费观看| 日韩91网站| 久久精品人人做人人看| 深田咏美亚洲精品福利社| 久热69九色熟妇97| 91色s| 久久一二三四| 久久婷婷综合国际产色怕| 欧美视频在线第3页| 中文字幕加勒比海高清无码免费视频| 欧洲与亚洲欧美精品中文字幕| 久艹免费| 探花熟女,姿勢到位,體驗感也到位| 欧美成人精品A片免费一区99| 熟女色图在线| 激情欧美97| 久操91视频| 欧美一区二区亚洲天堂| 久久欧洲| 日本媚薬中文字幕在线| 天天做日日做天天欢。| 第四色亚洲色图| 另类老少妇| AV一区观看| 亚洲激情网一二三四区| 碰人碰碰人人开房人肉| 91深夜夜| 黄色一级视| 黑人天8A∨高清网站| 国产精品久久久久久久久久二区三区| 国产亚洲色婷婷久久99精品91 - 百度 | 国产精品一级二级在线| 人妻偷拍一区二区三区| 日本精品一区二区中文字幕| 国产乱码精品久久久久久| 日本一区二区不卡| 精品国产乱码久久久久久口爆网站| 精品久久在线区一区| 91高清欧美| 黄片免费久久久久久久| 国产精品高潮久久AV| 黄骗免费网站| 欧美色五月| 香蕉国产97| 国产不卡免费在线视频| 久久精品视频久久久| 一区二区视频在看| 超碰在线国产| 精品二区三四区五电影 | 一区二区三区精品视频| 香蕉免费一区二区三区不读| 懂色中文一区二区三区| 国产精品九9| 国产精品视频在线观看| 色y情视频免费看| 婷婷亚洲综合| 黄呦呦在线| 黑人精品XXX一区一二区| 色亚洲欧美| 男女激情黄色网址| 欧美日韩亚洲五月天婷婷| 天天日天天干少妇日| 日本99热| 亚洲日韩美女丝袜美腿人妻视频| 色官网在线| 日本免费二区三区| 99久re热视频精品98| 天天夜夜rb| 欧美色色色| 免费成人在线熟妇网| 国产精品人妻熟女aⅴ| 欧美一区二区成人一卡| 日韩卡一卡二卡三在线| 人妻精品一区一区三区蜜桃91| 久操视频资源站公开| 久久视频少妇美女| 2024人人操人人摸| 欧美日韩资源| www.夜夜操| 国内伊人久久久久久网站视频| 粉嫩国产精品久久粉嫩| 欧美人与动性人交a| 九一综合精品视品av| 亚洲高清视频在线免费观看| 天天看特黄的免费网站| A V视频日本| 丝袜无码a片| 亚洲中文国际强奸字幕| 久久久精品久久| 国产免费一区在线观看| 天天cao在线| 二区熟妇韩日| 国产精品无码av| 亚洲日本大香蕉1| 国产久久一区二区午夜| 国产操逼视频在线观看| 超碰欧美97资源| 首页亚洲国产高跟丝袜诱惑视频| 国产免费黄色一级大片| 91爱做| 秋霞视频一区二区| 草草草视频在线免费看| 欧美日韩人妻少妇 一区二区三区| a在线视频免费观看| 婷婷超| 黄网站黄视频网站进入口| 欧美黄片欧美黄片xxx| 蜜臀99久| 亚洲视频二区 | 涩涩久久精品| 超碰免费在线| 久久性生大片免费观看性| 亚洲drav色图| 伊人影院在线理论播放| A片 AV一级在线播放观看免费| 超碰九7| 欧美日韩大陆黑人少妇99| 亚洲自拍青操视频| 猛交交| 免费亚洲黄色视频在线观看| 午夜精品久久久久久久久久久久久| 午夜福利区| 成人性爱电影网| 91视频精品| 90后后入| 伊人991| 加勒比无码一区二区三区| 很黄很色的视频在线观看| 熟妇视频一区二区三区在线| 老司机午夜精品福利视频一区二区 | 久久夜色一区二区| 激情五月婷婷综合| 岛国毛片手机在线观看| 欧美色综合| 久肏视频字幕| 日韩大香蕉AV影片| 国产激情av女片自拍| 干我久操| 国产乱子伦一区二区三区在线观看| 狠色婷婷久久一区二区三区_| 天天综合色电影| 国产欧美亚洲精品a第2页| 呦呦影院| 超碰久久.com| 亚洲AV在线资源| 色婷婷婷五月天激情四射| 午夜免费视频1000| 免费一级毛片在线视频观看| 一区操逼日比视频| 国产Av超碰| 91在线视频国产网站| 久久日韩肥臀| 久久精品国产97欧美精品亚洲 | 国产综合久| 熟女乱伦A| 岛国小电影| 中文字幕第2页| 丝袜美腿91| 这里是精品| 长长久久曰曰夜夜成人网| 亚洲一级特黄大片在线播放91| 欧美性色综合网| 国精综合一二三区影视| 色色色热| 五月天人妻综合| 大香蕉狠狠爱| a片亚洲一本通视频| 再深点灬舒服灬太大了好硬好爽| 欧美性高潮| 狠狠2050在线观看| 久久久久9| 少妇500双飞99| 久久久国产三级黄色片| 你想操日本小逼吗| 久久男人天堂| 亚洲强奸乱伦影视网| 日韩av在线精品观看| 97干在线| 成年女人18级毛片毛片免费观看| 最近的最新的中文字幕视频| 久久香蕉综合一本到3atv| 国产高清在线观看欧美| 亚洲欧洲日韩国产自在线| 久久亚洲AV无码专区首页| 一类无码操逼视频| 欧美顶级黄色大片免费| 日韩成人性爱电影在线播放| 久久久久国产无av| 国产亚洲色婷婷久久99精品91| 亚洲精品xxx| 美国aaaaa一级黄片| 国产一区二区av综合| 成人亚欧免费视频| 在线性黄高清免费视频| 大香蕉九九| 97亚洲综合电影| 中美日韩毛片| 色娱乐色呦呦夜夜夜夜av| 亚洲青青草| 国产后入式在线观看| 玖玖久久久| 色五月大香蕉| 成人综合色网| 亚洲蜜臀懂色| 久久视频,这里只有精品| 新91视频.cmp| 高清国产精品福利网站| 久久五十路熟女人妻| 竹菊影视国产一区二区| 男人天堂一区二区| 天天综合影院91| 青娱乐蜜桃臀AV色婷| 视频二区熟女人妻| 丁香九月婷婷| 激情五月天社区| 亚洲欧美成人在线| 中文啪啪视频| 情侣操 逼视频99| 啊啊在线| av在线播放国产一区| 亚洲成人性爱在线观看| 成人在线视频二区| 亚洲自拍青操视频| 国产美女高潮| 日本激情免费大片| 亚洲人成色9999精品久久| 久久宗合亚洲| 欧美在线播放| av天堂5| 日本午夜久久电影| 色天堂综合| 唯美清纯 妖精视频| 在线播放免费av福利片| 长长久久免费视频| 四虎在线免费视频| 久久伊人最新网址视频| 抽插无码高清一区| 99在线观看无大码| 少妇高潮九九九九| 亚洲欧洲日韩国产自在线| 久久久亚洲精品电影免费看| 亚洲精品蜜桃久久久| 这里只有精品视频在线观看麻豆| 天美传媒国产原创中文字幕亚洲欧美另类 | 国产av强奸美女| 午夜天天碰综合视频| 人妻熟女一区二区| 精品一区二区三区国产 | 立川理惠无码一区二区| 91成人在线| 精…码一二三区| 久热大香蕉| 骚女高跟AV在线| 18禁看网站一区| 91狠狠色丁香婷婷综合久久| 天天综合站| 日本黄色大片一级视频免费麻豆| 97人肏| 操久久久久| 日韩中文字幕视频在线观看| yy少妇精品久久| 97超碰人人模人人拍人人| 日日夜夜狠狠| 欧美97网| 极品色www影院| 很很很很操| 欧美亚洲第一页| 区一二区日韩亚洲乱码av电影| 九九热九九| 超碰碰碰碰| 熟妇无码视频三区| 秋霞视频一区二区| 超碰这里有精品| 亚洲av影音先锋| 夜夜高潮夜夜爽| 国产精品白丝| 日韩精品99999| 国产农村妇女毛片精品久久| 国产AV毛片| 女人的天堂大香蕉网| 日韩99精品视频综合区| 丰满搜索结果 -第18页- 久久高清无码 | 成人av在线播放| 欧美图片色综合| 精品人妻一区二区三区日产乱码| 大香蕉亚洲中文| 91无遮挡| 日本一二区免费| 亚洲加勒比久久日本道| 婷婷三区| 少妇一区二区三区高速| 超碰97最新人妻| 精品国产一区二区三区四区在线看| 欧美五区| 老司机老司机午夜影院| ...日韩成人一区二区三区字幕| 岛国大片在线观看网站入口| 精品久久九| 精品人人插人人操| 97国产|免费| 青青操青娱乐| 大象AV在线| 伊蕉97蜜桃97狠狠综合干| 激情五月天插| 蜜臀在线看片| 99热啪啪| 亚洲一区在线观看欧洲| 熟女高潮合集-永久久久-成人AV| av在线免费一区二区| 欧美日韩精品久久久久东北老熟妇| www.夜夜操| 久久久久久9| 欧美天堂日韩三级国产传媒| 岛国色情视频在线观看| 爱干爱射网啊啊啊| 亚洲精品啪视频| 日日AAvv| 97在线免费看| 欧美日韩在线视频网站| 91熟女.com| 99色| 国模私拍一区二区三区神乳| 欧美视频激情久久久久久| 日韩九区| 天天影视色香欲综合网小说| 久久草视频污视频| 人妻aa| 思思热国产高清| 青青草成人视频在线观看二区| 亚洲av淫乱| 欧美性爱五月天| 搡老女人老熟女91| 97在线观看免费视频l| 操逼操逼视频操逼| 一区二区视频在看| 天天日天天射天天干| 十八禁啪啦拍视频无遮挡| 网站A V在线| 夜夜嗨老熟女AV一区二区三区| 91ise欧美| 国产成人欧美一区二区三区的国产| 亚洲久9| 日韩啪啪啪视频| 九九av| 26UUU欧美激情一区二区| 欧美 亚洲 在线| 夜夜骑天天燥| 天美AV片| 国产福利精品最新在线 | 亚洲一区中文字幕一区| 国产乱伦视频污| 色97国产69香蕉| 这里只有精品视频在线| 成人a大片在线观看| 香蕉99秘 一区精品蜜桃臀| 日韩精品人妻中文字有码在线| 久久精品美女一区| 韩日性爱av| V A在线| 久99在线免费观看视频| 欧美人妻色| 神马久久久久眼| 8050午夜少妇无码| 人人干黄色| 国内伊人久久久久久网站视频| 国产中文字幕在线| 天美欧美国产| 久久久久久久 九九九九九九九| 国产无码一二三区| 在线观看色视频| 欧美 精品国产制服第一页| 怡红院成人视频| 中国熟女91| 二三四区精品| 鸥美插入视频| 北京专精特新企业招聘信息| 99热精品在线观看| 91强奸乱轮| 亚洲欧美综合区自拍另类| 偷拍 欧美 日韩| 亚洲清纯综合| 91青青在线视频| 欧美 日韩 婷婷 五月| 亚洲丝袜B诱惑| 91超碰人人| 国产自偷自拍一区| 国产熟女乱论| www.久久最新地址| 久久老女人| 久久人| 久久香蕉国产线看观看亚洲女人 | 97久久精品亚洲| 婷婷综合久久| 五月婷婷综合网| 狠狠操天天干| 99操碰| 亚洲欧美精品一区天堂久久| 另类小说五月天| 五月丁香综合激情| 久久久97| 久久极品一区二区| 久久99热这里只频精品6学生| 丁香九月激情| 色情综合网| 女人爽到高潮久久久| Julia在线播放亚洲久久| 精品人妻伦一二三区久久| 黄色高清无码无码破解免费暗网| 久久99亚洲精品久久99果| 国产又爽又黄| 狠狠综合| 国模精品一区二区三区苹果色戒 | 中文字幕一区二区无码成人| 欧美激情区| 久久伊人最新网址视频| 中文字幕在线免费观看2| 襙一襙| 亚洲色欲天天天堂色欲网女| 自拍偷拍 高清无码| 在线人人人人人人精品超| 国产精品久久成人免费| 亚洲欧美经典一区二区| 国产久久一区二区午夜| 宅男午夜在线视频| 最新中文字幕av| 国产精品午夜福利视频| 精品少妇99| 热99这里有精品综合久久| 国产无码三级视频在线观看| www.伪伪| 五月丁香成人网| 综合色图,成人综合网| 97综合在线观看| 男人久久精品| 97色操| 最新亚洲黄色免费电影| 欧美探花网| 一区二区三区激情在线观看| 91丨国产丨白浆| 97青娱乐超碰久久| 日韩电影免费网站麻豆视频| 人妻天堂网| 成人性爱av| www.人人cao| 91亚州日韩高清| 久久一二三四不卡| 欧美亚州综合网图片| 免费人成毛片乱码| 国产三级日产三级韩国三级| 亚洲国产一区二区三区四区国产| 97国产精品国| 中文字幕一区二区三四五区日日骚| 亚洲综合在线91| 极品欧美一区二区三区| 日韩精品一区二区三区色欲| 日韩精彩免费| 久久久久久裸体| 欧美日韩制服| 人人操人人操人人操人人操人人操人人人11.CM | 色 婷97| 久久久96精品| 91视频精品| 成人在线日韩| 亚洲www91| 欧美se综合| 欧美性爱第一区| 国模限制级电影| 97超碰免费生活| 九九九九国产| 大伊香蕉在线视频免费| 禁十八久久| 97久久超碰日韩精品| 人人操人人插 - 百度 - 百度| 免费视频a级毛片免费视频| 欧美aⅴ99久久黑人专区| 肥佬影院91| 久久男人精品| 久久婷婷色综合一区二区三区| 亚洲 综合 第一页| 日本一区二区亚洲综合| www.激情| 蜜臀在线看片| 国产在线激情视频| 精品一区二区三区蜜桃臀赵总 | 天堂种子在线www网资源| 国产熟女一区二区丰满| 白 大 人妻 区 在线| 97免费在线视频| 好一吊区二区| 日韩性爱小视频| 亚洲AV成人在线| 少妇专区一二三四五| 国产精品美女| 色综合色色| 午夜精品久久久久| 亚洲电影中字一区二区| 亚洲天堂电影精品一区| 偷拍亚洲情色| 国产欧美一级在线观看| 麻豆一区在线| 呦呦影院| 在线观看十八禁| 国产精选视频| 亚洲另类在线观看| 99色在线| 天天干夜夜一操| 97色涩| 亚洲国产一区二区入口| 久久亚洲不卡一区二区三区| 国产老太乱伦一区| 天天摸,夜夜摸| 天堂性色| 亚洲色婷婷| 日本二区不卡| 91呆哥人妻| 啊啊啊操死我了| 欧美系列在线一区二区| 欧亚日韩综合精品国产| 欧美一级A片不卡视频。| 欧洲天天在线| 2021国产成人精品久久| 奸色色 男人天堂 天天射| 久久黄人人爽视频| 无码聚合| 欧美天天影院| 91站街按摩店老熟女熟女| 大但人体久久久久| 在线色导航| 锕锕好爽 死我在线观看| 国产日韩欧美亚洲精品95 | 97爱免费插| 91福利网在线观看| xxx亚洲午夜天堂| jazzjazz国产精品麻豆| 日日干日日操五月天伦理视频| 男人女人18禁片免费看网站| 天天日天天射天天干| 日本性爱欧美性爱| 亚州高清av| 人妻熟女av国产网站| 亚洲性综合11| 丁香婷婷色五月| 中文字幕av一区二区三区人妻少妇 | 国产精品97超碰| 99久久综合网| 欧美色图99| 日日夜夜干| 四虎884| 久久超碰久| 香蕉视频精品亚洲一区二区三区在线播| 亚洲男人天堂Av| 国产成年女黄特黄| 美骚妇av高清在线| 在线欧美69V免费观看视频| 中美日韩毛片| 激情综合网五月婷婷五月天| 久操免费电影| 亚洲 图片 综合91| AV一起草在线| 国产视频一区二区三区在线免费观看 | 综精品久久久aaaa| 蜜乳AV色欲AVAV无码| 欧美成人免费在线观看| 色九久| 人妻酒店出差被中出免费在线播放| 日本三级久| 久久久久国产精品久久久| 神马久久久久久伦理片| 精品白丝一区| 国产乱码久久| 大香蕉黄色一级片免费看| 中文字幕色AV| 欧美在线干| 无码高清操逼| 欧美熟女激情| 免费中文在线| 丰满人妻区一区二区三| 超碰碰激情97+久| 免费A V在线播放| 91在线视频国产网站| 91少妇香蕉久久精品| 91久久婷婷| 欧美日韩啪啪电影| 999熟女精品| 精品久久久九九九孕妇| 亚洲国产精品无码AV在线| 97碰久久| av东京热男人的天堂| 国产11页| 大香网站| 91内射| 操老熟女AV| 99精品在线| 999亚洲国产视频| 78久久| 天天操天天日天天干| 看看小穴| 欧美一级黄片视频在线| 超碰97精品| 亚洲在钱| 六月丁操逼| 99热思思| 欧美伊人久久综合网| 91色欧美| 欧美色图天堂网m| 99热99在线| 国产女人与拘做受视频免费| 久久岛国| 超碰在线1234区| 久久av网| 国产精品一区人妻精品阁在线| 中日韩熟女| Sekablack无码一区| 九九热三级片| 久草毛片| 欧色性第一页| 一二三啪啪专区| 丁香六月婷| 少妇一区二区三区高速| jazzjazz国产精品麻豆| 亚洲高清欧美总合| 成年人免费观看网站| 人妻人人澡人人爽人人| 在线人妻熟女一区二区三区四区五区| 五月丁香激情综合网| 岛国视频免费在线观看| 日本成熟少妇A∨网站| 91丝袜美女视频| 97国产精品一区| 超碰社区97| 亚洲精品一卡二卡三卡福利视频网站 | 日韩AV无码中文一区二区| 一级做a爰片性色毛片久久| 美女啊啊啊啊啊| 国产精品午夜福利| 欧美精品 - 91爱爱| 国产精品乱人伊人网| 发朗少妇买婬全视频中文| 天天色播| 九九久久精品| 丁香五月婷婷基地| 色婷婷五月天| 精品国产一区二区三区av在线资源| 九九碰九九爱97| 五月丁香色综合| 91大学精品激情戏| 操狠狠| 狠狠狠一区二区三区| 97青青操视频| 九九九久千久久激情蜜桃在线看 | 无遮挡男女激烈动态图| 色屁屁影院www国产| 久久超碰网| 欧美91精品国产自产| 超碰95| 少妇被c 黄 免费观看| 97无码视频在线播放| 黄片免费日韩| 国产无码久久高清| 狠狠久久手机视频精品| 久久精品国产亚洲妲己影视| 女人与公拘交酡2020视频| 中文字幕第9页萱萱影音先锋| 中文操逼字幕| 国产又粗又大硬免费色网视频| 精品人成视频在线观看| 欧美人与动性人交a| 久久免费99精品久久久久久| 亚洲无码超碰免费| 亚洲无码国产精品久久| 亚洲精品xxx| 91动漫操逼视频| 色综合久久88色综合久久天天| 性爱av网站| 中文字幕永久在线| 1二区9| 美女极品一区二区三区| 性爱精品一区| 亚洲一区二区麻豆影院| 色老汉色| 青操影院| 亚洲丝袜诱惑| 亚洲一卡二卡在线免费| 亚洲精品第一| 色爱综合网| 97免费视频网| 素人伊尹大香蕉免费下载视频| 97碰久久| 国产精品麻豆视频网站| 丁香五月电影| 国产精品午夜成人福利| 破处bbq| 国产精品视频内谢女人| 91c色| 亚洲91极品| 激情小说亚洲图片| 欧美亚洲手机在线| 婷婷丁香九月| 日日日日做夜夜夜夜无码| 日本韩欧美在线播放a| 97干com| 日韩中文字幕精品一二三事国产精品| 欧美美女视频| 99re公开精品免费视频| 偷拍欧美综合| 岛国不卡超碰护士AV在线播放| 久久久久久久9| 成人性爱av.com| 麻豆天美国美国产| 男人的天堂日韩| 一起草三级AV电影在线观看 | 久久 精品| 亚洲国产成人精品久久久国产成人一区二区三. | 日韩无码嘿咻黑热久| 男人天堂婷婷五月天校园春色| 四虎在线播放| 五月婷亚洲精品天堂| 韩日无码在线观看| 人人爽夜夜操| 中国91AV| 国产亚洲精品农村妇女| 国产精品久久久视频| 无码人妻丰满熟妇区毛片| 人人操 欧美| 天天日少妇逼AV| AV色图| 国产在线观看91精品一区| 色色亚洲| 日本不卡免费二区| 天天日天天搞天天干| 亚洲欲色9532548967一区| 人妻精品一区一区三区蜜桃91| 国产精品盗摄 偷窥盗摄| 久久婷婷一区二| 99精品无码| 伊人久久大香线蕉无码| 色91综合网| 久久精品黄色| 香蕉久久国产AV一区二区| 精品人妻无码一区二区三区不卡-精品人妻无码一区二区...|精品少妇一区二区三 | 精品在线观看视频在线| 97国产天堂岛| 青娱乐淫乱1314| 红杏大香蕉| 蜜桃臀av一区二区| 国产精品麻豆视频网站| 97视频在| 日本孕妇一区二区视频操逼免费看 | 一级性爱视频免费在线| 夜夜肏2021| 97中文字幕九区| 中文字幕性感少妇av| 亚州九九九精品视频| 波多野结衣一级视频| 精品视频97| 人妻无一区二区三区| 成人女人国产|