14
\$\begingroup\$

Introduction

Sharp edges are, frankly, just plain dangerous so, given a PNG as input, blur the image using the method described below and blunt those damned sharp edges.

Method

To get the RGB value of each pixel, use the following three equations:

$$R = \sqrt{\frac{1.5\times\sum^n_{a=1}R^2_a}{n}}$$ $$G = \sqrt{\frac{1.5\times\sum^n_{a=1}G^2_a}{n}}$$ $$B = \sqrt{\frac{1.5\times\sum^n_{a=1}B^2_a}{n}}$$

Where \$\sum^n_{a=1}R^2_a\$ is the sum of the red values of each of the adjacent pixels squared. The value of \$n\$ is the number of adjacent pixels (e.g., a corner pixel will have an \$n\$ value of 3, whilst a pixel around the center of the image will have an \$n\$ value of 8).

An adjacent pixel is a pixel which is 1 pixel away from the original pixel in all directions (left, right, up, down and on all of the diagonals).

For example, in the following 3 x 1 image:

The blurred RGB value of the middle pixel will be:

$$R = \sqrt{\frac{1.5*(0^2+0^2)}{2}} = 0$$ $$G = \sqrt{\frac{1.5*(0^2+255^2)}{2}} = 220.836 = 221$$ $$B = \sqrt{\frac{1.5*(255^2+0^2)}{2}} = 220.836 = 221$$

where any decimal outputs are rounded to the nearest unit. You should not simply floor the result.

Therefore, the middle pixel will be the colour (0, 221, 221), or:

Resulting in the image:

You should repeat this process for every pixel in the image. (Note that you do this with the original pixels and not the modified pixels. Basically, you shouldn't overwrite the original image, and should keep it completely separate from the new, blurred image).

If you calculate any values to be greater than 255, assume that its value is 255 (I.e., a value of 374 would be set to 255).

The resulting output should be a separate PNG image (you may name this whatever you wish).

Examples

Super Mario

Original:

Blurred:

Checkerboard

Original:

Blurred:

Crisps

Original

Blurred

Not so crisp anymore

American Gothic

Original:

Blurred:

To see the blur on larger images, it's best to run the program again on the blurred image:

Challenge

The shortest code to blur a given PNG image wins.

You can use image processing libraries (such as PIL) but you must not use built-in blurring functions (Mathematica, I'm looking at you).

Note

As @orlp says below:

For the record, (to my knowledge) this is not a standard blurring method. This challenge is not an educational resource.

\$\endgroup\$
11
  • \$\begingroup\$ I am not really happy with that scaling. n should appear in the denominator. \$\endgroup\$
    – Karl Napf
    Aug 14, 2016 at 14:53
  • \$\begingroup\$ I thought of something very different when I saw "Blunt" :P. \$\endgroup\$
    – Adnan
    Aug 14, 2016 at 15:15
  • 3
    \$\begingroup\$ For the record, (to my knowledge) this is not a standard blurring method. This challenge is not an educational resource. \$\endgroup\$
    – orlp
    Aug 14, 2016 at 15:47
  • \$\begingroup\$ If you had a white pixel surrounded by 8 white pixels (all rgb(255,255,255)), the blurred pixel would be rgb(312,312,312). Are we just supposed to clamp values into the range [0,255]? \$\endgroup\$
    – kamoroso94
    Aug 14, 2016 at 16:46
  • 1
    \$\begingroup\$ @kamoroso94 1: Yes, assume any number greater than 255 is 255. 2: The example image is supposed to represent a 3 x 1 image. \$\endgroup\$
    – Beta Decay
    Aug 14, 2016 at 17:54

2 Answers 2

5
\$\begingroup\$

Python, 354 313 bytes

Not the best, but hey...

Using Space for 1st level indentation, Tab for 2nd level, then Tab+Space and Tab+Tab

import Image as I
A=I.open(raw_input())
w,h=A.size
B=I.new('RGB',(w,h))
s=[-1,1,0]
r=range
for x in r(w):
 for y in r(h):
    P=[]
    for d in s:
     for e in s:
        try:P+=[A.load()[x+e,y+d]]
        except:0
    P.pop()
    B.load()[x,y]=tuple(min(int(.5+(1.5*sum([v*v for v in t])/len(P))**.5),255)for t in zip(*P))
B.save("b.jpg")
  • Edit1: replacing math.sqrt() with ()**.5 thanks to beta decay
  • Edit2: using min for clamping (saving a lot!) and 0 for pass thanks to Loovjo
  • Edit3: +=[] for .append() saving 5 bytes
  • Edit4: using the variable s for the stencil
\$\endgroup\$
11
  • 1
    \$\begingroup\$ Surely n**0.5 is shorter than import math;math.sqrt(n)? Is there a reason for the latter? \$\endgroup\$
    – Beta Decay
    Aug 14, 2016 at 20:18
  • \$\begingroup\$ Yes it is, no there is no reason. I just forgot. \$\endgroup\$
    – Karl Napf
    Aug 14, 2016 at 20:26
  • 2
    \$\begingroup\$ v if v<256 else 255 can be shortened to min(v,255) \$\endgroup\$
    – xenia
    Aug 14, 2016 at 20:48
  • \$\begingroup\$ You can also replace pass with 0 \$\endgroup\$
    – xenia
    Aug 14, 2016 at 20:49
  • \$\begingroup\$ You need to state which image library you're using. If you're using PIL/Pillow (and it looks like you are), the top import statement should read from PIL import Image as I. \$\endgroup\$
    – user45941
    Aug 15, 2016 at 9:22
0
\$\begingroup\$

MATLAB, 130 bytes

Takes an image as an input and saves the output as b.png.

i=double(input(''));m=ones(3);m(5)=0;k=@(x)imfilter(x,m);imwrite(uint8(round((1.5*k(double(i.^2))./k(i(:,:,1)*0+1)).^.5)),'b.png')
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.