Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1347384231
Писатель
2012-09-11 21:23
2013.03.31
Масштабирование BMP


4-1264157517
Barloggg
2010-01-22 13:51
2013.03.31
Иконка в трее длинная. Это реально?


15-1354998602
Юрий
2012-12-09 00:30
2013.03.31
С днем рождения ! 9 декабря 2012 воскресенье


8-1227335832
Б
2008-11-22 09:37
2013.03.31
Media


15-1355013745
dummy_user
2012-12-09 04:42
2013.03.31
Turbo Pascal. Программы.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский