DEMO.DESIGN
Frequently Asked Questions
 
оглавление | demo party в ex-СССР | infused bytes e-mag | новости от ib/news | другие проекты | письмо | win koi lat

следующий фpагмент (2)
Фильтpы Q: А что значит "put the bitmap througth the filter" ? "Прогнать картинку через фильтр" -- итоговая яркость точки будет вычисляться как: 1 \~~~| Out (x, y) = C * > In (x+i, y+j) * Matr (i+2, j+2) /___| i,j=-1 Где Out (x, y) -- понятно, получаемая на выходе картинка In (x, y) -- исходная картинка Matr (x, y) -- матрица фильтра C -- некий нормализующий коэффициент (обычно = 1/сумму элементов матрицы) Для того, чтобы прогнать всю картинку -- необходимо сделать двойной цикл, в котором и вычислить все результирующие точки картинки по исходным -- "профильтровать". Или почитай книжки: 1. В.Яншин, Г.Калинин Обработка изображений на языке Си для IBM PC 2. К.Линдли Практическая обработка изображений на языке Си [....] Встpечая в гpафических пpогpаммах выpажение "матpичный фильтp", я все вpемя полагал, что это матpица соответствyющего пpеобpазования пиксельного изобpажения: Фильтpyется OldScreen -> NewScreen: For X = MinX..MaxX, Y=MinY..MaxY - pазмеpы изобpажения n = 0 For I = -1..1, J=-1..1 (для матpицы 3x3) n = n + OldScreen[x+i,y+j] * Matrix[i,j] NewScreen[x,y] = n / DivisionFactor (все это пpоделать для R, G и B по желанию, или для Gray) Чтобы сохpанить яpкость, DivisionFactor нyжно взять pавным сyмме всех элементов матpицы или единицy, если эта сyмма pавна нyлю (как в данном слyчае). Все это была только теоpия, котоpyю я использовал "для объяснения неизвестных понятий" в гpаф. пpогpаммах. Только что пpовеpил это на пpактике (на PaintShop Pro) - все оказалось пpавильно. А пpиведенный выше фильтp отыскивает кpая наpисованных объектов. [...] 1. Smooth. Делается осpеднением (тyпым или взвешенным) по некотоpой области вокpyг каждой точки. К пpимеpy + + * + + значение в * yмножается на 4, к немy пpибавляются значения в + и вся сyмма делится на 8 - это значение для точки-pезyльтата с теми же кооpдинатами, что *. Все это, ясен пеpец, для greyscale. Для truecolor делается подсчет для каждой из цветовых компонент (RGB, YUV и т.д., но не HSB). Для палитpового pежима пеpеводить в truecolor и дyмать, как быть с pезyльтатом. Резyльтат - pазмывание каpтинки. Частный слyчай - averaging NxN - осpеднение по квадpатy NxN. 2. Median. Опять же область (обычно квадpат). Беpем все точки в ней, соpтиpyем, выбиpаем сpеднюю по поpядкy. Это для greyscale. Для палитpового pежима yпоpядочиваем палитpy по яpкости или еще как. Для truecolor - лyчше гнать фильтp по каждой компоненте pаздельно. Резyльтат - исчезают мелкие детали/шyмы. Попpобyй на каpтинкy бpызнyть спpеем, а потом пpогнать median filter. Аналогично делаются фильтpы maximum и minimum. Они соответственно yвеличивают светлые/темные детали и yменьшают темные/светлые. Обычно делается по квадpатy NxN. 3. Билинейная интеpполяция. Пpи yвеличении каpтинки в N pаз (N может быть и дpобным, но >1 - для меньших нет смысла) цвет точки с кооpдинатами N*x, N*y (x,y могyт быть дpобными - это кооpдинаты на исходной каpтинке, N*x, N*y - целые - кооpдинаты на каpтинке-pезyльтате) вычисляется так: C(x,y) = (C([x],[y])*(1-{x}) + C([x]+1,[y])*{x}) * (1-{y}) + (C([x],[y]+1)*(1-{x}) + C([x]+1,[y]+1)*{x}) * {y} где [] - целая часть, {} - дpобная часть. Для RGB - считается для каждой компоненты. Резyльтат - пpи yвеличении полyчаем не любимые большие дyмовские квадpаты, а pазмытyю каpтинкy, что смотpится кyда лyчше. Дpyгой способ добиться того же pезyльтата - averaging NxN после yвеличения. 4. Mipmapping. Для yменьшения каpтинки. Заpанее pассчитаваем каpтинки в 2, 4, 8 и т.д. pаз меньше (в 2 pаза меньше - осpеднением по квадpатам 2x2 и далее из нее так же) - в итоге pазмеp данных на тpеть больше. После чего пpи yменьшении в N pаз выводим либо исходя из каpтинки с наиболее подходящим pазмеpом, либо беpем две (для N=5 - в 4 и 8 pаз меньшие) и интеpполиpyем ( C=(C4*(8-5)+C8*(5-4))/(8-4) ). Резyльтат - пpи yменьшении каpтинки не возникают меpцание, мyаp, аpтефакты всякие - см в doom в конце длинного коpидоpа. Дpyгой способ добится того же эффекта - averaging NxN пеpед yменьшением, но mipmapping кyда быстpее.
следующий фpагмент (3)|пpедыдущий фpагмент (1)
- [94] Computer Graphics (2:5030/84) ----------------------------- SU.GRAPHICS - Msg : 12 of 14 From : Alexey Vinokurov 2:5020/354.55 22 Oct 96 21:12:00 To : Lout Roman Subj : bitmap filter -------------------------------------------------------------------------------- Hi, dear Lout ! ¦ Quoting message of bitmap filter Четверг Сентябрь 26 1996 ¦ from Lout Roman to All LR> -+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- LR> 13) How do I find the 'edges' in a bitmap? LR> A simple method is to put the bitmap through the filter: LR> -1 -1 -1 LR> -1 8 -1 LR> -1 -1 -1 LR> This will highlight changes in contrast. Then any part of the LR> picture where the absolute filtered value is higher than some LR> threshold is an "edge". LR> -+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- LR> А что значит "put the bitmap througth the filter" ? "Прогнать картинку через фильтр" -- итоговая яркость точки будет вычисляться как: 1 \~~~| Out (x, y) = C * > In (x+i, y+j) * Matr (i+2, j+2) /___| i,j=-1 Где Out (x, y) -- понятно, получаемая на выходе картинка In (x, y) -- исходная картинка Matr (x, y) -- матрица фильтра C -- некий нормализующий коэффициент (обычно = 1/сумму элементов матрицы) Для того, чтобы прогнать всю картинку -- необходимо сделать двойной цикл, в котором и вычислить все результирующие точки картинки по исходным -- "профильтровать". Или почитай книжки: 1. В.Яншин, Г.Калинин Обработка изображений на языке Си для IBM PC 2. К.Линдли Практическая обработка изображений на языке Си ЗЫ Существует таккже еще несколько фильтров для выделения контуров. Yours sincerely, Alexey. --- Naked Dead (body) 2.50b+ * Origin: D00Ming in progress [....................] (2:5020/354.55)
следующий фpагмент (4)|пpедыдущий фpагмент (2)
Everything included is Copyright (C) 1996 Yamaha of XYZZ (Scott Scriven) My web page is at: http://www.VIS.colostate.edu/~scriven/ -------------------------------------- Image Filtering -------------------------------------- Image filtering is a process by which we can enhance (or otherwise modify, warp, and mutilate) images. I've seen enough posts asking about this that I've made this info file to answer most people's questions. This file has information (so far) only about "compare" filters, which compare a pixel somehow with the pixels around it to filter the image. Another term that may be important is that we're doing "weighted" filtering. (as opposed to "equal" filtering) That means that different pixels have different importance in calculating the image. When I find out how to do other types of filters, I'll add information about it to this document. ------------------------------------ The source code ------------------------------------ There isn't any at the moment. The algorithms seem, to me, much more important. Maybe I'll make general-purpose code later. ------------------------------------ Filtering "modes" ------------------------------------ In this document I'll refer to two different types of filtering: Color-based, and Height-based. Height-based filtering only works on indexed-color images. The most common example of this is a 256-color image. Each color has an index number 0-255 and we can treat that number as the "height", as if on a map. Color-based filtering ignores the index number of a color and uses its actual red/green/blue components for calculations. This works on 256-color images as well as truecolor images. Note that most good paint programs have rather nice support for color-based filters, but completely lack indexed-color tools. ------------------------------------ Performance -- speed ------------------------------------ Well, filters will work differently speedwise depending on how they are implemented, and how they are optimized. If you do color-based filters on a 256-color image, it'll probably go rather slow. However, the same thing on a truecolor image would go quite fast. Also, height-based filters on 256-color images are usually fast. Height- based filters on truecolor images are the same as color-based filters. -------------------------------------- How it works -------------------------------------- The process is fairly simple: Make a copy of the image in memory. We'll use this as the destination for our filter. (makes the filter work much better) Set aside a "final" pixel value variable. For height-based filters, this will probably be an integer; and color-based will use an rgb triplet. For each pixel in the image, For the pixel and those around it, Get the pixel's value and multiply it by the corresponding value in the filter grid. Add this result to the total. Now divide this number by the "division factor". And put the "final" pixel value back in the image. In C, the outermost layer would look something like this: for(y=top; y<=bottom; y++) for(x=left; x<=right; x++) { ... } This just sets up a two-dimensional loop to process each pixel in the image. And now, a side-track: The "filter grid" The filter grid is how you define what the filter does. Here's a 5x5 example: 0 0 0 0 0 0 1 3 1 0 0 3 5 3 0 0 1 3 1 0 0 0 0 0 0 division: 21 This filter will "soften" the image. What the numbers mean is this: Imagine that the "hot pixel" (the one we're calculating now) is at the center of the grid, where it has a 5. The pixels around that hot pixel correspond to the numbers around the 5. This leads back to what we're doing to apply the filter. We'll want to have another loop to process each of the 25 pixels in that 5x5 grid. For each pixel in the loop, we'll multiply that pixel's value by the number in the same position on the grid. In this example, the pixels that are 2 units away from the "hot" pixel aren't even used (the 0's cancel any effect those pixels might have). Then we add this value to the running total for this pixel. Notice that the pixel in the center has the highest number. That makes it the most important pixel in the filter, and its color will carry the most "weight" in the resulting calculated color. Finally, we divide the total by the division factor, and put this value where the original "hot" pixel was. The loop would now look something like this: for(y=top; y<=bottom; y++) // for each pixel in the image for(x=left; x<=right; x++) { gridCounter=0; // reset some values final = 0; for(y2=-2; y2<=2; y2++) // and for each pixel around our for(x2=-2; x2<=2; x2++) // "hot pixel"... { // Add to our running total final += image[x+x2][y+y2] * filter[gridCounter]; // Go to the next value on the filter grid gridCounter++; } // and put it back into the right range final /= divisionFactor; destination[x][y] = final; } And when it's all done, copy the destination to the source, and get rid of the destination image. This loop should do a height-based filter on a 256-color image. It will do the filter rather slowly, but it's up to you to optimize. To do a color-based filter, you'll need to do the same thing, but use three "final" values; for red, green, and blue. If you're doing a color-based filter on a 256-color image, you'll need to do even more work. You'll need to find the closest color in the palette to the "final" color. (this will probably cut the code speed down by a factor of 3 or more) IMPORTANT NOTE: You really should use two images when doing a filter. If you don't, the results will come out quite strange. ---------------------------------------------- Sample Filters (most are in Digital Artist) ---------------------------------------------- Soften (medium) 0 0 0 0 0 0 1 3 1 0 0 3 9 3 0 0 1 3 1 0 0 0 0 0 0 divide: 25 Soften (a lot) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 divide: 25 Soften (a little) 0 1 2 1 0 1 3 10 3 1 2 10 90 10 2 1 3 10 3 1 0 1 2 1 0 divide: 154 (I think) Sharpen (low) (negative values are useful for creating contrast) 0 0 0 0 0 0 -1 -3 -1 0 0 -3 41 -3 0 0 -1 -3 -1 0 0 0 0 0 0 divide: 25 Sharpen (medium) -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 49 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 divide: 25 "Soft" Sharpen (weird... try it repeatedly on an image) -1 -1 -1 -1 -1 -1 3 4 3 -1 -1 4 13 4 -1 -1 3 4 3 -1 -1 -1 -1 -1 -1 divide: 25 Diagonal "shatter" 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 divide: 4 Horizontal Blur 0 0 0 0 0 0 0 0 0 0 1 2 3 2 1 0 0 0 0 0 0 0 0 0 0 divide: 9 The "fire" filter (creates the "fire" effect, when used repeatedly) 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 divide: 4 -------------------------------------- Other ideas... -------------------------------------- It's possible to do quite a bit with filters like this. The fire effect is done this way, and the water effect is done in a very similar way too. Depending on the filter you use, you could create some very interesting effects. However, another type of filter is also useful: The "contrast" filter. It works by contrasting each pixel with those around it, instead of comparing the values. I don't really know how to get this to work correctly, though; but it can do things such as embossing and edge-finding. You may also want to try filters that have independent red, green, and blue filter grids (and do something different with each) to get some really strange (and neat) effects. I plan on implementing this in Digital Artist sometime, though I don't know when. --------------------------------------------------------- Testing filters without having to write a program for it --------------------------------------------------------- This is a plug for my paint program. To test filters, you can use Digital Artist (it's on my web page). It allows the user to create custom filters (and has several defaults ones) to apply to images. You can apply these filters both in color-based mode and height-based mode. (so you could treat an image as a 3D landscape) I've found this program to be very useful, and I hope others do too. Check the top of this document for the URL.
следующий фpагмент (5)|пpедыдущий фpагмент (3)
From: Lenik Terenin: -------------------- Пусть исходный обpаз хpанится в image (width*height), новый -- в new_image, матpица пpеобpазования -- matrix (3х3), как та, что написана тобою выше. for( i=1; i<width-1; i++) { // единички -- чтобы не тpогать for( j=1; j<height-1; j++) { // кpайние пихелы. sum = 0; for( n=0; n<3; n++) { // обpабатываем соседей с for( m=0; m<3; m++) { // коэффициентами из matrix sum += image[i+n-1][j+m-1] * matrix[n][m]; } } new_image[i][j] = sum / divisor; } }
следующий фpагмент (6)|пpедыдущий фpагмент (4)
- Usenet echoes (21:200/1) -------------------------- COMP.GRAPHICS.ALGORITHMS - Msg : 38 of 52 From : atsao@tkk.win.net 2:5030/144.99 12 May 94 15:44:54 To : All 18 May 94 02:54:16 Subj : Re: comp.graphics.algorithms FAQ -------------------------------------------------------------------------------- >How do I enlarge/sharpen/fuzz a bitmap? Sharpen Filters: (There are many variations, with the main characteristic that the center element is positive and the surrounding elements is negative ) -1 -1 -1 1 -2 1 -1 9 -1 -2 5 -2 -1 -1 -1 1 -2 1 Sharpen some Sharpen heavily Smooth/Fuzz Filters 1 1 1 1 1 1 1 1 1 (divide the result by 9) This filter can be extended to larger matrices for fuzzier effect. Anson Tsao Internet:atsao@tkk.win.net
следующий фpагмент (7)|пpедыдущий фpагмент (5)
- Usenet echoes (21:200/1) -------------------------- COMP.GRAPHICS.ALGORITHMS - Msg : 113 of 144 From : paradise@ajax.umcs.lublin.pl 2:5030/315 18 Jan 96 07:39:38 To : All 20 Jan 96 05:15:16 Subj : Blurring and stuff... -------------------------------------------------------------------------------- The formula for blurring is very simple and can be optimised to use realtime (the emboss is very similar) for example in my 3d engine. So here it goes: for each pixel in each scanline do (pseudo-code): color = getpix(x-1, y-1) + getpix(x, y-1) + getpix(x+1, y-1) + getpix(x-1, y) + getpix(x, y) + getpix(x+1, y) + getpix(x-1, y+1) + getpix(x, y+1) + getpix(x+1, y+1); putpix(x, y, color / 9) - this algo is for most 'perfect' (and also slowest) blurring. blurring and other filters can be easy done usign matrices (i use 3x3). for example: [ 1 1 1 ] [ 1 1 1 ] divisor = 3 [ 1 1 1 ] usign this matrix gives you something like 'motion blur' effect (c by me:): [ 0 0 1 ] [ 0 1 0 ] divisor = 3 [ 1 0 0 ] if you want other filters with theirs matrices, check out the files included to PhotoVision program or any other graphic program that allow to use user-defined filters (and have library of them). if anyone still have some questions, mail me
следующий фpагмент (8)|пpедыдущий фpагмент (6)
- [95] Computer Graphics (2:5030/84) ----------------------------- SU.GRAPHICS - Msg : 9 of 16 Pvt From : Lion Rokanidi 2:5057/4.23 15 Oct 96 02:23:00 To : Serguey Zefirov Subj : blur -------------------------------------------------------------------------------- Hello Serguey ! Thursday October 10 1996 17:07, Serguey Zefirov to Dmitry Seleznev: SZ> Hоpмальное использование blur состоит в pаботе с матpицей 3x3 - SZ> это девять сложений, одно деление (ссылка в таблицу). Такой blur SZ> С этой точки зpения мне интеpесно посмотpеть на pазные фильтpы, SZ> и как их можно ускоpить без сильной потеpи качества. Поэтому и SZ> интеpесуют честные методы. ;) Имитации - на фиг. Честный метод для матрицы n*m требует вовсе не n*m операций типа сложение, а всего лишь 2*m - в первом же простейшем варианте, приходящем в голову. А во втором, добавив чуток памяти под кольцевой буфер - m+1. Для матрицы 3*3 разница (4 против 9) еще не столь впечатляюща, но уже для 5*5 (6 против 25) эффект пятиминутного напряжения мозгов весьма заметен. Причем это еще далеко не предел, но 3 часа ночи - пардон.:) Люди, используйте инкрементальные алгоритмы. Как-то даже стремно такие тупые вещи объяснять.:) Первый метод состоит в прибавлении к предыдущей сумме значений из клеток добавляемого справа столбца (при движении матрицы на клетку вправо) и вычитании из отбрасываемого слева. Что характерно, при этом ширина матрицы на количество вычислений вообще не влияет (не считая начала каждой строки, где матрицу, конечно, нужно считать полностью). Второй метод - хранить суммы по n последним столбцам. Sincerely yours Lion, - the thinking animal -
следующий фpагмент (9)|пpедыдущий фpагмент (7)
- Demo/intro making and discussion (2:5030/84) ------------------ DEMO.DESIGN - Msg : 13585 of 13588 From : Andrew Lening 2:5026/49.11 24 Jun 36 03:47:35 To : Alexandr Simonov 19 May 00 02:13:52 Subj : Blur ------------------------------------------------------------------------------- Зюзик по поручению Андрея Ленинга рад поприветствовать Alexandr! AS> помогите с субжем.... Чтоб все быстро было ..... AS> на Пасе, если можно, и с коментариями.... AS> Сколько я это размазывание не пытался ускорить, ни чо не получилось AS> :( Вот. Бкз комметнтов и собсно блюp на асме :-) === Cut === Program Zuzik_Intro; { (c) Andrew Lening aka Zuzik aka 2:5026/49.11, 2000 } label pal_set; const xsize=30; ysize=23; {size of text} Zuzik: Array[0..ysize-1,0..xsize-1] of byte= ( (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), (0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0), (0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0), (0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0), (0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0), (0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0), (0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0), (0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), (0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), (0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0), (0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0), (0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0), (0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0), (0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0), (0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0), (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1) ); type BufferType=Array[0..63999] of Byte; var BackBuffer: BufferType; {бэкбуфер и массив для преобразований} BB2: ^BufferType; {второй} cntx,cnty: Word; {variables for 2D loops} sbb2,obb2: Word; {Seg:Ofs of second BB2^} FrameCount: LongInt; Procedure Blit; Assembler; {blits BB2^ to the screen} asm lea si,BackBuffer mov ax,$a000 mov es,ax xor di,di mov cx,32000 rep movsw end; Procedure CopyBBtoBB2; Assembler; {no comments :-) } asm lea si,BackBuffer mov es,sbb2 mov di,obb2 mov cx,16000 db 66h rep movsw end; Procedure OutZuzik; var x,y: Integer; begin x:=Random(319-xsize*2)+1; y:=Random(199-ysize*2)+1; For cntx:=0 to xsize-1 do For cnty:=0 to ysize-1 do If Zuzik[cnty,cntx]>0 then begin {вывод бюковки с 50% алфа-каналом} BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+(x+cntx shl 1)]:= 32+(BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+ (x+cntx shl 1)] shr 1); BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+(x+cntx shl 1)+1]:= 32+(BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+ (x+cntx shl 1)+1] shr 1); BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+(x+cntx shl 1)+320]:= 32+(BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+ (x+cntx shl 1)+320] shr 1); BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+(x+cntx shl 1)+321]:= 32+(BackBuffer[(y+cnty shl 1)shl 8+(y+cnty shl 1)shl 6+ (x+cntx shl 1)+321] shr 1); end; end; Procedure Transform; var rc: Word; {result color for a pixel} begin For cnty:=1 to 198 do For cntx:=1 to 318 do begin asm les di,bb2 xor ax,ax xor bx,bx mov di,cnty shl di,2 add di,cnty shl di,6 add di,cntx add al,es:[di+1] add al,es:[di-1] add al,es:[di+320] add al,es:[di-320] add bl,es:[di+321] add bl,es:[di-321] add bl,es:[di+319] add bl,es:[di-319] shr ax,2 shr bx,2 add ax,bx shr ax,1 mov rc,ax end; BackBuffer[cnty shl 8 + cnty shl 6 + cntx]:=rc; end; {For cntx:=1 to 318 do begin rc:=(BB2^[cntx-1]*Matrix[0,1]+ BB2^[cntx]*Matrix[1,1]+ BB2^[cntx+1]*Matrix[2,1]+ BB2^[320 + cntx-1]*Matrix[0,2]+ BB2^[320 + cntx]*Matrix[1,2]+ BB2^[320 + cntx+1]*Matrix[2,2]) div s_u; BackBuffer[cntx]:=rc; end; For cnty:=1 to 198 do begin rc:=(BB2^[(cnty-1)*320]*Matrix[1,0]+ BB2^[(cnty-1)*320 + 1]*Matrix[2,0]+ BB2^[cnty*320]*Matrix[1,1]+ BB2^[cnty*320 + 1]*Matrix[2,1]+ BB2^[(cnty+1)*320]*Matrix[1,2]+ BB2^[(cnty+1)*320 + 1]*Matrix[2,2]) div s_c; end;} end; begin asm mov ax,13h int 10h xor cx,cx pal_set: {установка палитры} mov dx,03c8h mov ax,cx out dx,al inc cx cmp cx,64 mov dx,03c9h out dx,al out dx,al out dx,al jne pal_set end; GetMem(BB2,64000); sbb2:=Seg(BB2^); obb2:=Ofs(BB2^); For cnty:=0 to 199 do For cntx:=0 to 319 do BB2^[cnty*320+cntx]:=0; BackBuffer:=BB2^; Repeat Transform; Blit; If (framecount mod 4)=0 then OutZuzik; CopyBBtoBB2; inc(FrameCount); {asm hlt end;} until Port[$60]=1; FreeMem(BB2,64000); asm mov ax,3 int 10h end; end.
следующий фpагмент (10)|пpедыдущий фpагмент (8)
- Netmail msgs (2:5030/84) ------------------------------------------------- From : Vitaly Mayatskih 2:5002/27.65 17 Sep 01 23:22:38 -------- Радиальный блюр реализуется следующим образом: на рабочей поверхности имеется точка 0 (центр блюра) с произвольными координатами (x0, y0), дающая начало прямым, проходящим через каждую точку поверхности. Hа каждой прямой откладываем вектор, кратный какому-либо числу, например, восьми. Hачало вектора будет лежать на сблюриваемой точке 1 (x1 ,y1), а конец указывать на точку 2, с которой мы хотим сблюрить. Y ^ 1 | / | / | 2 | / |/ 0------->X //x = |x0 - x1| //y = |y0 - y1| n = sqrt(x * x + y * y) / 8 + 1; vx = x / n; vy = y / n; vptr = y1 * XSIZE + x1; p1 = *vptr; p2 = *(vptr + vy * XSIZE + vx); *p1 = (p1 + p2) / 2; Пробегая в цикле по всем точкам на поверхности, имеем radial blur. Зададимся теперь целью сделать эффект приемлемым по скорости. Для этого надо избавиться от двух умножений, вычисления корня и трсх делений на точку. Посчитаем табличку, содержащую vx и vy для всех точек поверхности. Как видно, точка (x0, y0) разбивает плоскость на четыре части, вычисления в которых идут абсолютно одинаково, просто переменные цикла изменяются в разных пределах. Итак, считаем таблицу (вернее, две: для каждого из двух значений): nx = new char [XSIZE * YSIZE]; ny = new char [XSIZE * YSIZE]; for(int x = 0; x < XSIZE; x++) for(int y = 0; y < YSIZE; y++){ float n = sqrt(x * x + y * y) / 8 + 1; *(nx + y * XSIZE + x) = (char)(x / n); *(ny + y * XSIZE + x) = (char)(y / n); } } И, напоследок, пример цикла для одной четверти (левой верхней) поверхности: //bx, by - координаты центра блюра //videobuf - адрес фрейм-буфера int x, y; char p1, p2; int t, vx, vy; char *vptr; vptr = videobuf + (((by-1)<<6) + ((by-1)<<8) + bx - 1); //by * 320 + bx - 1 t = 0; for(y = by - 1; y >= 0; y--){ for(x = bx - 1; x >= 0; x--){ vx = *(nx + t); vy = *(ny + t); p1 = *(vptr); p2 = *(vptr + vx + (vy<<8) + (vy<<6)); //vy * 320 + vx *vptr = (p1 + p2)>>1; vptr--; t++; } vptr += bx - 320; t += 320 - bx; }

Всего 9 фpагмент(а/ов) |пpедыдущий фpагмент (9)

Если вы хотите дополнить FAQ - пожалуйста пишите.

design/collection/some content by Frog,
DEMO DESIGN FAQ (C) Realm Of Illusion 1994-2000,
При перепечатке материалов этой страницы пожалуйста ссылайтесь на источник: "DEMO.DESIGN FAQ, http://www.enlight.ru/demo/faq".