-
kaldirishe (11.02.13 22:38) [0]Здравствуйте уважаемые форумчане)
Занялся на досуге оптимизацией кода копирования битмапа на битмап(в процедуре прямоугольник на прямоугольник, но не суть). Решил попробовать процедуру move, получил ацкое ускорение и забыл) Однако вернувшись к ней снова меня стали терзать смутные сомнения… А не копирую ли я массив указателей? Что будет если по адресу убитого первого битмапа запишется что то иное. Или мои сомнения беспочвенны и так сделать можно?
Собственно код:
TColor32 = packed record
b, g, r, a: Byte;
end;
TLine32 = array[Word] of TColor32;
PLine32 = ^TLine32;
function DrawAlpha(Source, Dest: TBitmap; SourceRect, DestRect: TRect): Boolean;
var
x0, y0, y, temp_y, AWidth: Integer;
x1, y1, x2, y2: Integer;
x3, y3, x4, y4: Integer;
SourceLine, DestLine: PLine32;
begin
Result := (Source.PixelFormat = pf32bit) and (Dest.PixelFormat = pf32bit);
if Result then
try
with Source do
begin
x1 := SourceRect.Left;
if SourceRect.Left < 0 then x1 := 0
else if SourceRect.Left >= Width - 1 then x1 := Width - 1;
x2 := SourceRect.Right;
if SourceRect.Right < 0 then x2 := 0
else if SourceRect.Right >= Width - 1 then x2 := Width - 1;
y1 := SourceRect.Top;
if SourceRect.Top < 0 then y1 := 0
else if SourceRect.Top >= Height - 1 then y1 := Height - 1;
y2 := SourceRect.Bottom;
if SourceRect.Bottom < 0 then y2 := 0
else if SourceRect.Bottom >= Height - 1 then y2 := Height - 1;
end;
with Dest do
begin
x3 := DestRect.Left;
if DestRect.Left < 0 then x3 := 0
else if DestRect.Left >= Width - 1 then x3 := Width - 1;
x4 := DestRect.Right;
if DestRect.Right < 0 then x4 := 0
else if DestRect.Right >= Width - 1 then x4 := Width - 1;
y3 := DestRect.Top;
if DestRect.Top < 0 then y3 := 0
else if DestRect.Top >= Height - 1 then y3 := Height - 1;
y4 := DestRect.Bottom;
if DestRect.Bottom < 0 then y4 := 0
else if DestRect.Bottom >= Height - 1 then y4 := Height - 1;
end;
if x2 - x1 > x4 - x3 then x0 := x4 - x3
else x0 := x2 - x1;
if y2 - y1 > y4 - y3 then y0 := y4 - y3
else y0 := y2 - y1;
temp_y := y3 - y1;
AWidth := x0 * 4;
for y := y1 to y1 + y0 do
begin
SourceLine := Source.ScanLine[y];
DestLine := Dest.ScanLine[temp_y + y];
Move(SourceLine[x1], DestLine[x3], AWidth);
end;
except
Result := False;
end;
end; -
MBo © (11.02.13 23:18) [1]>А не копирую ли я массив указателей?
Нет, сами данные -
kaldirishe (12.02.13 08:48) [2]Пасиб
-
kaldirishe (13.02.13 23:01) [3]Добрый вечер!
Ну раз пошла такая пьянка), позвольте спросить еще об одном, попробую сформулировать… Я масштабирую изображение формата bmp 32 бита, средствами gdi+. Алгоритм может вызвать недоумение, но опытным путем проверено, что прямая загрузка\выгрузка через поток-потеря прозрачности.. короче это работает, проверено. Далее изображение выводится через AlphaBlend на конечный битмап. Прошу прощения за много букф, перехожу к главному… Столкнулся с непонятной для себя ситуевиной, на семерке, при увеличении, получаю цветную каемку на изображении, на xp, все нормально( Может кто нибудь это объяснить и посоветовать как с этим бороться?
http://layerform.net/w7_n.png под семеркой
http://layerform.net/w_xp_n.png xp, виртуалка
код масштабирования, после выводим на конечный битмап и UpdateLayeredWindow
function StretchBitmap(ASource, ADest: TBitmap; AWidth, AHeight: Integer): Boolean;
var
AGPSource, AGPDest: TGPBitmap;
AW: Integer;
ABitmapData: TBitmapData;
AScanline: PByte;
ABitmapLine: PLine32;
AStride, Y: integer;
ADestColor: PRGBQuad;
begin
Result := ASource.PixelFormat = pf32bit;
if Result then
try
with ASource do
begin
ADest.Width := AWidth;
ADest.Height := AHeight;
ADest.PixelFormat := pf32bit;
AGPSource := TGPbitmap.Create(Width, Height, PixelFormat32bppARGB);
AGPDest := TGPbitmap.Create(AWidth, AHeight, PixelFormat32bppARGB);
try
AGPSource.LockBits(MakeRect(0, 0, Width, Height), ImageLockModeWrite, PixelFormat32bppARGB, ABitmapData);
try
AScanline := ABitmapData.Scan0;
AStride := ABitmapData.Stride;
AW := Width shl 2;
for Y := 0 to Height - 1 do
begin
ABitmapLine := ScanLine[Y];
ADestColor := PRGBQuad(AScanline);
Move(ABitmapLine[0], ADestColor^, AW);
inc(AScanline, AStride);
end;
finally
AGPSource.UnlockBits(ABitmapData)
end;
with TGPGraphics.Create(AGPDest) do
try
SetInterpolationMode(InterpolationModeHighQualityBicubic);
SetSmoothingMode(SmoothingModeAntiAlias);
DrawImage(AGPSource, MakeRect(0, 0, AWidth, AHeight), 0, 0, Width, Height, UnitPixel);
finally
Free;
end;
AGPDest.LockBits(MakeRect(0, 0, AWidth, AHeight), ImageLockModeRead, PixelFormat32bppARGB, ABitmapData);
try
AScanline := ABitmapData.Scan0;
AStride := ABitmapData.Stride;
with ADest do
begin
AW := Width shl 2;
for Y := 0 to Height - 1 do
begin
ABitmapLine := ScanLine[Y];
ADestColor := PRGBQuad(AScanline);
Move(ADestColor^, ABitmapLine[0], AW);
inc(AScanline, AStride);
end;
end;
finally
AGPDest.UnlockBits(ABitmapData)
end;
finally
AGPDest.Free;
AGPSource.Free;
end;
end;
except
Result := False;
end;
end; -
MBo © (14.02.13 06:31) [4]>на семерке, при увеличении, получаю цветную каемку на изображении, на xp, все нормально
Возможно, по-разному работают алгоритмы интерполяции цветов при изменении размера -
Eraser © (14.02.13 07:21) [5]
> kaldirishe (11.02.13 22:38)
лучше использовать bitblt и ее производные, быстрее будет наверняка. -
kaldirishe (14.02.13 08:52) [6]
> Возможно, по-разному работают алгоритмы интерполяции цветов
> при изменении размера
Как то странно это выглядит( Разные библиотеки для разных версий с одинаковыми заголовками( Кстати, только сейчас обратил внимание-форма в виде рисунка тоже различается на приведенных картинках. А ее я gdi+ не мучал, только AlphaBlend и UpdateLayeredWindow. Надо сильно подумать(
> лучше использовать bitblt и ее производные, быстрее будет
> наверняка.
Я попробовал gdi+ из-за сглаживания. -
kaldirishe (14.02.13 09:13) [7]Ложная тревога, сейчас на работе посмотрел как выглядит у сослуживца на семерке… Все ок. Значит «проблемы» с домашним ноутом, на котором идет борьба за производительность, хотя глубина цвета у него та же, 32.
-
Eraser © (14.02.13 19:16) [8]
> kaldirishe (14.02.13 08:52) [6]
для bitblt сглаживание смысла не имеет по определению, а для stretchblt его можно включить. -
antonn © (25.02.13 20:25) [9]
> лучше использовать bitblt и ее производные, быстрее будет
> наверняка.
собственно stretchblt и может давать каемку, т.к. использует "аппаратное" сглаживание -
kaldirishe (27.02.13 17:28) [10]Отчитываюсь), мой сайт (я его правда на буржуйском языке сделал) http://layerform.net/, раздел “Download”, пример “This example shows how to create a desktop with TStretchButtonLayerControl of the "three steps"
(for ver 2.0)”. Масштабирование выполнено средствами GDI+, хотя как масштабирует Photopaint мне нравится больше.