You call it Centering, I call it Code Golf

16

"Let's face it, aligned images are like little gifts from Heaven. Welcome, but unexpected." - Geobits

+10000 reputation to whoever wins this challenge.

Rules:

1) You are to generate a program.

2) Input will be an image, however whether it is passed as a file or a list of numbers is up to you.

3) Output will be a file which when opened in paint (or similar) will show the image aligned.

4) The canvas size will always be between 100 x 100 and 2000 x 2000 pixels. It will always be a rectangle, but not always a square.

5) No hard coding of images or funky URL magic.

6) No external libraries to be used.

Guide to Centralisation (Joshpbarron Variant)

An image will be defined as centered if the 1st white(255,255,255,>0 rgba) or transparent(x,y,z,0 rgba) on an axis is equal distance (plus or minus 1 pixel) from the edge of the canvas.

This can be achieved (and will be verified by) the following method.

1) Imagine a bounding box around the object. (Black lines added for help)

enter image description here

2) Move the object around until the edge of the object is equal distance from the appropriate edge of the canvas.

enter image description here

3) Now forget the black lines.

enter image description here

Input:

enter image description here

Output:

enter image description here

More inputs here.

And respective outputs here.

The +10000 rep is a lie.

Joshpbarron

Posted 2015-05-05T12:50:42.600

Reputation: 787

should the program handle completely white/transparent images? – Cristian Lupascu – 2015-05-06T09:23:22.310

As there is nothing to center, the same image should be returned. Same for images with no empty space. – Joshpbarron – 2015-05-06T09:39:20.373

You should add some specifics on the images that this should work for. For example should it work for an image that contains a mostly white background but has holes of transparency? Or does having transparency mean there will be no white, and vice versa. – bubalou – 2015-05-07T15:06:14.630

Sorry, but the explanation is obvious. RBGA codes are given. – Joshpbarron – 2015-05-07T18:34:51.433

In the description, you talk about the distance of the 1st white/transparent pixel from an edge. Don't you mean the first non-white? Otherwise all the sample inputs are already solutions, because the distance of the first white pixel from each edge is 0, so those distanced are all equal. – Reto Koradi – 2015-06-06T15:33:50.050

Answers

0

Python 3, 120 205 bytes

EDIT : As the output image must have the same size as the input, the script gets longer ...

EDIT2 : It seems that the rule 6 (no external library) has been added after I answered, so this answer is to be considered invalid anyway :(

from PIL.Image import*;from PIL.ImageOps import*
c='RGB';i=open(input()).convert(c);w,h=i.size
o,a=new(c,(w,h),'white'),i.crop(invert(i).getbbox())
e,f=a.size;o.paste(a,((w-e)//2,(h-f)//2));o.save('o.png')

The former version just cropped the input image:

from PIL.Image import*;from PIL.ImageOps import*
i=open(input()).convert('RGB')
i.crop(invert(i).getbbox()).save('o.png')

both scripts read the image file name from stdin, and saves the output image as 'o.png'. for example :

python3 script.py <<< s2rMqYo.png

It accepts at least PNG images (potentially with an alpha channel) -- Tested 'ok' on the set provided by the asker.

...waiting for my reward ):

dieter

Posted 2015-05-05T12:50:42.600

Reputation: 2 010

1I can't test this at the minute, but does the output canvas size match the input canvas size? – Joshpbarron – 2015-05-05T14:55:11.013

1pro tip for your future shell endeavors: python3 script.py <<< s2rMqYo.png is cleaner – undergroundmonorail – 2015-05-05T15:05:06.373

@undergroundmonorail thx ! – dieter – 2015-05-05T15:31:15.247

@Joshpbarron : no it doesn't .. but it wasn't asked to be so, was it ? – dieter – 2015-05-05T15:33:23.097

All the output images are. – Joshpbarron – 2015-05-05T15:37:31.397

Would you state that keeping the same size is mandatory ? – dieter – 2015-05-05T15:49:27.657

If you must not keep the same size, then just cut all the white space, what remains is centered. – edc65 – 2015-05-05T16:08:54.060

sure, that's what my answer actually does – dieter – 2015-05-05T16:13:41.610

1The output must be the same size as the input, yes. – Joshpbarron – 2015-05-05T16:28:17.327

3You're using a library (PIL), which is not allowed. (PIL cannot be called part of the standard libraries, because it is not included with Python by default.) – marinus – 2015-05-05T16:33:55.740

2@marinus I think that this is a bit harsh.. That alienates a huge number of programming languages. – Beta Decay – 2015-07-06T19:34:22.860

2

HTML5 + JavaScript (ES5), 515 bytes

That count includes the HTML tags as they are part of the program. If you only count the image processing code, it is 376 bytes including the function wrapper.

<canvas id=o></canvas><script>f=function(p){o=new Image();o.crossOrigin='Anonymous';o.src=p;o.onload=function(){v=document.getElementById('o'),c=v.getContext('2d');v.width=l=w=o.width;v.height=t=h=o.height;c.drawImage(o,0,0);for(k=255,d=c[g='getImageData'](0,0,w,h).data,r=b=i=0;i<d.length;)if((d[i++]<k||d[i++]<k||d[i++]<k)&&d[i++]){x=i/4%w;y=~~(i/4/w);l=l<x?l:x;t=t<y?t:y;b=b>y?b:y;r=r>x?r:x}n=c[g](l,t,r-l+1,b-t+1);c.clearRect(0,0,w,h);c.putImageData(n,(w-r+l)/2,(h-b+t)/2)}}</script><input onblur=f(this.value)>

Input

A URL to an image.

Security restrictions

Because this program is running in a browser environment, only URLs to CORS-enabled images will work. Imgur is CORS enabled.

IE 10 does not support CORS. I haven't tested in IE 11 yet but it does work in Chrome and Firefox.

How to run

  1. Type/paste in a URL into the input field.
  2. De-focus (tab/click out of) from the input field.

Output

It outputs on the canvas on the page.

As this is a browser-based application, security restrictions prevent automatic download of a file but you can right click and save image in Chrome and Firefox. I haven't tested on IE 11 yet.

Demo

JavaScript code has been removed from the script element and put into the appropriate area to accommodate Stack Snippets:

f = function(p) {
  o = new Image();
  o.crossOrigin = 'Anonymous';
  o.src = p;
  o.onload = function() {
    v = document.getElementById('o'), c = v.getContext('2d');
    v.width = l = w = o.width;
    v.height = t = h = o.height;
    c.drawImage(o, 0, 0);
    for (k = 255, d = c[g = 'getImageData'](0, 0, w, h).data, r = b = i = 0; i < d.length;)
      if ((d[i++] < k || d[i++] < k || d[i++] < k) && d[i++]) {
        x = i / 4 % w;
        y = ~~(i / 4 / w);
        l = l < x ? l : x;
        t = t < y ? t : y;
        b = b > y ? b : y;
        r = r > x ? r : x
      }
    n = c[g](l, t, r - l + 1, b - t + 1);
    c.clearRect(0, 0, w, h);
    c.putImageData(n, (w - r + l) / 2, (h - b + t) / 2)
  }
}
<canvas id=o></canvas>
<input onblur=f(this.value)>

rink.attendant.6

Posted 2015-05-05T12:50:42.600

Reputation: 2 776

Confirmed working in Edge. I imagine it'd work in IE11 as well. – Alex Van Liew – 2015-08-05T22:24:24.047

0

Processing 2 - 323 450

Image is read from the file f.png in the data folder of the sketch. Places the image and determines it's bounds. Calculates the correct position and replaces the image shifted correctly.

PImage p=loadImage("h.png");int a,b,c,d,x,y,w,i,n,m,t;a=w=p.width;c=i=p.height;clear();size(w,i,P2D);x=y=b=d=t=0;image(p,0,0);loadPixels();while(x<w*i){if(pixels[x]==color(255))t=1;x++;}x=0;background(255);image(p,0,0);loadPixels();while(y*w+x<w*i){if(pixels[y*w+x]!=color(255)){if(x<a)a=x;if(x>b)b=x;if(y<c)c=y;if(y>d)d=y;}x++;if(x==w){x=0;y++;}}n=(w-(b-a))/2;m=(i-(d-c))/2;clear();if(t>0)background(255);image(p,n-a,m-c);loadPixels();save("g.png");

readable version:

PImage p=loadImage("h.png");
int a,b,c,d,x,y,w,i,n,m,t;
a=w=p.width;
c=i=p.height;
clear();
size(w,i,P2D);
x=y=b=d=t=0;
image(p,0,0);
loadPixels();
while(x<w*i)
{
 if(pixels[x]==color(255))t=1;
 x++;
}
x=0;
background(255);
image(p,0,0);
loadPixels(); 
while(y*w+x<w*i)
{
 if(pixels[y*w+x]!=color(255))
 {
   if(x<a)a=x;
   if(x>b)b=x;
   if(y<c)c=y;
   if(y>d)d=y;
 }
 x++;
 if(x==w){x=0;y++;}
}
n=(w-(b-a))/2;
m=(i-(d-c))/2;
clear();
if(t>0)background(255);
image(p,n-a,m-c);
loadPixels();
save("g.png");

Example output:

enter image description hereenter image description hereenter image description here enter image description here enter image description here

You can get processing here

bubalou

Posted 2015-05-05T12:50:42.600

Reputation: 305

Could you please provide a sample output file for me to compare. – Joshpbarron – 2015-05-06T22:03:49.353

It's nice...but not quite. The input images have a transparent background. – Joshpbarron – 2015-05-07T08:07:30.287

1"Image is read from the file f.png". Really? In your code, I see this line: PImage p=loadImage("h.png"); at the very top. – SirPython – 2015-07-06T17:21:05.180

color(-1) and background(-1) are each 1 byte shorter than color(255) and background(255) respectively. And I think you can remove the P2D in the size call – user41805 – 2017-04-23T15:43:08.550