5
$\begingroup$

I want to take an image of X resolution, and make a new image of .5X resolution consisting of every other pixel from the original image.

For example, if I had a 10 pixel image:

1 2 3 4 5 6 7 8 9 0

then I'd want the new image to be:

1 3 5 7 9

Is there any way to do such a thing, and output it to a new image file?

$\endgroup$
  • $\begingroup$ maybe related: blender.stackexchange.com/questions/43322/… $\endgroup$ – cegaton Feb 21 '16 at 5:08
  • $\begingroup$ If I understand q correctly, new image would be 2244668800 (or 1133557799) ? $\endgroup$ – batFINGER Feb 24 '16 at 5:15
  • $\begingroup$ Sorry, I fixed the question. I don't want duplicates. I want to split off every other pixel as a new, smaller image. $\endgroup$ – Drudge Feb 24 '16 at 6:23
  • $\begingroup$ If what you need is to make a 10 pixel image a 5 pixel image, just render at 50% the resolution. $\endgroup$ – cegaton Feb 24 '16 at 7:09
  • $\begingroup$ I need the pixels to not be downsampled or altered. I want to split some pixels off to one image, others to another image, without any of their values being changed. $\endgroup$ – Drudge Feb 24 '16 at 9:56
8
+50
$\begingroup$

In your case where you are looking for exactly ½ resolution there is a very simple solution, just use the scale node in the compositor.

This is a 20x20px image; enlarged 16 times (to show detail). Here is the original if you want to try it. original image

Now after going through the scale node, you can see that every other pixel from the original is in the scaled image (again scaled up 16 times).
scaled image

All you have to do is set up the compositor nodes: Image, Scale, and Composite nodes. scale setup in compositor


However if you need every other pixel starting with the second row or column of pixels you can add in a translate node to move the image before you scale it. Then after the scale node move the image back to the center.

This node setup will give you every other pixel starting with the second column. (Use the Y axis for the rows).
scale and translate setup in the compositor


Last set the render size to ½ the resolution of the input image. So for a 10 megapixel image you could type 3872/2 in the resolution X field. In the render tab of the properties window.

$\endgroup$
  • $\begingroup$ That works for getting every other pixel starting with the first of every row. What if I wanted the 2nd of every row? So instead of 13579, if I wanted 24680? $\endgroup$ – Drudge Feb 24 '16 at 23:32
  • $\begingroup$ Just translate your Image by one Pixel first... ;-) $\endgroup$ – Samoth Feb 25 '16 at 10:07
  • $\begingroup$ @Samoth thanks, I had tried that a few days ago but for some reason I did not get it. works well, edited answer. $\endgroup$ – David Feb 27 '16 at 15:48
  • $\begingroup$ @Drudge take a look at the edited answer. $\endgroup$ – David Feb 27 '16 at 15:48
  • $\begingroup$ @David looks good. Could I use this if I wanted every 3rd pixel? Will the translate cause me to lose or gain pixels on the edges? Also, I thought that scale downsampled the image by averaging the 2 pixels it was combining, not by using only the first. Do you know how that works? $\endgroup$ – Drudge Feb 28 '16 at 1:23
6
$\begingroup$

You can use the python PIL (or Pillow for python3) library to do this, or to do this directly in Blender (which is slower but works, and the generated image is directly usable as an image texture or whatever you'd like).

PIL method:

from PIL import Image

imPath = "C:/tmp/0017.png"

im = Image.open( imPath )

half = Image.new('RGB', tuple([ int(d/2) for d in im.size ]) )

for i in range( im.size[0] ):
    for j in range( im.size[1] ):
        if i % 2 == 0 and j % 2 == 0:
            half.putpixel(( int(i/2), int(j/2) ), im.getpixel((i,j)) )

half.show()

Direct blender script:

This method is slower than the PIL solution but not too slow (took me around 2 seconds on my i7 laptop for a 1280x720 pixel image).

It will create a Blender Image Data (bpy.data.images) object and another one for the generated half size image (you can see it in the UV/image editor).

import bpy
from os.path import dirname, basename

imPath = "C:/tmp/x.png" # <== Replace this with the path to your image

bpy.ops.image.open(
    filepath      = imPath,
    directory     = dirname( imPath ),
    files         = [ { 'name' : basename( imPath ) } ],
    relative_path = False
)

origImg = bpy.data.images[ basename( imPath ) ]

half = bpy.data.images.new( 
    "half", 
    int( origImg.size[0] / 2 ), 
    int( origImg.size[1] / 2 ) 
)

pxList      = list( origImg.pixels )
quartets    = [ pxList[i:i+4] for i in range(0, len(origImg.pixels), 4) ]
halved      = [ p for i,p in enumerate( quartets ) if int( i / origImg.size[0] ) % 2 == 0 and i % 2 == 0 ]
half.pixels = [ chan for p in halved for chan in p ]
$\endgroup$
4
$\begingroup$

I don't know if this will be a solution for you, or how you plan to use the final file, but one thing you could do is double up the pixels on one axis. It would visually have the same effect, but of course you are increasing the file size.

Compositor node setup for half-res effect

And you will need to change your Render Resolution to be double on the axis that appears stretched.

Double the pixel count of the original on the Y axis

(In this example the original image was 200x200 pixels)

Here is a close-up of the effect:

Close-up of the half-resolution effect

$\endgroup$
1
$\begingroup$

This method may seem a little on the manual side of things, however the verification and adjustment feedback are very real-time, and common place.

You can also use UV Mapping, you would just have to map each face to every other pixel, and set your camera to orthographic mode (had to set orthographic scale to 5.0 - See y resolution limitation for reason below).

For this image the two mesh objects are 5x1 units. The camera minimum resolution in y is 4px, so had to make res 4x20, but set the factor to 25%.

Then you can just render out to Image.

Note: Use cycles (Blender Internal results are not pretty) with image texture plugged into an emission shader with strength set to 0.5, with no lamp in the scene.enter image description here

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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