Russian Qt Forum
Ноябрь 01, 2024, 08:25 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QPainter: сделать часть изображения прозрачным.  (Прочитано 8252 раз)
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« : Февраль 06, 2015, 10:52 »

Доброго времени суток!

Есть простая задача: в QImage определённый регион QRect сделать полностью прозрачным, удалив при этом предыдущий контент.

попробовал "очевидный" вариант:
Код
C++ (Qt)
       QImage img;
       QRect removedRect;
       // .. получаем картинку и вычисляем регион
       QPainter p(&img);
       p.fillRect(removedRect, Qt::transparent);
 
- и упс: тот контент, что был в том регионе, за кот. отвечает rect, остался на месте.
Полез в доку, нашёл 2 метода: void QPainter::setOpacity ( qreal opacity ) и void   setBackgroundMode ( Qt::BGMode mode ) Ура, думаю, оно! Установил opacity в 1., а backgroundMode в Qt::OpaqueMode. Но результат остался прежним Грустный
Пришлось идти на крайние (с моей точки зрения) меры: апдейтить значения пикселей вручную:

Код
C++ (Qt)
       int startX = removedRect.topLeft().x();
       for  (int i = 0; i < removedRect.height(); ++i) {
           uchar *scanline = img->scanLine(i);
           scanline += startX * 4;
           for (int x = 0; x < removedRect.width(); ++x) {
               *(scanline + x) = (uchar)0x00;
               *(scanline + x + 1) = (uchar)0x00;
               *(scanline + x + 2) = (uchar)0x00;
               *(scanline + x + 3) = (uchar)0x00;
           }
       }
 
Сиё поделие работает, но как то по мне, дык слишком низкоуровнево. Может кто подскажет, как достичь такого же результата с  помощью QPainter?
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Февраль 06, 2015, 11:02 »

Создай новый QImage и залей его Qt::transparent.
Потом задай через QPainter::setClipRegion() "дырку".
Потом через QPainter::drawImage() залей оригинальную картинку.

UPD. Достаточно перед рендерингом "дырку" залить Qt::transparent и уже с учётом неё задать clipping ( QRegion( image_rect ).subtracted( hole_rect ) ).
« Последнее редактирование: Февраль 06, 2015, 11:15 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Февраль 06, 2015, 11:06 »

Код
C++ (Qt)
       p.fillRect(removedRect, Qt::transparent);
 
Это должно работать. Проверьте что формат имеджа QImage::ARGB32. Иначе выложите тестовый проект
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #3 : Февраль 06, 2015, 11:09 »

Это должно работать.
Неа, не должно. Это тоже самое, как положить на холст картины позрачное стекло. Подмигивающий
Записан

Qt 5.11/4.8.7 (X11/Win)
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« Ответ #4 : Февраль 06, 2015, 11:29 »

Код
C++ (Qt)
       p.fillRect(removedRect, Qt::transparent);
 
Это должно работать. Проверьте что формат имеджа QImage::ARGB32. Иначе выложите тестовый проект
Формат QImage::Format_ARGB32_Premultiplied, не работает. Действительно, как прозрачное стекло накладывается. Для теста пробовал вместо Qt::transparent  Qt::red - закрашивает красным, всё ок.
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« Ответ #5 : Февраль 06, 2015, 11:31 »

Создай новый QImage и залей его Qt::transparent.
Потом задай через QPainter::setClipRegion() "дырку".
Потом через QPainter::drawImage() залей оригинальную картинку.

UPD. Достаточно перед рендерингом "дырку" залить Qt::transparent и уже с учётом неё задать clipping ( QRegion( image_rect ).subtracted( hole_rect ) ).
Ух ты блин, спасибо. Но довольно накладно по расходам, хотелось бы без создания временных изображений, пока остаюсь на своём варианте.
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #6 : Февраль 06, 2015, 11:33 »

Ух ты блин, спасибо. Но довольно накладно по расходам, хотелось бы без создания временных изображений, пока остаюсь на своём варианте.
Смотри в "UPD". Там именно так.
Записан

Qt 5.11/4.8.7 (X11/Win)
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« Ответ #7 : Февраль 06, 2015, 11:38 »

Код
C++ (Qt)
       p.fillRect(removedRect, Qt::transparent);
 
Это должно работать. Проверьте что формат имеджа QImage::ARGB32. Иначе выложите тестовый проект
Пожалуйста:
Код
C++ (Qt)
#include <QApplication>
#include <QLabel>
#include <QPainter>
#include <QImage>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
 
   QImage img(QSize(500, 500), QImage::Format_ARGB32_Premultiplied);
   img.fill(Qt::green);
   {
       QPainter p(&img);
       p.fillRect(QRect(QPoint(0, 0), QSize(250, 250)), Qt::red);
       p.fillRect(QRect(QPoint(255, 255), QSize(250, 250)), Qt::transparent);
   }
   QLabel label;
   label.setPixmap(QPixmap::fromImage(img));
   label.show();
   return a.exec();
}
 
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Февраль 06, 2015, 11:54 »

Неа, не должно. Это тоже самое, как положить на холст картины позрачное стекло. Подмигивающий
Да, по умолчанию он альфу не реплейсит. Значит так ему по рогам

Код
C++ (Qt)
p.setCompositionMode(QPainter::CompositionMode_Clear);
p.fillRect(QRect(QPoint(255, 255), QSize(250, 250)), Qt::transparent);
 

А понятие "холст" давно устарело и употребляется только Верес'ом  Улыбающийся
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #9 : Февраль 06, 2015, 11:57 »

А понятие "холст" давно устарело и употребляется только Верес'ом  Улыбающийся
В своей ремарке я имел в виду настоящий холст Подмигивающий

Кстати, тоже была мысля через сomposition за-XOR-ить, но чего-то засомневался.
« Последнее редактирование: Февраль 06, 2015, 12:01 от GreatSnake » Записан

Qt 5.11/4.8.7 (X11/Win)
Kurles
Бывалый
*****
Offline Offline

Сообщений: 480



Просмотр профиля
« Ответ #10 : Февраль 06, 2015, 12:36 »

Всем спасибо. Взял вариант с
Код
C++ (Qt)
p.setCompositionMode(QPainter::CompositionMode_Clear);
 
Записан

Код
C++ (Qt)
while(!asleep()) sheep++;
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.219 секунд. Запросов: 23.