小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

我的Qt作品(9)Qt使用Cairo繪圖引擎提升抗鋸齒效果【開源】

 漢無為 2023-03-14 發(fā)布于湖北

之前寫了一篇文章《Qt使用GDI繪圖(僅Windows平臺)》

Qt使用GDI繪圖(僅Windows平臺)_libaineu2004的博客-CSDN博客

本篇重點介紹Cairo繪圖引擎,Qt自帶的QPainter的繪圖效率和抗鋸齒效果都沒有cairo的好。cairo 的目標(biāo)是以跨平臺的方式在打印機和屏幕上產(chǎn)生相同的輸出,它正在成為 Linux? 圖形領(lǐng)域的重要軟件。GNOME、GTK+、Pango 等許多軟件已經(jīng)使用了它提供的 2D 功能。另外,cairo 還支持生成 PostScript 或 PDF 輸出,從而產(chǎn)生高質(zhì)量的打印結(jié)果。在理想情況下,cairo 的用戶可以在打印機和屏幕上獲得非常接近的輸出效果。

一、Cairo簡介

Cairo:C編寫的開源繪圖引擎(基于LGPL協(xié)議),大名鼎鼎的FireFox就是用這個繪圖引擎的。Cairo是非常流行的開源2D圖形渲染引擎庫,它支持包括X-Windos,Win32,圖像,pdf在內(nèi)的各種輸出設(shè)備。目前,Cairo已被廣泛的使用在多個平臺上來渲染圖形界面,包括Firefox/Webkit-EFL/GTK+/Poppler/Qt等等。Qt的QPainter提供的抗鋸齒效果沒有cairo的好。cairo是用C編寫的,但是為大多數(shù)常用的語言提供了綁定。選用 C 語言有助于創(chuàng)建新的綁定,同時在進行C語言調(diào)用時可以提供高性能。應(yīng)該特別注意Python綁定,它支持快速原型開發(fā),而且降低了學(xué)習(xí)cairo繪圖API的門檻。Cairo的繪圖效率是接近GDI/GDIPlus的。經(jīng)過優(yōu)化算法,可以做到完全忽略繪圖效率上的差別。此外,gtk不如qt流行,Qt支持cairo。

cairo 是一個矢量繪圖(vector drawing)庫,因此繪圖需要對圖形進行幾何描述,而不是描述位圖中填充的像素。在采用位圖繪圖(bitmap drawing)時,按照預(yù)先決定的布局用預(yù)先決定的顏色填充一系列像素,而且圖形的質(zhì)量與位圖的大小成正比。 在放大或修改位圖圖像時,位圖繪圖方法的效果就會變差。圖像常常會變得模糊,就像是近距離觀看背投電視或其他大屏幕電視時的效果。在某一距離上,圖像可能看起來很清楚,但是靠近之后就會看到許多離散的點。因為數(shù)據(jù)無法定義預(yù)先定義的像素之間應(yīng)該是什么,所以放大時會很明顯地損失清晰度。計算機繪圖系統(tǒng)和體系結(jié)構(gòu)很早就出現(xiàn)了,cairo 的設(shè)計借鑒了 PostScript 和 PDF 模型的許多經(jīng)驗。cairo 之所以借鑒 PostScript 和 Portable Document Format(PDF)方法是因為,它們都使用數(shù)學(xué)語句定義圖像。由于用幾何方法表示圖像,所以可以在任何時候在一定范圍內(nèi)計算幾何描述,從而重新創(chuàng)建整個圖像(或一部分圖像)。圖形的幾何性質(zhì)被表示為點、曲線和直線(這些元素構(gòu)成了矢量)。

Cairo samples 官方樣例

Examples 官方案例

Download

Index of /snapshots 搶鮮版源碼

Index of /releases 穩(wěn)定版源碼,提供了C/C++,Python,R語言的支持。pixman是它的依賴庫。

https://github.com/freedesktop/cairo C語言源碼

https://github.com/pygobject/pycairo Python bindings for cairo

cairo / cairo-demos · GitLab

二、Cairo使用示例

例1、和Qt結(jié)合的原理是:Cairo畫圖到QImage的緩存(image.bits),再用QPainter把QImae貼圖出來。

  1. void MainWindow::paintEvent(QPaintEvent *pEvent)
  2. {
  3. Q_UNUSED(pEvent);
  4. //原生的繪圖
  5. QPainter p(this);
  6. p.drawLine(QPoint(0, 0), QPoint(150, 220));
  7. //使用cairo繪圖引擎
  8. const char *pVersion = cairo_version_string();
  9. qDebug() << pVersion;
  10. //創(chuàng)建一張圖QImage
  11. int iW = this->width();
  12. int iH = this->height();
  13. QImage image(iW, iH, QImage::Format_ARGB32);
  14. unsigned char *pData = image.bits();
  15. int iLineStride = image.bytesPerLine();
  16. //將此圖轉(zhuǎn)換為cairo圖
  17. cairo_surface_t *pCairoSurface = cairo_image_surface_create_for_data(pData, CAIRO_FORMAT_ARGB32, iW, iH, iLineStride);
  18. cairo_surface_set_device_scale(pCairoSurface, 1, 1);
  19. cairo_t *pCairoContext = cairo_create(pCairoSurface);
  20. cairo_surface_destroy(pCairoSurface);
  21. if (pCairoContext)
  22. {
  23. double x = 100.6, y = 328.0;
  24. double x1 = 102.4 + 100, y1 = 130.4,
  25. x2 = 153.6 + 240, y2 = 405.6,
  26. x3 = 230.4 + 400, y3 = 200;
  27. cairo_move_to(pCairoContext, x, y);
  28. cairo_curve_to(pCairoContext, x1, y1, x2, y2, x3, y3);
  29. cairo_set_line_width(pCairoContext, 1.0); //設(shè)置線寬
  30. cairo_set_source_rgb(pCairoContext, 1.0, 0.0, 0.0); //設(shè)置線顏色
  31. cairo_stroke(pCairoContext);
  32. cairo_destroy(pCairoContext);
  33. }
  34. //貼圖
  35. p.drawImage(this->rect(), image);
  36. }

例2、讀圖片文件,并顯示

  1. //define params
  2. int width, height, channels;
  3. //read image data from file using stb_image.h
  4. unsigned char* data = stbi_load(imagePath.c_str(), &width, &height, &channels, STBI_rgb_alpha);
  5. //create surface with image size and format is ARGB32
  6. this->imageSource = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  7. //get pointer of cairo data
  8. unsigned char * surface_data = cairo_image_surface_get_data(this->imageSource);
  9. //copy current data to surface pointer
  10. memcpy(surface_data, data, width * height * 4 * sizeof(unsigned char));
  11. //mark as dirty to refresh surface
  12. cairo_surface_mark_dirty(this->imageSource);
  13. //free image data
  14. free(data);

或者

  1. int w, h;
  2. cairo_surface_t *image;
  3. image = cairo_image_surface_create_from_png ('data/romedalen.png');
  4. w = cairo_image_surface_get_width (image);
  5. h = cairo_image_surface_get_height (image);
  6. cairo_translate (cr, 128.0, 128.0);
  7. cairo_rotate (cr, 45* M_PI/180);
  8. cairo_scale (cr, 256.0/w, 256.0/h);
  9. cairo_translate (cr, -0.5*w, -0.5*h);
  10. cairo_set_source_surface (cr, image, 0, 0);
  11. cairo_paint (cr);
  12. cairo_surface_destroy (image);

三、完整的工程源碼及庫文件

本人使用的編程環(huán)境是QtCreator + MSVC2019 32/64位

https:///libaineu2004/cairo_demo

四、cairo的開源應(yīng)用案例是scribus軟件

scribus是開源項目,使用C++/Qt GUI

源碼檢索關(guān)鍵詞【cairo_image_surface_create_for_data】 

 Cairo畫圖到QImage的緩存(image.bits),再用QPainter把QImae貼圖出來。

  1. canvas.cpp
  2. void Canvas::drawContents(QPainter *psx, int clipx, int clipy, int clipw, int cliph)
  3. {
  4. ScPainter *painter=nullptr;
  5. QImage img = QImage(clipw * devicePixelRatio(), cliph * devicePixelRatio(), QImage::Format_ARGB32_Premultiplied);
  6. img.setDevicePixelRatio(devicePixelRatio());
  7. painter = new ScPainter(&img, img.width(), img.height(), 1.0, 0);
  8. painter->clear(palette().color(QPalette::Window));
  9. painter->newPath();
  10. painter->moveTo(0, 0);
  11. painter->lineTo(clipw, 0);
  12. painter->lineTo(clipw, cliph);
  13. painter->lineTo(0, cliph);
  14. painter->closePath();
  15. painter->setClipPath();
  16. painter->translate(-clipx, -clipy);
  17. painter->setZoomFactor(m_viewMode.scale);
  18. painter->translate(-m_doc->minCanvasCoordinate.x(), -m_doc->minCanvasCoordinate.y());
  19. painter->setLineWidth(1);
  20. painter->setFillMode(ScPainter::Solid);
  21. painter->end();
  22. psx->drawImage(clipx, clipy, img);
  23. delete painter;
  24. painter=nullptr;
  25. }

桌面排版軟件Scribus v1.5.5源碼編譯,使用VS2017+Qt5.12.7環(huán)境_libaineu2004的博客-CSDN博客

x1.skia

Skia是一個開源的二維圖形庫,提供各種常用的API,并可在多種軟硬件平臺上運行。谷歌Chrome瀏覽器、Chrome OS、Fuchsia、安卓、Flutter、火狐瀏覽器、火狐操作系統(tǒng)以及其它許多產(chǎn)品都使用它作為圖形引擎。Skia由谷歌出資管理,任何人都可基于BSD免費軟件許可證使用Skia。Skia開發(fā)團隊致力于開發(fā)其核心部分, 并廣泛采納各方對于Skia的開源貢獻。
Qt+Skia組合也是繪圖的好方案

Windows環(huán)境VS2017編譯skia庫,親測成功,借助skui的方法_libaineu2004的博客-CSDN博客

x2.geogebra

GeoGebra是自由且跨平臺的動態(tài)數(shù)學(xué)軟件,提供各級教育使用,包含了幾何、代數(shù)、表格、圖形、統(tǒng)計和微積分,集中在一個容易使用的軟件。

www./classic

www./calculator

GeoGebra Classic - GeoGebra

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多