Форум: "Начинающим";
Текущий архив: 2013.03.31;
Скачать: [xml.tar.bz2];
ВнизМасштабирование BMP Найти похожие ветки
← →
Писатель (2012-09-11 21:23) [0]
Procedure Reduce(var bmp,BmpDest: TBItmap);
var
bmp2: TBItmap;
begin
bmp2 := Tbitmap.Create;
bmp2.PixelFormat := pf24bit;
bmp2.Width := BmpDest.Width;
bmp2.Height:= BmpDest.Height;
bmp2.Canvas.StretchDraw(bmp2.Canvas.Cliprect, bmp);
//StretchBlt(bmp2.Canvas.Handle,0,0,BmpDest.Width,BmpDest.Height,bmp.Canvas.Handle ,0,0,Bmp.Width,Bmp.Height,SRCCOPY);
//Self.Canvas.Draw( 100, 10, bmp );
bmp.free;
bmp :=bmp2;
end;
Требуется привести размер одного бмп к размеру другого, для последующего их сравнения (изображения монохромные и должны оставаться такими после ресайза). Для простоты, можно свести задачу к его уменьшению. Нашел код, который сверху. Но проблема в том, что он не "растягивает/сжимает" изображение, он его просто отрезает. Т.е. если например берем букву "U" и пытаемся ее уменьшить по вертикали на 1 пиксель, то в данной реализации букве просто отрезает дно (
В то же время паинт, убирает пиксель по высоте там где надо и "дно" остается на месте. И даже если в паинте пририсовать еще и верх, т.е. довести до буквы "O" то опять же при уменьшении на 1 пиксель, ни "дно" ни "потолок". не страдают при сжатии.
Вопрос, что я делаю не так? или функция StretchDraw в принципе так работает? и если так, то может быть кто нить может привести пример, как уменьшать картинку с более приемлимыми потерями.
Еще в инете разрекламирована билинейная интерполяция, но она более менее приемлемо работает только на увеличение и в разы. При небольших изменениях в любую сторону получается ерунда.
← →
Писатель (2012-09-11 21:29) [1]А и еще в данном коде (вернее во всех реализациях его откуда я это и выдрал), есть строчка Self.Canvas.Draw( 100, 10, bmp );
Но что такое Self я че то так и не понял, посему эту строчку не использовал. может в этом секрет?bmp2.Canvas.StretchDraw(bmp2.Canvas.Cliprect, bmp);
//StretchBlt(bmp2.Canvas.Handle,0,0,BmpDest.Width,BmpDest.Height,bmp.Canvas.Handle ,0,0,Bmp.Width,Bmp.Height,SRCCOPY);
А эти 2 строчки дают одинаковый результат (
← →
MBo © (2012-09-11 21:37) [2]Ничего не отрезается, просто режим уменьшения по умолчанию так работает, выбрасывая часть пикселов.
Перед StretchBlt можно задать SetStretchBltMode c подходящим в конкретных условиях параметром
← →
KSergey © (2012-09-12 07:56) [3]Лучше взять библиотечку работы в изображениями, чес. слово.
На торри явно есть много, ну или гуглем поискать
← →
Плохиш © (2012-09-12 11:42) [4]
procedure ResizeBMP(ABitMap: TBitmap; ANewWidth, ANewHeight: Integer);
var
tmpBmp: TBitmap;
(**)
divHeight,
divWidth: double;
(**)
begin
tmpBmp := TBitmap.Create;
try
tmpBmp.PixelFormat := ABitMap.PixelFormat;
tmpBmp.Width := ABitMap.Width;
tmpBmp.Height := ABitMap.Height;
BitBlt(tmpBmp.Canvas.Handle, 0, 0, tmpBmp.Width, tmpBmp.Height,
ABitMap.Canvas.Handle, 0, 0, SRCCOPY);
(**)
divHeight := ABitMap.Height / ANewHeight;
divWidth := ABitMap.Width / ANewWidth;
if (divHeight = 1.0) and (divWidth = 1.0) then
begin // Keine トnderung
ANewWidth := ABitMap.Width;
ANewHeight := ABitMap.Height;
end
else if divHeight > divWidth then
begin // Bei Height
ANewWidth := trunc(ABitMap.Width / divHeight);
end
else // Bei Width
begin
ANewHeight := trunc(ABitMap.Height / divWidth);
end;
(**)
ABitMap.Width := ANewWidth;
ABitMap.Height := ANewHeight;
if SetStretchBltMode(ABitMap.Canvas.Handle, HALFTONE) = 0 then
begin
ShowMessage("SetStretchBltMode: " + SysErrorMessage(GetLastError));
end
else if not SetBrushOrgEx(ABitMap.Canvas.Handle, 0, 0, nil) then
begin
ShowMessage("SetBrushOrgEx: " + SysErrorMessage(GetLastError));
end
else if not StretchBlt(ABitMap.Canvas.Handle, 0, 0, ABitMap.Width, ABitMap.Height,
tmpBmp.Canvas.Handle, 0, 0, tmpBmp.Width, tmpBmp.Height, SRCCOPY) then
begin
ShowMessage("StretchBlt: " + SysErrorMessage(GetLastError));
end;
finally
tmpBmp.Free;
end;
end;
← →
han_malign (2012-09-12 16:34) [5]
> Требуется привести размер одного бмп к размеру другого, для последующего их сравнения ...
> Для простоты, можно свести задачу к его уменьшению.
- для простоты задачу надо сводить до приведения обоих изображений к НОК размеров, но поскольку в общем случае НОК может быть слишком большим - надо не масштабировать изображения, а считать дельту на виртуальном разностном растре, через элементарное преобразование координат...
Причем оценочный дельта-растр, в отличие от расчетного - в виду опроксимационной направленности задачи - должен иметь минимальные по обоим координат размеры. Условие сбоя дельта-пикселя - вес(для ЧБ - площадь) разницы больше половины...
|***| |**|
| **| |**|
| *|
* * *|* * * * * *|* * * |
* * *|* * * * * *|* * * 0 | 0
* * *|* * * * * *|* * * |
----------- - ----------- = -----------
*|* * * * * *|* * * |
*|* * * |* * * 4/9 | 0
*|* * * |* * * |
Естественно работать будет только в полутоновом смысле, для "черного на белом" и "белого на черном" - нужно точно знать алгоритм редукции(причем важно помнить, что в случае увеличения с не целой кратностью - редукция тоже имеет место быть).
← →
alexdn © (2012-09-12 19:56) [6]> han_malign (12.09.12 16:34) [5]
а вот действительно, даже если использовать Stretch, какие масштабы использовать, чтобы проглатывание пикселей было минимальным?
← →
alexdn © (2012-09-12 19:57) [7]т.е. как лучше масштабировать, кратно 1,125 например, или 1/2, 1/3 и т.д..
← →
alexdn © (2012-09-12 20:22) [8]вот нашёл кое что, но как это практически применить?
•"Nearest neighbor". Быстрейший и худший метод, поскольку используется попросту значение бижайшей точки исходной картинки. По сути, часть точек отбрасывается (при уменьшении) либо дуплицируется (при увеличении).
•"Bilinear". В обоих направлениях проводится линейная интерполяция (используется 2х2 матрица, то есть 4 ближайших точки). Быстрый и неплохой метод, слегка сглаживающий картинку, однако при больших увеличениях начинает проявляться блочная структура.
•"Bicubuc". В обоих направлениях проводится кубическая интерполяция (по матрице 4х4, то есть используется 16 ближайших точек), дает более резкую картинку. При увеличении дает значительно лучший результат, чем билинейный метод. Поскольку детали прорисовываются четче, усиливаются и шумы, то есть картинки с шумами нужно увеличивать очень осторожно. Значительно медленнее, чем билинейный фильтр.
•"Precise bilinear". В обоих направлениях проводится линейная интерполяция, но вместо 2х2 используется полная билинейная матрица. При увеличении работает аналогично билинейному методу, но при уменьшении очень эффективно сглаживает шумы.
•"Precise bicubuc". В обоих направлениях проводится кубическая интерполяция по полному бикубическому ядру. Очень хорош как при увеличении так и при уменьшении картинки. Медленнее всех предыдущих. Имеется выбор между тремя значениями одного из параметров (но на глаз разницу не видно). A=-1.00 дает наиболее четкую картинку.
•"Lanczos3". Используется матрица 6х6 (то есть каждая точка вычисляется по 36 соседним точкам. Многие считают этот метод лучшим, но он и самый медленный.
← →
Jeer © (2012-09-12 21:40) [9]Смотреть, например, FastLib
Там такие фильтры реализованы:
type
TResizeFilter = (rfNearest,rfBox,rfBilinear,rfHanning,rfHamming,rfHermite,rfBell, rfCatrom,rfBicubic,rfSpline2,rfMitchell,rfGaussian,rfSpline3,rfSinC3,rfLanczos3, rfBlackman3);
← →
alexdn © (2012-09-12 22:28) [10]> Jeer © (12.09.12 21:40) [9]
> Смотреть, например, FastLib
FastLib это отдельная? что то не вижу даже в XE2.
← →
brother © (2012-09-14 06:14) [11]да
← →
Писатель (2012-09-24 18:32) [12]
> Лучше взять библиотечку работы в изображениями, чес. слово.
>
> На торри явно есть много, ну или гуглем поискать
что есть тори?
← →
Писатель (2012-09-24 18:47) [13]скачал http://narod.yandex.ru/100.xhtml?sapersky.narod.ru/files/FastLIBv389i.rar
А инструкции внятной по этому нет?
← →
Sapersky (2012-09-25 11:33) [14]Инструкции нет, есть пример с масштабированием:
http://sapersky.narod.ru/files/ResizeTest.rar
Как вариант, можно использовать Graphics32 (качественное масштабирование оттуда и скопипастено), там есть документация.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2013.03.31;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.017 c