Skip to main content
New Participant
December 8, 2016
Answered

How do I loop and fill pixel-by-pixel

  • December 8, 2016
  • 4 replies
  • 4891 views

Hello

I'm new to photoshop scripting so this might be a simple question to answer but after searching the internet for a couple of hours I thought I try out this forum.

I'm trying to create a white noise texture with 'perfect distribution', i.e. that each pixel/texel in a 16x16 bitmap has a unique grayscale value (0 to 255). So I was thinking maybe I could write a script using photoshop. For that to work I would need to get control of the pixel data, traverse it and fill each pixel individually.

Is this possible?

I did read that I could use Bridge SDK, Set each pixel randomly to one of five pre-defined colors . But that seems to be an old post aimed for CS6 and I'm using CC 2015 so I'm not sure I can use that SDK anymore.

So does anybody know is this possible with Photoshop scripting or should I better use some other tool? In that case what tool?

Thanks!

This topic has been closed for replies.
Correct answer mutagenicpixels

Alternatively you can use the same bridge script you referenced but modified a bit:

#target bridge 

var bitmap = new BitmapData(16, 16);

var output = new File(Folder.desktop + "/Bitmap Test File.jpg");

var colours = [];

function createColours(){

    for(var i = 0; i < 256; i++){

        var hex = i.toString(16);

        var colourVal = hex.length == 1 ? "0" + hex : hex;

        colours.push(String('#' + colourVal + colourVal + colourVal));

    }

    shuffle(colours);

}

function shuffle(array){

    var i = array.length;

    var j = 0;

    var tempVal;

    while (i--) {

        j = Math.floor(Math.random() * (i + 1));

        tempVal = array;

        array = array;

        array = tempVal;

    }

    createImage(array);

}

function createImage(shuffledColours){

    var step = 0;

   

    for(var y = 0; y < bitmap.height; y++){ 

        for(var x = 0; x < bitmap.width; x++){

            bitmap.setPixel(x, y, shuffledColours[step]);

            step++;

        } 

    }

    bitmap.exportTo(output, 100);

}

createColours();

This results in an image like this:

Of course this is scaled up beyond 16px

4 replies

Jarda Bereza
Inspiring
December 11, 2016

If you normaly work with C++ you could be interested in Photoshop SDK

In examples is "disolve filter" and you can modify code and set to layer any pixels you want.

It should be faster than anything else and you can apply this filter to smart object and so on.

This example supports 8bit, 16bit and 32bit per channel and also CMYK.

13923292_1302261026470379_7817625681848121845_o.jpg?oh=4e0897a7e2e8d8c1452da9b2a56e552f&oe=58E8D10A

And there are also examples for file-formats. So you can open/save your custom file-format.

Inspiring
December 10, 2016

You can also write the data with binary encoding to a raw file using File.write(), and then open the raw image and save it in whatever format you wish.

mutagenicpixelsCorrect answer
Inspiring
December 8, 2016

Alternatively you can use the same bridge script you referenced but modified a bit:

#target bridge 

var bitmap = new BitmapData(16, 16);

var output = new File(Folder.desktop + "/Bitmap Test File.jpg");

var colours = [];

function createColours(){

    for(var i = 0; i < 256; i++){

        var hex = i.toString(16);

        var colourVal = hex.length == 1 ? "0" + hex : hex;

        colours.push(String('#' + colourVal + colourVal + colourVal));

    }

    shuffle(colours);

}

function shuffle(array){

    var i = array.length;

    var j = 0;

    var tempVal;

    while (i--) {

        j = Math.floor(Math.random() * (i + 1));

        tempVal = array;

        array = array;

        array = tempVal;

    }

    createImage(array);

}

function createImage(shuffledColours){

    var step = 0;

   

    for(var y = 0; y < bitmap.height; y++){ 

        for(var x = 0; x < bitmap.width; x++){

            bitmap.setPixel(x, y, shuffledColours[step]);

            step++;

        } 

    }

    bitmap.exportTo(output, 100);

}

createColours();

This results in an image like this:

Of course this is scaled up beyond 16px

5imonBAuthor
New Participant
December 9, 2016

Thanks for the good answer!

I liked the 2nd implementation better as it's faster. Your code outputs to jpg. The documentation seemed to indicate that BitmapData could output to PNG's as well but I didn't manage to get that working.

I did see some compression artifacts even with 100% quality, see colour levels. Not a big deal but preferably I would like to get a perfect result

Inspiring
December 9, 2016

The exportTo() only saves in JPG format according to documentation. You can change the file name on line 4 from ".jpg" to ".png" and that seems to change the filetype but it's probably still under JPG compression. I'm curious as to what you're going to use this for

Also, would you mark my code reply as answering your question?

Thanks!

Inspiring
December 8, 2016

Assuming that you're only using a 16x16 px canvas

var doc = app.activeDocument;

var fillColor = new SolidColor();

var step = 0;

for(var y = 0; y < 16; y++){

    for(var x = 0; x < 16; x++){

        doc.selection.select([[x, y], [x, y + 1], [x + 1, y + 1], [x + 1, y]], SelectionType.REPLACE);

        fillColor.rgb.hexValue = String(toHex(step) + toHex(step) + toHex(step));

        doc.selection.fill(fillColor);

        step++;

    }

}

doc.selection.deselect();

function toHex(c) {

    var hex = c.toString(16);

    return hex.length == 1 ? "0" + hex : hex;

}

Of course the 16x16 canvas has 256 total pixels and there are only 256 greyscale values to fill it so it becomes a gradient