-
Избитый вопрос, но все ответы которые я нашел меня не устраивают. Так как все же качественно (!) и быстро (!) масштабировать картинку? Главным образом уменьшить.
-
Могу дать алгоритмы очень быстрого умменьшения в 2 и 4 раза, но завтра.
-
> Так как все же качественно (!) и быстро (!) масштабировать > картинку?
Уважаемый, если бы существовал Самый_Лучший_Алгоритм, других алгоритмов бы просто не было
-
>homm Буду признателен. Буду ждать. Хотя конечно хотелось бы иметь алгоритм для произвольного k.
-
>Так как все же качественно (!) и быстро (!) масштабировать картинку?
Качественно vs. Быстро = Оптимально
Так как численных критериев нет, то оптимально - это может быть и алгоритм B-Spline, Mitchel, Bell, Triangle (см. Irfan View), т.е. что-то между Lanchos и Hermite.
-
И где найти эти алгоритмы?
-
> И где найти эти алгоритмы?
Посмотри как сделано в FastDIB. Ну можно сделать конечно и более качественно, чем там, но быстрее уже вряд ли.
-
Тогда и я говорю: посмотри Graphics32. Там, кстати, фильтронаписание поставлено на поток - все карты у пользователя-программиста.
-
> [6] DVM © (13.10.07 23:50) > но быстрее уже вряд ли.
категорически не согласен
-
> категорически не согласен
ну тогда код в студию, чего зря фразами кидаться
-
> [9] antonn © (14.10.07 09:01) > ну тогда код в студию, чего зря фразами кидаться
Блин, я изтрахал весь яндекс, но так и не могу найти этот FastDib, дабы провести тестироание.
-
Кажется нашел, нужно было сразу гугль узать :) Счас будет вам код.
-
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
jpeg, ExtCtrls, StdCtrls, fastbmp;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
Image2: TImage;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
var
CPUisMMX: Boolean;
function NewDIBBitmap(Wi, He: DWORD; pf: TPixelFormat): TBitmap;
begin
Result := TBitmap.Create;
Result.PixelFormat := pf;
Result.HandleType := bmDIB;
Result.Width := Wi;
Result.Height := He;
end;
function DIBBits(BMP: TBitmap): Pointer;
var
Section: TDIBSECTION;
begin
BMP.HandleType := bmDIB;
GetObject(BMP.Handle, sizeof(TDIBSECTION), @Section);
Result := Section.dsBm.bmBits;
end;
function ScanLineSize(BMP: TBitmap): Integer;
var
Section: TDIBSECTION;
begin
BMP.HandleType := bmDIB;
GetObject(BMP.Handle, sizeof(TDIBSECTION), @Section);
Result := ((Section.dsBmih.biBitCount * Section.dsBmih.biWidth + 31) shr 3) and $FFFFFFFC;;
end;
function isMMX: Boolean;
var I: Integer;
begin
I := 0;
Result := false;
asm PUSHFD
POP EAX
OR EAX, 1 shl 21
PUSH EAX
POPFD
PUSHFD
POP EAX
TEST EAX, 1 shl 21
JZ @@1
AND EAX, not( 1 shl 21 )
PUSH EAX
POPFD
PUSHFD
POP EAX
TEST EAX, 1 shl 21
JNZ @@1
INC [ I ]
@@1:
end;
if I = 0 then Exit; asm MOV EAX, 1
PUSH EDX
PUSH EBX
PUSH ECX
DB $0F, $A2
MOV [ I ], EDX POP ECX
POP EBX
POP EDX
end;
if (I and (1 shl 23)) <> 0 then
Result := true;
end;
-
procedure BitmapAntialias4X(SrcBitmap, DstBitmap: TBitmap);
type AGRBQuad = array [0..0] of TRGBQuad;
PAGRBQuad = ^AGRBQuad;
var yDest: integer;
xDest: integer;
xSrc: integer;
i: integer;
R: integer;
G: integer;
B: integer;
rowDest: PAGRBQuad;
rowSrc: array [0..3] of PAGRBQuad;
_rowSrc: PAGRBQuad;
SrcBits: DWORD;
DstBits: DWORD;
dHeight: DWORD;
dWidth: DWORD;
Delta: DWORD;
begin
if CPUisMMX then begin
SrcBits := DWORD(DIBBits(SrcBitmap));
DstBits := DWORD(DIBBits(DstBitmap));
dHeight := DstBitmap.Height;
dWidth := DstBitmap.Width;
Delta := ScanLineSize(SrcBitmap);
asm
pushad
mov esi, SrcBits
mov edi, DstBits
db $0f, $ef, $d2
mov eax, dHeight
@LM1: push eax
mov eax, dWidth
@LM2: mov ecx, esi
db $0f, $6e, $09
db $0f, $60, $ca
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $08
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $0c
db $0f, $60, $da
db $0f, $dd, $cb
add ecx, Delta
db $0f, $6e, $19
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $08
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $0c
db $0f, $60, $da
db $0f, $dd, $cb
add ecx, Delta
db $0f, $6e, $19
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $08
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $0c
db $0f, $60, $da
db $0f, $dd, $cb
add ecx, Delta
db $0f, $6e, $19
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $08
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $0c
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $71, $d1, $04
db $0f, $67, $ca
db $0f, $7e, $0f
add edi, 4
add esi, 16
sub eax, 1
jnz @LM2
mov ecx, Delta
lea esi, [esi + ecx*2]
add esi, ecx
pop eax
sub eax, 1
jnz @LM1
db $0f, $77
popad
end;
end else
for yDest := 0 to DstBitmap.Height -1 do begin
rowDest := DstBitmap.ScanLine[yDest];
for i := 0 to 3 do
rowSrc[i] := SrcBitmap.ScanLine[yDest*4+i];
for xDest := 0 to DstBitmap.Width-1 do begin
xSrc := xDest*4;
R:=0; G:=0; B:=0;
for i := 0 to 3 do begin
_rowSrc := rowSrc[i];
R:= R+_rowSrc[xSrc+0].rgbRed
+ _rowSrc[xSrc+1].rgbRed
+ _rowSrc[xSrc+2].rgbRed
+ _rowSrc[xSrc+3].rgbRed;
G:= G+_rowSrc[xSrc+0].rgbGreen
+ _rowSrc[xSrc+1].rgbGreen
+ _rowSrc[xSrc+2].rgbGreen
+ _rowSrc[xSrc+3].rgbGreen;
B:= B+_rowSrc[xSrc+0].rgbBlue
+ _rowSrc[xSrc+1].rgbBlue
+ _rowSrc[xSrc+2].rgbBlue
+ _rowSrc[xSrc+3].rgbBlue;
end;
DWORD(rowDest[xDest]) := ((R and $0ff0) shl 12) or ((G and $0ff0) shl 4) or (B shr 4);
end;
end;
end;
-
procedure BitmapAntialias2X(SrcBitmap, DstBitmap: TBitmap);
type AGRBQuad = array [0..0] of TRGBQuad;
PAGRBQuad = ^AGRBQuad;
var yDest: integer;
xDest: integer;
xSrc: integer;
i: integer;
R: integer;
G: integer;
B: integer;
rowDest: PAGRBQuad;
rowSrc: array [0..3] of PAGRBQuad;
_rowSrc: PAGRBQuad;
SrcBits: DWORD;
DstBits: DWORD;
dHeight: DWORD;
dWidth: DWORD;
Delta: DWORD;
begin
if CPUisMMX then begin
SrcBits := DWORD(DIBBits(SrcBitmap));
DstBits := DWORD(DIBBits(DstBitmap));
dHeight := DstBitmap.Height;
dWidth := DstBitmap.Width;
Delta := ScanLineSize(SrcBitmap);
asm
pushad
mov esi, SrcBits
mov edi, DstBits
db $0f, $ef, $d2
mov eax, dHeight
@LM1: push eax
mov eax, dWidth
@LM2: mov ecx, esi
db $0f, $6e, $09
db $0f, $60, $ca
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
add ecx, Delta
db $0f, $6e, $19
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $71, $d1, $02
db $0f, $67, $ca
db $0f, $7e, $0f
add edi, 4
add esi, 8
sub eax, 1
jnz @LM2
add esi, Delta
pop eax
sub eax, 1
jnz @LM1
db $0f, $77
popad
end;
end else
for yDest := 0 to DstBitmap.Height -1 do begin
rowDest := DstBitmap.ScanLine[yDest];
for i := 0 to 1 do
rowSrc[i] := SrcBitmap.ScanLine[yDest*2+i];
for xDest := 0 to DstBitmap.Width-1 do begin
xSrc := xDest*2;
R:=0; G:=0; B:=0;
for i := 0 to 1 do begin
_rowSrc := rowSrc[i];
R:= R+_rowSrc[xSrc+0].rgbRed
+ _rowSrc[xSrc+1].rgbRed;
G:= G+_rowSrc[xSrc+0].rgbGreen
+ _rowSrc[xSrc+1].rgbGreen;
B:= B+_rowSrc[xSrc+0].rgbBlue
+ _rowSrc[xSrc+1].rgbBlue;
end;
DWORD(rowDest[xDest]) := ((R and $03fc) shl 14) or ((G and $03fc) shl 6) or (B shr 2);
end;
end;
end;
procedure BlendBitmaps(var DestBitmap, FromBitmap, ToBitmap: TBitmap; Factor: Integer;
ClipRect:TRect);
type AGRBQuad = array [0..0] of TRGBQuad;
PAGRBQuad = ^AGRBQuad;
var Factor2: byte;
i, j: integer;
DestRow: PAGRBQuad;
FromRow: PAGRBQuad;
ToRow: PAGRBQuad;
FromDibBits: DWORD;
ToDibBits: DWORD;
DestDibBits: DWORD;
_Width: integer;
_Height: integer;
_Right: integer;
_Top: DWORD;
begin
if CPUisMMX then begin
_Top := FromBitmap.Width * 4 * ClipRect.Top + ClipRect.Left * 4;
FromDibBits := DWORD(DIBBits(FromBitmap)) + _Top;
ToDibBits := DWORD(DIBBits(ToBitmap)) + _Top;
DestDibBits := DWORD(DIBBits(DestBitmap)) + _Top;
_Width := ClipRect.Right - ClipRect.Left;
_Height := ClipRect.Bottom - ClipRect.Top;
_Right := (FromBitmap.Width - ClipRect.Right + ClipRect.Left) * 4;
asm
mov edx, Factor
mov dh, dl
mov ax, dx
shl eax, 16
mov ax, dx
mov esi, FromDibBits
mov edi, ToDibBits
mov edx, DestDibBits
db $0f, $ef, $d2
db $0f, $6e, $d8
db $0f, $60, $da
mov eax, $00404040
db $0f, $6e, $e0
db $0f, $60, $e2
db $0f, $f9, $e3
mov ecx, _Height
@LM1:
mov ebx, _Width
@LM2:
db $0f, $6e, $06
db $0f, $6e, $0f
db $0f, $60, $c2
db $0f, $60, $ca
db $0f, $d5, $c4
db $0f, $d5, $cb
db $0f, $dd, $c8
db $0f, $71, $d1, $06
db $0f, $67, $ca
db $0f, $7e, $0a
add esi, 4
add edi, 4
add edx, 4
sub ebx, 1
jnz @LM2
add esi, _Right
add edi, _Right
add edx, _Right
sub ecx, 1
jnz @LM1
db $0f, $77
end
end else begin
Factor2 := 64-Factor;
for i := ClipRect.Top to ClipRect.Bottom-1 do begin
DestRow := DestBitmap.ScanLine[i];
FromRow := FromBitmap.ScanLine[i];
ToRow := ToBitmap.ScanLine[i];
for j := ClipRect.Left to (ClipRect.Right-1) do begin
DestRow[j].rgbBlue := ((FromRow[j].rgbBlue*Factor2)
+ (ToRow[j].rgbBlue*Factor)) shr 6;
DestRow[j].rgbGreen := ((FromRow[j].rgbGreen*Factor2)
+ (ToRow[j].rgbGreen*Factor)) shr 6;
DestRow[j].rgbRed := ((FromRow[j].rgbRed*Factor2)
+ (ToRow[j].rgbRed*Factor)) shr 6;
end;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var t,i : DWORD;
begin
Image1.Picture.bitmap.LoadFromFile('c:\52a.bmp');
Image1.Picture.Bitmap.PixelFormat := pf32Bit;
Image1.Picture.Bitmap.HandleType := bmDIB;
Image2.Picture.Bitmap := NewDIBBitmap(512, 384, pf32bit);
T := GetTickCount();
for i := 0 to 999 do begin
BitmapAntialias2x(Image1.Picture.Bitmap, Image2.Picture.Bitmap);
end;
ShowMessage(inttostr(Gettickcount-t));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
BMP1: TFastBMP;
BMP2: TFastBMP;
t,i : DWORD;
begin
BMP1 := TFastBMP.Create;
BMP1.LoadFromFile('c:\52a.bmp');
BMP2 := TFastBMP.Create;
BMP2.SetSize(512, 384);
T := GetTickCount();
for i := 0 to 999 do begin
BMP1.SmoothResize(BMP2);
end;
ShowMessage(inttostr(Gettickcount-t));
BMP2.Draw(image2.Canvas.Handle, 0, 0);
end;
initialization
CPUisMMX := FALSE;
CPUisMMX := isMMX();
end.
-
FastBMP — 4000 мой вариант — 1400
Естественно, что SmoothResize более универсальная…
-
> homm ©
извращенец %)
-
в хорошем смысле:)
-
> homm © (14.10.07 14:47) [15]
Ну и че такое за FastBMP?
-
> > homm ©
procedure TForm1.Button2Click(Sender: TObject);
var
BMP1: TFastDIB;
BMP2: TFastDIB;
t,i : DWORD;
begin
BMP1 := TFastDIB.Create;
BMP1.LoadFromFile('c:\1.bmp');
BMP2 := TFastDIB.Create;
BMP2.SetSize(640, 482, 32);
T := GetTickCount();
for i := 0 to 999 do begin
FastResize(BMP1,BMP2);
end;
ShowMessage(inttostr(Gettickcount-t));
BMP2.Draw(image2.Canvas.Handle, 0, 0);
end;
Результат 1390 даже для более большой картинки чем у тебя. Твой же код вообще не рабочий.
-
-
> [19] DVM © (14.10.07 19:01) > Твой же код вообще не рабочий.
О_о Да ну?
-
> О_о Да ну?
вот представь себе Access Violation
-
За ссылку сенкс, сам только ту версию нашел, что протестировал.
> Результат 1390 даже для более большой картинки чем у тебя.
И какое у твоей разрешение?
-
> [22] DVM © (14.10.07 19:40) > вот представь себе Access Violation
Ты не повар :)
-
> И какое у твоей разрешение?
а у твоей? :)
> Ты не повар :)
Все то, что ты написал выше вставлено в форму с двумя кнопками и двумя Image. При нажатии на кнопку 1 - AV. Delphi 7. Искать причину мне неохота.
-
> [25] DVM © (14.10.07 19:44) > Искать причину мне неохота.
Причина в том. что разрешение должно быть у картинки 1024*768, надо пологать ?
-
> И какое у твоей разрешение?
800 на 600
-
> [27] DVM © (14.10.07 19:44)
В серьез полагаешь, что 800*600 больше, чем 1024*768? :)
У меня получилось 844 для 1024*768, НО ты чувствуешь разницу между «FastResize» и «Качественное масштабирование» ??? Я думаю имеется виду как минимум, не хуже билинейного.
-
> Причина в том. что разрешение должно быть у картинки 1024*768, > надо пологать ?
Поменял на 1024*768*32 - теперь Stream Read Error
У FastDIB результат почти не изменился - 1400 стало при перегоне в 640*482 Если перегонять в 512 * 384, то результат вообще 1047
-
> ты чувствуешь разницу между «FastResize» и «Качественное > масштабирование» ??? Я думаю имеется виду как минимум, не > хуже билинейного.
И какой метод интерполяции у тебя?
-
for i := 0 to 999 do begin
Bilinear24(BMP1,BMP2);
end; Имеем 4280 :-Р
-
> [30] DVM © (14.10.07 19:51) > И какой метод интерполяции у тебя?
Билинейный.
-
> Поменял на 1024*768*32 - теперь Stream Read Error
НЕ ВЕРЮ! Image1.Picture.bitmap.LoadFromFile('c:\52a.bmp');
Image1.Picture.Bitmap.PixelFormat := pf32Bit;
Image1.Picture.Bitmap.HandleType := bmDIB;
Image2.Picture.Bitmap := NewDIBBitmap(512, 384, pf32bit);
T := GetTickCount();
for i := 0 to 999 do begin
BitmapAntialias2x(Image1.Picture.Bitmap, Image2.Picture.Bitmap);
end;
Все ли так? Разрешение точно 1024*768 ?
-
> НЕ ВЕРЮ!
procedure TForm1.Button1Click(Sender: TObject);
var t,i : DWORD;
begin
Image1.Picture.bitmap.LoadFromFile('c:\1.bmp');
Image1.Picture.Bitmap.PixelFormat := pf32Bit;
Image1.Picture.Bitmap.HandleType := bmDIB;
Image2.Picture.Bitmap := NewDIBBitmap(512, 384, pf32bit);
T := GetTickCount();
for i := 0 to 999 do begin
BitmapAntialias2x(Image1.Picture.Bitmap, Image2.Picture.Bitmap);
end;
ShowMessage(inttostr(Gettickcount-t));
end;
-
> homm ©
А так ты в 2 раза уменьшаешь! Я то сразу и не заметил.
-
-
Блин, я чуть было не стал качать :) 3 метра, ага? Нет уж :)
Выбрось FastDIB, уж по крайней мере билинейную интерпляцию он нифига не делает. Можеь проверить результат, полученый в фотошопе при уменьшении в 4 раза.
-
Для пущей наглядности предлагаю сравнить как один слой на другом, выставив для верхнего режим Difference.
-
> Выбрось FastDIB, уж по крайней мере билинейную интерпляцию > он нифига не делает
Делает. SmoothResize(BMP1,BMP2, rfBilinear);
-
> homm ©
Сравнивать в данном случае некорректно. Функции FastDIB рассчитаны на произвольный размер, а не на уменьшение в 2 раза.
-
Действительно, делает :) 109 секунд делает :)
-
А у меня за одну :)
-
> Действительно, делает :) > 109 секунд делает :)
че то тут не так
-
> [40] DVM © (14.10.07 20:10) > Сравнивать в данном случае некорректно.
Я об этом сразу сказал, просто ты кое кто считает, что я «зря фразами кидаюсь» ;)
-
> [43] DVM © (14.10.07 20:13) > че то тут не так
Я итебе скажу, что тцт не так :) procedure SmoothResize24(Src,Dst:TFastDIB;Filter:TResizeFilter);
if s<1 then pw^.w:=Round(f((m-pw^.pos)*s)*s*$10000) Вот эта вот букавка F — это вызов функции… Для каждого пикселя… естествеено это жопа.
-
> homm © (14.10.07 20:15) [45]
Точно.
-
> homm © (14.10.07 20:07) [38] > Для пущей наглядности предлагаю сравнить как один слой на > другом, выставив для верхнего режим Difference.
Кстати все ок. 1 к 1 как в фотошопе.
-
5200 мсек занимет 1000 масштабирований с билинейной фильтрацией
-
procedure TForm1.Button2Click(Sender: TObject);
var
BMP1: TFastDIB;
BMP2: TFastDIB;
t,i : DWORD;
begin
BMP1 := TFastDIB.Create;
BMP1.LoadFromFile('c:\1.bmp');
BMP2 := TFastDIB.Create;
BMP2.SetSize(512, 384, 32);
T := GetTickCount();
for i := 0 to 999 do begin
Bilinear32(BMP1,BMP2);
end;
ShowMessage(inttostr(Gettickcount-t));
BMP2.Draw(image2.Canvas.Handle, 0, 0);
BMP2.SaveToFile('C:\2.BMP');
end;
Файл 2 и полученный в фотошопе после масштабирования с билинейной фильтрацие идентичны. Так что не надо гнать на FastDIB. :) Если учесть, что это результат для произвольных размеров, а не для 2 или 4, то он не хуже чем твой. Следовательно FastDIB обогнать все же сложно.
-
> [49] DVM © (14.10.07 21:20) > Файл 2 и полученный в фотошопе после масштабирования с билинейной > фильтрацие идентичны.
> [37] homm © (14.10.07 20:06) > Можеь проверить результат, полученый в фотошопе при уменьшении в ЧЕТЫРЕ раза.
-
В том, и штука, что он берет исходный пиксель и 2 соседних, результат верен только для 2-х кратного и менее-кратного ументшения :)
-
> > Можеь проверить результат, полученый в фотошопе при уменьшении > в ЧЕТЫРЕ раза.
Все ок. Проверь сам. Может ты неправильно фильтрацию в фотошопе случайно выбрал?
-
уменьшил вообще до 100х100 , т.е. с изменением пропорций. Результат идентичен фотошоповскому. Увеличил до 1000х1000 - тоже идентично.
-
-
> 3) Их разность :)
а сдвинуть слои не пробовал?
-
> homm © (14.10.07 21:50) [54]
у тебя картинка какой цветности? 24 или 32? Функцию FastDIB берешь какую?
я работаю с картинкой из папки мои рисунки (Закат.jpg), которую я фотошопом увеличил до 1024 на 768 32 бит цвет и сохранил в BMP.
-
Куда сдвигать, они разные!! Приглядись к первой и второй картинке, они очень разные!
-
> [56] DVM © (14.10.07 21:53) > у тебя картинка какой цветности? 24 или 32?
32, Bilinear32
> Закат.jpg Ты бы еше квадрат тупо красным залал…
-
> homm © (14.10.07 21:50) [54]
осторожно, у меня рядом дети сидят %)
-
> Ты бы еше квадрат тупо красным залал…
Какая разница, нормальный рисунок. Ну взял я другую фотку все ок
-
-
-
Итак, проведем эксперимент. 1) Берем исходную фотку: http://dvmuratov.narod.ru/1.bmp (3 мб) 2) Натравливаем на фотку этот код:
procedure TForm1.Button2Click(Sender: TObject);
var
BMP1: TFastDIB;
BMP2: TFastDIB;
t,i : DWORD;
begin
BMP1 := TFastDIB.Create;
BMP1.LoadFromFile('c:\1.bmp');
BMP2 := TFastDIB.Create;
BMP2.SetSize(1000, 1000, 32);
T := GetTickCount();
for i := 0 to 0 do begin
Bilinear32(BMP1,BMP2);
end;
ShowMessage(inttostr(Gettickcount-t));
BMP2.Draw(image2.Canvas.Handle, 0, 0);
BMP2.SaveToFile('C:\2.BMP');
end;
2) Открываем файл 1 в фотошопе (версия 8) 3) Открываем файл 2 в фотошопе 4) Меняем размеры первого файла на 1000*1000 с билинейной фильтрацией без сохранения пропорций. 5) Перетаскиваем на первый файл слой из вторгго файла 6) делаем сравнение У меня абсолютное совпадение т.е. черный квадрат
-
> [63] DVM © (14.10.07 22:04) > Меняем размеры первого файла на 1000*1000
Стоп, откуда такая цифра???
> [53] DVM © (14.10.07 21:31) > уменьшил вообще до 100х100
-
[51] прочти.
-
> homm ©
Саш, ей богу у меня одинаковые, я уж другую фотку взял с разными цветами и бабочкой.
-
> Стоп, откуда такая цифра???
от балды
-
сравни, 100*100, как ты сказал, или уменьшеную в 4, как я сказал, не береи от балды! :)
-
> homm ©
Получил я разницу. Но она появляется далеко не на всех изображениях и не при любых размерах.
-
Н авсех изображениях (кроме залитого ккрасным цветом квадрата) на разрешениях, которые я уже оговорил, и даже причину, по которой эти ограничения получаются, тоже сказал.
-
> homm ©
кстати, а с чего ты вообще взял, что картинки должны быть абсолютно идентичны. Алгоритмы отличаются. Но не настолько, чтобы одна картинка была заметно хуже другой.
Вот я взял для примера две программы одна Photoshop, другая Macromedia FireWorks (теперь тоже адобе). Я думаю, ты не будешь спорить с реализацией алгоритмов сглаживания у этих компаний. Так вот, для одной и той же картинки для размера 100*100 они дают разные результаты. Причем разница между ними даже больше, чем у FastDIB и фотошопа. Так что это не показатель.
-
долго ругаться будете? :) у ветки и так мега положительная полезность :)
homm © а есть на асме блитинг (с альфой или просто "прозрачный цвет") двух битмапов (либо просто массивов)?
-
-
> [71] DVM © (14.10.07 22:35) > Но не настолько, чтобы одна картинка была заметно хуже другой.
А он хуже ;) > Причем разница между ними даже больше, чем у FastDIB и фотошопа.
Ты уверен, что в Macromedia FireWorks было именно билинейное сглаживание? > [72] antonn © (14.10.07 22:56) > а есть на асме блитинг
У меня нет, хотя пора бы уже :) > Кстати, твой вариант у меня так и не заработал. http://homm86.narod.ru/files/resize.rar 130 kb.
-
> Ты уверен, что в Macromedia FireWorks было именно билинейное > сглаживание?
там явно выбирается при сохранении, как и в фотошопе
-
-
> [76] DVM © (15.10.07 00:15) > че-то не скачивается
Счас должно.
-
Так что выяснили то, что можно реализовать 2-хкратное уменьшение быстрее, чем универсальное в FastDIB?
-
> [78] sdubaruhnul © (15.10.07 15:16) > Так что выяснили то, что можно реализовать 2-хкратное уменьшение > быстрее, чем универсальное в FastDIB?
Да. 2-х, 4-х, 8-и, сколько угодно кратное.
-
В FastDIB вообще нет функций для быстрого уменьшения в 2xN раз. Там есть функции для такого увеличения. Только они, вроде бы без билинейной фильтрации. Но можно дописать.
Меня больше теперь интересует, результаты алгоритмов билинейной фильтрации должны быть одинаковы или нет?
-
> [80] DVM © (15.10.07 16:15) > Меня больше теперь интересует, результаты алгоритмов билинейной > фильтрации должны быть одинаковы или нет?
Должны. Ты же сам видишь, то, что получается в FastDIB, или в Pain.NET — кака полная.
-
> Ты же сам видишь, то, что получается в FastDIB, или в Pain. > NET — кака полная.
Почему у всех, даже известных и вызывающих доверие программ они разные?
Почему у Photoshop, Macromedia Fireworks, Intel OpenCV разные результаты? И у кого из них правильный?
-
Ок, пусть будут разные, но не такие говенные как у Pain.NET и FastDIB.
Можешь сделать общий png, на котором бы были представлены уменьшеные в 4 раза в Photoshop, Macromedia Fireworks, Intel OpenCV? у меня ни второго не третьего.
-
> [82] DVM © (15.10.07 16:20) > И у кого из них правильный?
У меня. И я кстати, не шучу. Суть метода — сложить и поделить. Т.к. у меня довольно частный случай в алгоритмах, определить что именно нужно сложить и на что поделить — проще всего.
-
> Можешь сделать общий png,
Сделаю. Но вечером, на работе у меня вообще ничего из перечисленного нет.
-
В FastDIB вообще нет функций для быстрого уменьшения в 2xN раз.Уменьшение в 2 раза: http://sapersky.narod.ru/files/FastSizeEx.rarТакже там имеется вариант SmoothResize, работающий примерно в 2 раза быстрее. Но SmoothResize - всё-таки скорее качественная, чем быстрая фильтрация. Сама функция рассчитана в большей степени на сложные фильтры вроде Lancros (и что немаловажно - на фильтры РАЗНОЙ длины, что вынуждает крутить "внутренний" цикл для каждого пикселя). А Bilinear, ИМХО, это неплохой компромисс между скоростью и качеством. Если кому-то не нравится - не используйте, нам больше достанется :)
-
Кстати, непонятно, какой смысл сравнивать с Photoshop. Он рекордов скорости ставить не собирается и может применить медленный, но качественный метод вроде SmoothResize c rfBilinear. Сравнивать нужно с кодом homm, который работает с любым коэффициентом масштабирования, быстрее Bilinear и даёт более качественный результат. Кстати, где он? Я что-то пропустил? :)
-
> [87] Sapersky (15.10.07 19:27) > Сравнивать нужно с кодом homm, который работает с любым > коэффициентом масштабирования, быстрее Bilinear и даёт > более качественный результат.
Еше не написан такой.
> Также там имеется вариант SmoothResize, работающий примерно > в 2 раза быстрее. Но SmoothResize - всё-таки скорее качественная, > чем быстрая фильтрация.
Какое-то противоречие.
> Кстати, непонятно, какой смысл сравнивать с Photoshop. Он > рекордов скорости ставить не собирается и может применить > медленный, но качественный метод вроде SmoothResize c rfBilinear.
Он и применяет качественный фильтр, результат использования которого равен моему результату, и он же, собственно и есть самый настоящий билинеар.
-
-
> [89] DVM © (15.10.07 21:44) > 3) Разница есть (небольшая но есть)
Ну это уже небольшие нюансы в построении… По скрину видно, что строится верно, как минимум не хуже билинейного.
-
> [72] antonn © (14.10.07 22:56) > а есть на асме блитинг (с альфой или просто "прозрачный > цвет") двух битмапов (либо просто массивов)?
Наваял без асма пока. Поучается примерно 100 кадров в секунду для 1024*768. procedure TForm1.Button1Click(Sender: TObject);
type
ARGBQuad = array [0..0] of TRGBQuad;
PARGBQuad = ^ARGBQuad;
AByte = array [0..0] of Byte;
PAByte = ^AByte;
var
BMP1: TBitmap;
BMP2: TBitmap;
SL1, SL2: PARGBQuad;
V1, V2: TRGBQuad;
R: ^TRGBQuad;
i, j: Integer;
A_1, A: Integer;
Delta: DWORD;
T: DWORD;
begin
BMP1 := TBitmap.Create;
BMP1.LoadFromFile('C:\1.bmp');
BMP2 := TBitmap.Create;
BMP2.LoadFromFile('C:\2.bmp');
T := GetTickCount;
SL1 := BMP1.ScanLine[0];
SL2 := BMP2.ScanLine[0];
Delta := DWORD(BMP1.ScanLine[1]) - DWORD(SL1);
for i := 0 to BMP1.Height-1 do begin
for j := 0 to BMP1.Width-1 do begin
V1 := SL1[j];
V2 := SL2[j];
A := V2.rgbReserved;
A_1 := 255-V2.rgbReserved;
R := @SL1[j];
R.rgbBlue := (V2.rgbBlue*A_1+V1.rgbBlue*A) shr 8;
R.rgbGreen := (V2.rgbGreen*A_1+V1.rgbGreen*A) shr 8;
R.rgbRed := (V2.rgbRed*A_1+V1.rgbRed*A) shr 8;
end;
SL1 := Pointer(DWORD(SL1) + Delta);
SL2 := Pointer(DWORD(SL2) + Delta);
end;
ShowMessage(IntToStr(GetTickCount - T));
Image1.Canvas.StretchDraw(Rect(0, 0, 1024, 768), BMP1);
BMP1.Free;
BMP2.Free;
end; Обе картинки болжны быть 32-х битные, причем вторая должна в резервном бите содержать альфаканал (легко сделать в фотошопе).
-
я наверное щас совсем оборзею, но можно попросить о помощи? :) битмапы храню в массиве dword (так по идее доступ еще быстрее, и почка для асма:)) немножко велосипеда: const
MaxBTCount = MaxInt div SizeOf(dword);
type
BTElement = dword;
TBTArray = array[0..MaxBTCount-1] of BTElement;
PxlByte = array [0..2] of byte;
LongAS = packed record
DW: array [0..3] of dword;
end;
pPRBT= ^TPRBT; TPRBT = record
b1,b2,b3,b4:dword;
end;
pPRBD= ^TPRBD; TPRBD = record
b1,b2:dword;
end;
TBT = Class
private
procedure setarrays(x,y:integer);
public
DIBWidth : integer;
DIBHeight : integer;
P: ^TBTArray;
constructor Create;
destructor Destroy; override;
procedure loadbitmap(bitmap:tbitmap);
procedure savebitmap2file(filename:string);
procedure set_widthheight(w,h:integer);
end;
implementation
constructor TBT.Create;
begin
inherited;
DIBWidth:=0;
DIBHeight:=0;
end;
destructor TBT.Destroy;
begin
FreeMem(P, DIBWidth*DIBHeight*SizeOf(BTElement));
inherited;
end;
procedure TBT.setarrays(x,y:integer);
begin
FreeMem(P, DIBWidth*DIBHeight*SizeOf(BTElement));
DIBWidth:=x;
DIBHeight:=y;
P:=AllocMem(DIBWidth*DIBHeight * SizeOf(BTElement));
end;
procedure TBT.set_widthheight(w,h:integer);
begin
setarrays(w,h);
end;
procedure TBT.loadbitmap(bitmap:tbitmap);
var x,y,cou,n: Integer; Row2:PRGBAArray;
begin
cou:=0;
setarrays(bitmap.Width,bitmap.Height);
for Y:=0 to bitmap.Height-1 do begin
Row2:=bitmap.ScanLine[y];
for x:=0 to bitmap.Width-1 do begin
if((Row2[x].rgbRed=255) and (Row2[x].rgbGreen=0) and (Row2[x].rgbBlue=0)) then
Row2[x].rgbReserved:=0 else
Row2[x].rgbReserved:=255;
P^[ y*DIBWidth+x ]:=(Row2[x].rgbRed or (Row2[x].rgbGreen shl 8) or (Row2[x].rgbBlue shl 16) or (Row2[x].rgbReserved shl 24));
end;
end;
end;
procedure TBT.savebitmap2file(filename:string);
var bb:tbitmap; x,y,cou: Integer; Row2:PRGBAArray; fd:dword;
begin
bb:=tbitmap.Create;
try
bb.PixelFormat:=pf32bit;
bb.Width:=DIBWidth;
bb.Height:=DIBHeight;
for Y:=0 to bb.Height-1 do begin
Row2:=bb.ScanLine[y];
for x:=0 to bb.Width-1 do begin
fd:=P^[ y*DIBWidth+x ];
Row2[x].rgbBlue:=Byte(fd shr 16);
Row2[x].rgbGreen:=Byte(fd shr 8);
Row2[x].rgbRed:=Byte(fd);
Row2[x].rgbReserved:=Byte(fd shr 24);
end;
end;
bb.SaveToFile(filename);
finally
bb.Free;
end;
end;
небольшой класс, грузящий битмап в массив и сохранающий как битмап. Оптимизаций загрузки/сохранения не делал, потом. Так вот, в асме я дуб, но хочется быстрее, выше и сильнее, особенно если с ММХ/SSE и тп:) кстати, код для уменьшения:) procedure antialias_x2(var BTSourc,BTDest:TBT);
var x,y,cou,num,i,cxi,cx,wi,hi: Integer; Row2:PRGBAArray; fd:dword;
y1,y2,totr,totg,totb,tota:integer;
yy1,yy2:pPRBD;
wii,hii:integer;
begin
wii:=BTSourc.DIBWidth div 2;
hii:=BTSourc.DIBHeight div 2;
for Y:=0 to hii-1 do begin
y1:=y*2*BTSourc.DIBWidth;
y2:=y1+BTSourc.DIBWidth;
for x:=0 to wii-1 do begin
cx:=x*2;
yy1:=pPRBD(@(BTSourc.P^[ y1+cx ]));
yy2:=pPRBD(@(BTSourc.p^[ y2+cx ]));
totb:=LongRec(yy1.b1).Bytes[2] + LongRec(yy2.b1).Bytes[2] ;
totb:=totb+LongRec(yy1.b2).Bytes[2] + LongRec(yy2.b2).Bytes[2] ;
totg:=LongRec(yy1.b1).Bytes[1] + LongRec(yy2.b1).Bytes[1] ;
totg:=totg+LongRec(yy1.b2).Bytes[1] + LongRec(yy2.b2).Bytes[1] ;
totr:=LongRec(yy1.b1).Bytes[0] + LongRec(yy2.b1).Bytes[0] ;
totr:=totr+LongRec(yy1.b2).Bytes[0] + LongRec(yy2.b2).Bytes[0];
tota:=LongRec(yy1.b1).Bytes[3] + LongRec(yy2.b1).Bytes[3] ;
tota:=tota+LongRec(yy1.b2).Bytes[3] + LongRec(yy2.b2).Bytes[3] ;
BTDest.P^[ y*wii+x ]:=((totr Shr 2) or ((totg Shr 2) shl 8) or ((totb Shr 2) shl 16)or ((tota Shr 2) shl 24));
end;
end;
end; альфаблитинг (с проверками на границы и произольным началом вывода): procedure AlfaBliting(var BTPic,BTBack:TBT; _x,_y:integer);
var x, y,xd,yd,yyd: Integer; _r,_b,_g:integer;
w_out,h_out,tmp,x_cor,y_cor,x_corS,y_corS: Integer;
_d,_dd:double;
fd,fs,fr:dword;
begin
w_out:=BTBack.DIBWidth;
h_out:=BTBack.DIBHeight;
if (_x)>w_out-1 then exit; if (_x+w_out)<0 then exit;
if (_y)>h_out-1 then exit; if (_y+h_out)<0 then exit;
if _x<0 then x_corS:=abs(_x) else x_corS:=0;
if _y<0 then y_corS:=abs(_y) else y_corS:=0;
if (_x+BTPic.DIBWidth)>w_out then x_cor:=_x+BTPic.DIBWidth-w_out else x_cor:=0;
if (_y+BTPic.DIBHeight)>h_out then y_cor:=_y+BTPic.DIBHeight-h_out else y_cor:=0;
y_cor:=BTPic.DIBHeight-1-y_cor;
tmp:=BTPic.DIBWidth-1-x_cor; _dd:=(100/255)/100;
for y:=y_corS to y_cor do begin
yd:=y*BTPic.DIBWidth;
yyd:=(y+_y)*BTBack.DIBWidth;
for x:=x_corS to tmp do begin
fd:=BTPic.P^[ yd+x ];
if(LongRec(fd).Bytes[3]>0)then begin
xd:=x+_x;
fs:=BTBack.P^[ yyd +xd ];
_d:=LongRec(fd).Bytes[3]*_dd;
_r:= LongRec(fs).Bytes[0]+round((LongRec(fd).Bytes[0]-LongRec(fs).Bytes[0])*_d);
if _r>255 then _r:=255 else if _r<0 then _r:=0;
_g:= LongRec(fs).Bytes[1]+round((LongRec(fd).Bytes[1]-LongRec(fs).Bytes[1])*_d);
if _g>255 then _g:=255 else if _g<0 then _g:=0;
_b:= LongRec(fs).Bytes[2]+round((LongRec(fd).Bytes[2]-LongRec(fs).Bytes[2])*_d);
if _b>255 then _b:=255 else if _b<0 then _b:=0;
if LongRec(fs).Bytes[3]<LongRec(fd).Bytes[3] then
BTBack.P^[ yyd +xd ]:=(_r or (_g shl 8) or (_b shl 16)or (LongRec(fd).Bytes[3] shl 24))
else
BTBack.P^[ yyd +xd ]:=(_r or (_g shl 8) or (_b shl 16)or (LongRec(fs).Bytes[3] shl 24));
end;
end; end;
end; и "обычный" блит с "прозрачным каналом" (прозрачный канал - это альфа с значением 0): procedure Bliting(var BTPic,BTBack:TBT; _x,_y:integer);
var x, y,yd,yyd: Integer;
w_out,h_out,tmp,x_cor,y_cor,x_corS,y_corS: Integer;
begin
w_out:=BTBack.DIBWidth;
h_out:=BTBack.DIBHeight;
if (_x)>w_out-1 then exit; if (_x+w_out)<0 then exit;
if (_y)>h_out-1 then exit; if (_y+h_out)<0 then exit;
if _x<0 then x_corS:=abs(_x) else x_corS:=0;
if _y<0 then y_corS:=abs(_y) else y_corS:=0;
if (_x+BTPic.DIBWidth)>w_out then x_cor:=_x+BTPic.DIBWidth-w_out else x_cor:=0;
if (_y+BTPic.DIBHeight)>h_out then y_cor:=_y+BTPic.DIBHeight-h_out else y_cor:=0;
y_cor:=BTPic.DIBHeight-1-y_cor;
tmp:=BTPic.DIBWidth-1-x_cor;
for y:=y_corS to y_cor do begin
yd:=y*BTPic.DIBWidth;
yyd:=(y+_y)*BTBack.DIBWidth;
for x:=x_corS to tmp do begin
if(LongRec(BTPic.P^[ yd+x ]).Bytes[3]>0)then
BTBack.P^[ yyd+x+_x ]:=BTPic.P^[ yd+x ];
end;
end;
end; так вот, я понимаю, что выгрузил тут много всякого, не поможите оптимизировать? :)
-
Еше не написан такой.
Так вот сначала напиши, а потом советуй выбросить FastDIB.
> Также там имеется вариант SmoothResize, работающий примерно > в 2 раза быстрее. Но SmoothResize - всё-таки скорее качественная, > чем быстрая фильтрация.
Какое-то противоречие.
Я имел в виду - быстрее, чем тот вариант SmoothResize, который в составе FastLib 3.9.9. Но медленнее, чем Bilinear.
> Кстати, непонятно, какой смысл сравнивать с Photoshop. Он > рекордов скорости ставить не собирается и может применить > медленный, но качественный метод вроде SmoothResize c rfBilinear.
Он и применяет качественный фильтр, результат использования которого равен моему результату, и он же, собственно и есть самый настоящий билинеар.
Против Фотошопа FastLib'у есть что выставить - у SmoothResize качество ничуть не хуже, и скорость скорее всего тоже. Но Bilinear - это специально оптимизированная на скорость (ценой некоторой потери качества) функция. Поэтому не стоит сравнивать её с меланхоличным Фотошопом. С BitmapAntialias2X тоже не стоит, уж неловко напоминать почему. С чем стоит - уже писал :)
Теперь о том, почему совмешение скорости с качеством маловероятно. Причина высокого качества, которое даёт SmoothResize - переменная длина фильтра, которая зависит не только от типа фильтра, но и от коэффициента масштабирования. И эта же переменная (и бОльшая по величине) длина, как я уже писал в [86] (а не "вызов f для каждого пикселя") - причина тормознутости функции. Ну и в какой-то степени обработка в 2 прохода (приходится создавать промежуточный буфер). Т.е. можно, конечно, создать некий гибрид SmoothResize/Bilinear, и он будет даже несколько быстрее первой (за счёт фиксированной функции, обработки в 1 проход и т.п.), но до 2-й по скорости всё равно не дотянет. Не проще ли тогда господам эстетам просто вызывать SmoothResize при K < 0.5, а в остальных случаях Bilinear?
-
antonn © (16.10.07 01:07) [92]
См. SpriteUtils-2.
-
> Так вот сначала напиши, а потом советуй выбросить FastDIB.
Мне незачем искать, я и так знаю, что еше нет «кода, написаного, homm (мной), который работает с любым коэффициентом масштабирования, быстрее Bilinear и даёт более качественный результат».
> Против Фотошопа FastLib'у есть что выставить - у SmoothResize > качество ничуть не хуже, и скорость скорее всего тоже.
Просто делать делать необоснованные утверждения? Photoshop — 532 ms, SmoothResize — 2312ms.
> Но Bilinear - это специально оптимизированная на скорость > (ценой некоторой потери качества) функция.
«ИМХО» забыл добавить.
> Поэтому не стоит сравнивать её с меланхоличным Фотошопом.
«меланхоличным Фотошопом» это как понять?
-
2 antonnprocedure BitmapAntialias2X(SrcBitmap, DstBitmap: TBt);
type AGRBQuad = array [0..0] of TRGBQuad;
PAGRBQuad = ^AGRBQuad;
var yDest: integer;
xDest: integer;
xSrc: integer;
i: integer;
R: integer;
G: integer;
B: integer;
rowDest: PAGRBQuad;
rowSrc: array [0..3] of PAGRBQuad;
_rowSrc: PAGRBQuad;
SrcBits: DWORD;
DstBits: DWORD;
dHeight: DWORD;
dWidth: DWORD;
Delta: DWORD;
begin
if CPUisMMX then begin
SrcBits := DWORD(SrcBitmap.P);
DstBits := DWORD(DstBitmap.P);
dHeight := DstBitmap.DIBHeight;
dWidth := DstBitmap.DIBWidth;
Delta := SrcBitmap.DIBWidth*SizeOf(BTElement); asm
pushad
mov esi, SrcBits
mov edi, DstBits
db $0f, $ef, $d2
mov eax, dHeight
@LM1: push eax
mov eax, dWidth
@LM2: mov ecx, esi
db $0f, $6e, $09
db $0f, $60, $ca
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
add ecx, Delta
db $0f, $6e, $19
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $6e, $59, $04
db $0f, $60, $da
db $0f, $dd, $cb
db $0f, $71, $d1, $02
db $0f, $67, $ca
db $0f, $7e, $0f
add edi, 4
add esi, 8
sub eax, 1
jnz @LM2
add esi, Delta
pop eax
sub eax, 1
jnz @LM1
db $0f, $77
popad
end;
end else
end; получилось 219мс супротив 657 с antialias_x2. BitmapAntialias4X преобразуется точно так-же, ни одна асмовская строчка не затрагивается :) Паскалевскую версию закоментировал, надеюсь ты сам с ней разберешся :) А вообще лучше бы оптимизировал загрузку изображений, толку было бы больше.
-
> [95] homm © (16.10.07 06:33) > > Так вот сначала напиши, а потом советуй выбросить FastDIB. > > Мне незачем искать
Прошу прощения, прочлось как «сначала поищи».
-
> [92] antonn © (16.10.07 01:07) > if((Row2[x].rgbRed=255) and (Row2[x].rgbGreen=0) and (Row2[x].rgbBlue=0) ) then
if ((DWORD(Row2[x]) AND $ffffff)=$ff0000) then > P^[ y*DIBWidth+x ]:=(Row2[x].rgbRed or (Row2[x].rgbGreen > shl 8) or (Row2[x].rgbBlue shl 16) or (Row2[x].rgbReserved > shl 24));
P[ y*DIBWidth+x ] := DWORD(Row2[x]);
-
> if((Row2[x].rgbRed=255) and (Row2[x].rgbGreen=0) and (Row2[x].rgbBlue=0)) then > Row2[x].rgbReserved:=0 else > Row2[x].rgbReserved:=255;
Сечас компилятора нет под рукой, но можно попробовать избавится от условного перехода. Row2[x].rgbReserved := Byte(boolean( (DWORD(Row2[x]) AND $ffffff) xor $ff0000) )*$ff; Слабо верится, что Дельфи поймет, что я тут хотел сказать, но вдруг :)
-
Просто делать делать необоснованные утверждения? Photoshop — 532 ms, SmoothResize — 2312ms.
Да, сам не пробовал сравнивать. Кстати, а где у Фотошопа встроенный таймер (и какая версия нужна)? Версия SmoothResize моя или стандартная?
-
> [100] Sapersky (16.10.07 09:26) > Кстати, а где у Фотошопа встроенный таймер и какая версия нужна
В программе ProcessExplorer. Любая.
> Версия SmoothResize моя или стандартная? Из комплекта FastDIB. ([20])
-
> [100] Sapersky (16.10.07 09:26) > Версия SmoothResize моя или стандартная?
Даже если твоя в 2 раза быстрее (как здявлено) она все равно в 2 раза медленнее, чем в фотошопе. Я склонен полагать, что в фотошопе функции всеже менее универсальны, просто их там туча, для каждого формата пикселей и фильтра своя. Соответственно они более оптимизированы.
-
У меня получилось - в 1.5 раз медленнее Фотошопа. В принципе, приемлемо, тем более что я осознанно отказался от некоторых оптимизаций в пользу компактности кода. Фирме Adobe - миль пардон, недооценил её продукт.
-
В фотошопе не только под все форматы изображений сделаны оптимизации, но и под разные процессоры и с использование MMX, SSE и т.д.
-
а кишки битмапа хранятся в нем "задом-наперед"?
-
> [105] antonn © (27.10.07 13:24)
Есть формат с обратным порядком строк, пиксели насколько помню всегда слева направо.
-
аа, точно, по вертикали разный ипиксели в BGR лежат ну пиксели то обратно перевернуть не проблема: bswap eax
ror eax, 8 у меня со строками какая то фигня происходит, на две больше по вертикали отсчитывает :)
-
вернемся к истокам
>Так как все же качественно (!) и быстро (!) масштабировать картинку
почему бы не попробовать directX? что-то, а скорость там будет.
-
> почему бы не попробовать directX? что-то, а скорость там > будет.
а если на машине нет нужной версии DX? А если еще со встроенным решением...
-
> почему бы не попробовать directX? что-то, а скорость там > будет.
Ты картинку туда загонять будешь дольше, чем масштабировать. А потом, какой смысл использовать DirectX если вывод картинки на экран не планируется.
-
> homm © (16.10.07 07:03) [96]
тут какая то ерунда выяснилась... в коде [96]: jnz @LM2
add esi, Delta
add esi, 4
pop eax
sub eax, 1
jnz @LM1 без выделеного картинка сдвигается. а вроде ведь работало... вот теперь сижу и думаю, а код "работающий" или очень "нежный"? :)
-
хм, нет, все равно ерунда, ниче не понимаю %) на маленьких изображениях все пучком (64*64), на больших - сдвиг
-
аа, доперло %) если нечетное кол-во пикселей по Х, то сдвигается... блин :(
-
> [113] antonn © (10.11.07 23:23) > если нечетное кол-во пикселей по Х, то сдвигается...
Там вообще код спецефический, был сделан для строго определенной подачи данных, в которой ошибки быть не должно.
-
почему бы не попробовать directX? что-то, а скорость там будет.Ну вот для иллюстрации выкладываю ещё раз свой тест: http://sapersky.narod.ru/files/GDI_vs_DDraw_vs_FastLIB.rarДля DX в заголовке формы после "+" пишется время создания поверхности и копирования в неё картинки. Претензии по качеству аппаратного масштабирования (которое, действительно, неважное, ближе к Bilinear, чем к SmoothResize/StretchBlt) просьба предъявлять производителям видеокарт. Бороться с плохим качеством можно выводом через 3D с использованием, например, трилинейной фильтрации, или хотя бы просто мип-мэппингом (который можно организовать и вручную с софтвером/DDraw).
-
Помогите. Необходимо запихать BitMap картинку в массив. Как это сделать?
-
> [116] Андрей (27.11.07 00:51)
Читай про PixelFormat и ScanLine.
-
на предыдущей странице ведь есть...
-
А битмап - это и так массив :)
-
но почему то с перевернутыми строками... :(
-
Использую TFastDib, не для всех Jpeg получается сделать SmoothResize - AV получаю (для 256-цветной картинки, например).
-
Вопрос отпал, всё получилось.
-
cgwsnpbkm fqajlt laehj qimoe xcdtaoqmk gwej dpqxvyo
-
> Причина в том. что разрешение должно быть у картинки 1024*768, > надо пологать ?
homm, спасибо за код. Но скажите как с помощью вашего алгоритма уменьшить изображение в 1.5 и в 3 раза а не только в 2 и 4? Очень надо. Сама я точно так не напишу.
|