Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C++ Builder
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.08.2015, 12:02   #21
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

ResourceSpace, у меня получилось выводить PNG-картинку, чтобы она просвечивала рабочий стол (см. пост #8 - сейчас удалось получить нарисованное, но только как единое целое, а не как два разных изображения):

Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TBlendFunction blend;
SIZE s1;
TPoint p1;
int x,y;
Vcl::Imaging::Pngimage::TByteArray *dst,*alpha;
TRGBLine *src;

TBitmap *bb;

SetWindowLong(Handle,GWL_EXSTYLE,GetWindowLong(Handle,GWL_EXSTYLE) | WS_EX_LAYERED);

TPngImage *Image = new TPngImage;
Image->LoadFromFile("Image.png");
Width = Image->Width;
Height = Image->Height;

bb = new TBitmap;
// with bb

bb->PixelFormat = pf32bit;
bb->Width = Image->Width;
bb->Height = Image->Height;

for (y = 0; y < Height; y++)
{
alpha = Image->AlphaScanline[y];
src = (TRGBLine *)Image->Scanline[y];
dst = (Vcl::Imaging::Pngimage::TByteArray *)bb->ScanLine[y];

for (x = 0; x < Width; x++)
{
dst->data[x * 4] = src->data[x].rgbtBlue * alpha->data[x] >> 8;
dst->data[x * 4 + 1] = src->data[x].rgbtGreen * alpha->data[x] >> 8;
dst->data[x * 4 + 2] = src->data[x].rgbtRed * alpha->data[x] >> 8;
dst->data[x * 4 + 3] = alpha->data[x];
};
};

// with blend

blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;


s1.cx = Width;
s1.cy = Height;
p1 = Point(0,0);

UpdateLayeredWindow(Handle,0,NULL,&s1,bb->Canvas->Handle,&p1,0,&blend,ULW_ALPHA);
bb->Free();

Image->Free();


Show();
}
А как можно сделать несколько таких слоёв? Чтобы поверх этой PNG-картинки выводить другие?

Последний раз редактировалось Bruce Wayne; 04.08.2015 в 12:06.
Bruce Wayne вне форума Ответить с цитированием
Старый 04.08.2015, 12:28   #22
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Вынести отрисовку в отдельный метод.
Вызывать нужное число раз.

Может стоит посмотреть в сторону этой функции:
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

Последний раз редактировалось waleri; 04.08.2015 в 12:31.
waleri вне форума Ответить с цитированием
Старый 04.08.2015, 12:35   #23
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

waleri, а можно пример с первым случаем (отрисовкой), если не сложно? Просто я не понимаю, что Вы имеете в виду, ведь нужно поверх основного PNG-изображения отображать/скрывать другие PNG-картинки...

Последний раз редактировалось Bruce Wayne; 04.08.2015 в 13:12.
Bruce Wayne вне форума Ответить с цитированием
Старый 05.08.2015, 06:36   #24
ResourceSpace
Форумчанин
 
Аватар для ResourceSpace
 
Регистрация: 30.06.2015
Сообщений: 353
По умолчанию

Прости, прозевал сообщение, только сейчас увидел. Незнакомый компонент, проверь что будет: если так или так делать будет затирать альфу?:
Код:
bb->Canvas->Draw(30, 30, Image);
Код:
Image->Draw(bb->Canvas, Rect(30, 30, Image->Width+30, Image->Height+30));
Можно конечно вручную блендить, но предлагаю сперва попробовать так (правил прям тут, могут быть опечатки):
Код:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;
TBlendFunction blend;
SIZE s1;
TPoint p1;

void __fastcall Premult_BMP(TBitmap *BMP){
    Vcl::Imaging::Pngimage::TByteArray *dst;
    int x,y;
    Width = BMP->Width;
    Height = BMP->Height;
    assert(BMP->PixelFormat = pf32bit)
    for (y = 0; y < Height; y++){
        dst = (Vcl::Imaging::Pngimage::TByteArray *)BMP->ScanLine[y];
        for (x = 0; x < Width; x++){
            dst->data[x * 4] = dst->data[x * 4] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 1] = dst->data[x * 4 + 1] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 2] = dst->data[x * 4 + 2] * dst->data[x * 4 + 3] >> 8;
        };
    };
}

void __fastcall Load_BMP_From_PNG(TBitmap *BMP, String FileName){
    Vcl::Imaging::Pngimage::TByteArray *dst,*alpha;
    TRGBLine *src;
    int x,y;
    TPngImage *PNG = new TPngImage;
    PNG->LoadFromFile(FileName);
    BMP->PixelFormat = pf32bit;
    BMP->Width = PNG->Width;
    BMP->Height = PNG->Height;
    Width = Image->Width;
    Height = Image->Height;
    for (y = 0; y < Height; y++){
        alpha = PNG->AlphaScanline[y];
        src = (TRGBLine *)PNG->Scanline[y];
        dst = (Vcl::Imaging::Pngimage::TByteArray *)BMP->ScanLine[y];
        for (x = 0; x < Width; x++){
            dst->data[x * 4] = src->data[x].rgbtBlue;
            dst->data[x * 4 + 1] = src->data[x].rgbtGreen;
            dst->data[x * 4 + 2] = src->data[x].rgbtRed;
            dst->data[x * 4 + 3] = alpha->data[x];
        };
    };
    PNG->Free();
}

void __fastcall TForm1::FormCreate(TObject *Sender){
    TBitmap *Layer;
    TBitmap *Image1;
    TBitmap *Image2;
    TBitmap *Image3;
    blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
    s1.cx = Width;
    s1.cy = Height;
    p1 = Point(0,0);
    SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
    Layer = new TBitmap;
    Layer->PixelFormat = pf32bit;
    Layer->Width = s1.cx;
    Layer->Height = s1.cy;
//    Layer->Canvas->Brush->Color:=RGB(0, 0, 0);
//    Layer->Canvas->FillRect(Layer->Canvas->ClipRect);
    Image1 = new TBitmap;
    Load_BMP_From_PNG(Image1, "Image1.png");
    Premult_BMP(Image1);
    Image2 = new TBitmap;
    Load_BMP_From_PNG(Image2, "Image2.png");
    Premult_BMP(Image2);
    Image3 = new TBitmap;
    Load_BMP_From_PNG(Image3, "Image3.png");
    Premult_BMP(Image3);
    AlphaBlend(Layer->Canvas->Handle, 20, 20, Image1->Width, Image1->Height, Image1->Canvas->Handle, 0, 0, Image1->Width, Image1->Height, &blend);
    AlphaBlend(Layer->Canvas->Handle, 50, 50, Image2->Width, Image2->Height, Image2->Canvas->Handle, 0, 0, Image2->Width, Image2->Height, &blend);
    AlphaBlend(Layer->Canvas->Handle, 80, 80, Image3->Width, Image3->Height, Image3->Canvas->Handle, 0, 0, Image3->Width, Image3->Height, &blend);
    Premult_BMP(Layer);
    UpdateLayeredWindow(Handle, 0, NULL, &s1, Layer->Canvas->Handle, &p1, 0, &blend, ULW_ALPHA);
    Image1->Free();
    Image2->Free();
    Image3->Free();
    Layer->Free();
    Show();
}
ResourceSpace вне форума Ответить с цитированием
Старый 05.08.2015, 08:31   #25
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

ResourceSpace, спасибо Вам ОГРОМНОЕ! (в приведённом коде буквально чуть-чуть поправить нужно было) И всем-всем, кто помогал и принимал участие! Всё получилось Вот конечный вариант:

Код:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;
BLENDFUNCTION blend;
SIZE s1;
TPoint p1;

void __fastcall Premult_BMP(TBitmap *BMP){
	Vcl::Imaging::Pngimage::TByteArray *dst;
	int x,y;
	Form1->Width = BMP->Width;
	Form1->Height = BMP->Height;
	assert(BMP->PixelFormat = pf32bit);
	for (y = 0; y < Form1->Height; y++){
		dst = (Vcl::Imaging::Pngimage::TByteArray *)BMP->ScanLine[y];
		for (x = 0; x < Form1->Width; x++){
            dst->data[x * 4] = dst->data[x * 4] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 1] = dst->data[x * 4 + 1] * dst->data[x * 4 + 3] >> 8;
            dst->data[x * 4 + 2] = dst->data[x * 4 + 2] * dst->data[x * 4 + 3] >> 8;
		};
	};
}

void __fastcall Load_BMP_From_PNG(TBitmap *BMP, String FileName){
	Vcl::Imaging::Pngimage::TByteArray *dst,*alpha;
    TRGBLine *src;
    int x,y;
	TPngImage *PNG = new TPngImage;
    PNG->LoadFromFile(FileName);
    BMP->PixelFormat = pf32bit;
    BMP->Width = PNG->Width;
	BMP->Height = PNG->Height;
	Form1->Width = PNG->Width;
	Form1->Height = PNG->Height;
	for (y = 0; y < Form1->Height; y++){
        alpha = PNG->AlphaScanline[y];
        src = (TRGBLine *)PNG->Scanline[y];
		dst = (Vcl::Imaging::Pngimage::TByteArray *)BMP->ScanLine[y];
		for (x = 0; x < Form1->Width; x++){
            dst->data[x * 4] = src->data[x].rgbtBlue;
            dst->data[x * 4 + 1] = src->data[x].rgbtGreen;
            dst->data[x * 4 + 2] = src->data[x].rgbtRed;
			dst->data[x * 4 + 3] = alpha->data[x];
		};
    };
    PNG->Free();
}

void __fastcall TForm1::FormCreate(TObject *Sender){
    TBitmap *Layer;
    TBitmap *Image1;
    TBitmap *Image2;
	TBitmap *Image3;
	blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.SourceConstantAlpha = 255;
	blend.AlphaFormat = AC_SRC_ALPHA;
    s1.cx = Width;
    s1.cy = Height;
    p1 = Point(0,0);
    SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
	Layer = new TBitmap;
    Layer->PixelFormat = pf32bit;
	Layer->Width = s1.cx;
    Layer->Height = s1.cy;
	Layer->Canvas->Brush->Color=RGB(0, 0, 0);
	Layer->Canvas->FillRect(Layer->Canvas->ClipRect);
	Image1 = new TBitmap;
	Load_BMP_From_PNG(Image1, "Image1.png");
	Premult_BMP(Image1);
	Image2 = new TBitmap;
	Load_BMP_From_PNG(Image2, "Image2.png");
	Premult_BMP(Image2);
	Image3 = new TBitmap;
	Load_BMP_From_PNG(Image3, "Image3.png");
	Premult_BMP(Image3);
	::AlphaBlend(Layer->Canvas->Handle, 20, 20, Image1->Width, Image1->Height, Image1->Canvas->Handle, 0, 0, Image1->Width, Image1->Height, blend);
	::AlphaBlend(Layer->Canvas->Handle, 50, 50, Image2->Width, Image2->Height, Image2->Canvas->Handle, 0, 0, Image2->Width, Image2->Height, blend);
	::AlphaBlend(Layer->Canvas->Handle, 80, 80, Image3->Width, Image3->Height, Image3->Canvas->Handle, 0, 0, Image3->Width, Image3->Height, blend);
	Premult_BMP(Layer);
	UpdateLayeredWindow(Handle, 0, NULL, &s1, Layer->Canvas->Handle, &p1, 0, &blend, ULW_ALPHA);
	Image1->Free();
	Image2->Free();
	Image3->Free();
	Layer->Free();
	Show();
}

Последний раз редактировалось Bruce Wayne; 05.08.2015 в 08:40.
Bruce Wayne вне форума Ответить с цитированием
Старый 05.08.2015, 21:47   #26
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

Цитата:
Незнакомый компонент, проверь что будет
Чуть не забыл: второй вариант не затирает альфу

Последний раз редактировалось Bruce Wayne; 05.08.2015 в 21:58.
Bruce Wayne вне форума Ответить с цитированием
Старый 09.08.2015, 12:38   #27
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

Единственная странность в том, что вся форма "мигает" (пропадает и тут же появляется) в процессе перерисовки не из FormCreate... Я стал загружать все изображения заранее, чтобы этого избежать, но появилась другая проблема: если выполнять отрисовку в цикле с задержкой в 200 мс для получения эффекта анимации, то при перемещении курсора по форме или при её перетаскивании становятся полностью невидимыми все уже загруженные картинки, кроме последней нарисованной, причём повторная отрисовка не помогает

Если же форму и курсор не перемещать, то всё отображается нормально. Свойство DoubleBuffered не помогает.

Если не загружать картинки в память заранее, то в цикле получается сильно бросающееся в глаза "мигание" всей формы. Как можно от этого избавиться? Уже всё перепробовал...
Bruce Wayne вне форума Ответить с цитированием
Старый 09.08.2015, 12:49   #28
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

Фухх... Отбой - уже в который раз ситуацию спасают таймеры Использовал их вместо цикла, проблема решена, простите за ложную тревогу...
Bruce Wayne вне форума Ответить с цитированием
Старый 09.08.2015, 13:06   #29
ResourceSpace
Форумчанин
 
Аватар для ResourceSpace
 
Регистрация: 30.06.2015
Сообщений: 353
По умолчанию

Ни в коем случае никаких циклов, очередь сообщений и так цикл.
Свойство DoubleBuffered не работает для Layered. Окно Layered не получает сообщений перерисовки и не использует рисования на окне.
Да и сам Layered по сути уже тот же DoubleBuffered.
ResourceSpace вне форума Ответить с цитированием
Старый 09.08.2015, 18:14   #30
Bruce Wayne
Пользователь
 
Регистрация: 08.07.2015
Сообщений: 21
По умолчанию

ResourceSpace, спасибо большое за информацию! Век живи, век учись
Bruce Wayne вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
AlphaBlend: наложить bmp на jpg или наоборот fredwriter Помощь студентам 2 17.09.2012 19:28
Полупрозрачный DIV X@OC HTML и CSS 3 18.04.2011 08:54
полупрозрачный слой voldemen HTML и CSS 1 14.09.2010 22:14
Добавить точечному рисунку альфа канал, что бы рисунок воспринимался функцией AlphaBlend Son Мультимедиа в Delphi 3 11.02.2010 16:46
Как наложить полупрозрачный рисунок поверх видео. jocry Мультимедиа в Delphi 3 03.11.2009 09:22