There is a task: to enlarge the image 100x100 with four channels (red, green, blue, alpha channel; it contains a very blurred spot), up to size 2500x2500, and bring it to a previously prepared graphic device context. In fact, a brush, like brushes in Adobe Photoshop. The problem is just to increase (resize). Here is the original image (or brush; I only show the alpha channel, the rest is not important):
alt text
Drawn with a standard Photoshop brush.
But what happens after I increase my algorithm (once again: do not pay attention to the color: it is set randomly). I used leni interpolation . alt text
Do you also see these rough edges? So: the whole problem is in them. These roughness are in the alpha channel, because the color of the whole brush is uniform. Because of them, when drawing a line with a brush, terrible dirt is formed. To understand the nature of these irregularities, I decided to draw in Photoshop a 1-pixel-wide strip representing a smooth gradient from white to blue, and then again to white. Then I expanded each strip in width, first with my algorithm, then in Photoshop: alt text http://plasmon.rghost.ru/38526229/image.png
alt text http://rghost.ru/38526272/image.png
In the first picture again you can see the bumps. That is why, in my opinion, irregularities arise: alt text http://rghost.ru/38526320/image.png
Here, the x axis is the pixel number, y is the color. Blue dots are original, red ones approximated by linear interpolation. The blue graph shows perfect spline interpolation, but it takes too long to run on a computer. So, do you see the broken black graph of linear interpolation? These very corners of the broken line, it seems to me, form such roughness.

In Photoshop, the settings are interpolation "Bicubic (best for smooth gradients)", but "Linear" and "Bicubic" in Photoshop give the same result with my algorithm. So we can assume that "Bicubic (best for smooth gradients)" in Photoshop, the image is first increased by linear interpolation and then the banal blur filter is applied.


So. All blur filters that I found on the Internet are working extremely slowly (including mine). Most likely, Photoshop uses a graphics accelerator. But is it possible to somehow accomplish my task only with the help of the CPU? And to work a maximum of a second. Waiting for your suggestions.


//горизонтальная интерполяция между исходными пикселами for y:=1 to setedbrush.h_orig do for x := 1 to setedbrush.w_orig-1 do begin x_0:=round(x*k); x_x:=x_0+1; x_1:=round((x+1)*k); y_y:=round(y*k); while(x_x<>x_1) do begin cl:=round((temp[x_1,y_y].r-temp[x_0,y_y].r)/(x_1-x_0))+temp[x_0,y_y].r; temp[x_x,y_y].r:=cl; cl:=round((temp[x_1,y_y].g-temp[x_0,y_y].g)/(x_1-x_0))+temp[x_0,y_y].g; temp[x_x,y_y].g:=cl; cl:=round((temp[x_1,y_y].b-temp[x_0,y_y].b)/(x_1-x_0))+temp[x_0,y_y].b; temp[x_x,y_y].b:=cl; cl:=round((temp[x_1,y_y].a-temp[x_0,y_y].a)/(x_1-x_0))+temp[x_0,y_y].a; temp[x_x,y_y].a:=cl; inc(x_0); inc(x_x); end; end; 

Here x_0 is the extreme known left pixel, respectively x_1 is the right one; x_x is the calculated pixel, y_y is the current line. Formula based on similarity of right triangles.


The result is already better than before. But when drawing a line - dirt. Well, it is necessary to smooth out ... Although, maybe, it's in the picture. alt text http://rghost.ru/38553575/image.png

  • Or not to do without a graphic accelerator? - ololo
  • one
  • If the image is known to be a blur, can it be used? And apply the algorithm radially. - KoVadim
  • Not. This is the case here. - ololo
  • @sercxjo, And the last question: please specify your answer: "By the way, you can convert the formulas to replace division by multiplication and derive the division operation for the internal cycle, it will be slightly faster. - ololo

1 answer 1

You assume why they arise, and you build a real graph of the brightness change along one line of some kind.

The next pixel is calculated through the previous one, so the error will accumulate. Try to calculate according to the extreme points, it is clear that one more multiplication is required, but it will be more accurate. First, check whether interpolation will become better, if we assume that it is

 round((temp[x_1,y_y].a-temp[x_0,y_y].a)*(x_x-x_0)/(x_1-x_0)) + temp[x_0,y_y].a 

and x_0 in the inner loop does not change

  • cl: = round ((temp [x_1, y_y] .r-temp [x_0, y_y] .r) / (x_1-x_0)) + temp [x_0, y_y] .r; - ololo
  • one
    those. only on one coordinate stretch? What type of variables? - sercxjo
  • First, each element x, y of the original matrix is ​​copied to the element x k, y k of the calculated matrix. The calculated matrix, after that, looks like a field dotted with dots. Then between each vertical and horizontal pair of points, more points are drawn by linear interpolation. In this case, my interpolation is carried out horizontally for red, where x_0 is the first known element, x_1 is the second, and cl is the pixel between them. After all of the above, a grid is formed on the calculated matrix, the cells of which need to be filled. Next course of action, I think you understand. - Ololo
  • one
    Something in the formula, I do not see the coordinate of the calculated pixel. cl and temp are integers? - sercxjo
  • one
    Understood, the next pixel is calculated through the previous one, so the error will accumulate. Try to calculate according to the extreme points, it is clear that one more multiplication is required, but it will be more accurate. By the way, you can convert formulas to replace division by multiplication and derive the division operation for the internal cycle, it will be a little faster. - sercxjo