Thursday, September 14, 2017

adobe photoshop - Advice on batch exporting sections of an image


I have a large PSB file (33600x19200px) and I need to write a script to export sections of this image as a series of images. What would the best approach be ?


Initially I thought about scripting slices and exporting, but Save for Web is diabled for this resolution.


Another option I thought was this:



  1. loop through each section I need to export

  2. make a selection


  3. copy pixels

  4. create a new document

  5. paste pixels

  6. save for the web with the format and name I need

  7. close the document without saving

  8. goto 1


Is this the best approach ? What are your suggestions ?


Update:


Here's my script with the steps above:



#target photoshop

var doc = app.activeDocument;
var sel = doc.selection;//main document selection
var rows = 70;
var cols = 40;
var cell = 240;//size of a cell/display image/region of interest
var space=240; //space in between cells
var dname = doc.name.substr(0,doc.name.length-4);
var dir = doc.path.toString()+"/";

var dpi72 = 182.88036576073152146304292608585;
var options = new ExportOptionsSaveForWeb();
options.format = SaveDocumentType.JPEG;
options.quality = 75;

//*
for(var y = 0; y < cols; y++){
for(var x = 0 ; x < rows; x++){
var xpos = (x * (cell+space))+((1-y%2) * space);//+ di-grid offset
var ypos = (y * (cell+space));


try{

sel.select([[xpos,ypos],[xpos+cell,ypos],[xpos+cell,ypos+cell],[xpos,ypos+cell]],SelectionType.REPLACE,0,false);
sel.copy(true);

var nname = dname + "_"+((x+1)) + "_" + ((y+1));
//$.writeln("["+x+"]["+y+"]" +nname +"\n"+sel.bounds);
//*
var small = app.documents.add(cell,cell,dpi72,dname,NewDocumentMode.RGB,DocumentFill.WHITE);


app.activeDocument = small;

small.paste();
small.exportDocument (new File(dir + "/" + nname + ".jpg"), ExportType.SAVEFORWEB, options);
small.close(SaveOptions.DONOTSAVECHANGES);

app.activeDocument = doc;
//*/
}catch(err){

x = rows;
y = cols;
alert(err);
}
}
}

The script works, but it's a bit slow. Is my approach ok or is there a faster way to do this ?



Answer



This should be a lot faster. Instead of copy and pasting into a new file hundreds of times, it does this:




  1. Makes the Background into a Layer.

  2. Reduces the Canvas size down to the cell size.

  3. Slides the Layer around 'under' the Canvas to the correct location.

  4. Does a "Save For Web" essentially the same as your script.

  5. Go to 3 and repeat, then stop when it runs out of pixels to nibble on.


It calculates the number of Cells per row, as well as the number of rows. No pre-configuration is needed!


There are some variables you can set at the beginning of the file should you ever need to.




NOTE: The script assumes that you start with a flattened file, and MAKE SURE YOU HAVE A BACKUP COPY of your artwork just in case anything goes wrong.



On my machine at work (absolutely nothing fancy or powerful, just a beater PC) it created the 350 tiles of your sample file in about 6 minutes. You can help the speed by hiding the Tools and Pallets (by pressing Tab) before running the script. Also, minimizing Photoshop while the script runs seems to help a bit too.


// Alter these as needed
var cellWidth = 240; // The width, in px, of your image cell
var cellHeight = 240; // The height, in px, of your image cell
var xOffset = 240; // The space, in px, between each cell in a row
var yOffset = 240; // The space, in px, between each row. Set to 0 for traditional checker board effect
var options = new ExportOptionsSaveForWeb();
options.format = SaveDocumentType.JPEG;

options.quality = 75;

// Don't change these unless you know why you should! :)
var doc = app.activeDocument;
var dname = doc.name.substr(0,doc.name.length-4);
var dir = doc.path.toString()+"/";
var rowShift = true;
var imageWidth = activeDocument.width.as('px');
var imageHeight = activeDocument.height.as('px');


// Store the current rulerUnits for later. We're going to change
// it to pixels for now, and we want to change it back later.
var myRulerUnits = app.preferences.rulerUnits;

// Set rulerUnits to pixels
app.preferences.rulerUnits = Units.PIXELS;

// Find the "Background"
var layerRef = doc.artLayers.getByName("Background");


// Set our "Background" to be a Layer
layerRef.isBackgroundLayer = false;

// Reduce the Canvas size to our cell size
doc.resizeCanvas(cellWidth, cellHeight, AnchorPosition.TOPLEFT);

var totalOffset = 0;
var xMovement = 0;

// Do the magic

for (var y = 0; y < numberOfRows(); y++)
{
totalOffset = 0;

for (var x = 0; x < numberOfCells(); x++)
{
if (x == 0)
{
xMovement = (rowShift) ? xOffset : 0;
}

else
{
xMovement = cellWidth + xOffset;
}

totalOffset += xMovement;

// Offset the layer into our Canvas "window"
layerRef.applyOffset(-(xMovement), 0, OffsetUndefinedAreas.WRAPAROUND);


saveCell(x,y);
};

// Offset the layer back to the left and down one row
layerRef.applyOffset(totalOffset, -(cellHeight + yOffset), OffsetUndefinedAreas.WRAPAROUND);

// Flip the rowShift. If it was true, make it false and vice versa.
rowShift = !rowShift;
};


// Calculate number of cells per row. May change depending in rowShift, etc
function numberOfCells()
{
var theWidth = imageWidth;

if (rowShift == true)
{
var theWidth = theWidth - xOffset;
}
return Math.floor((theWidth + xOffset) / (cellWidth + xOffset));

}

// Calculate number of rows
function numberOfRows()
{
return Math.floor((imageHeight + yOffset) / (cellHeight + yOffset));
}

// Pad the cell x and y numbers for proper sorting
function pad(num, size)

{
var s = "000000000" + num;
return s.substr(s.length-size);
}

// Actually save, or really "Save For Web" the cell
function saveCell(x, y)
{
var nname = dname + "_" + pad((x + 1), 3) + "_" + pad((y + 1), 3);


doc.exportDocument (new File(dir + "/" + nname + ".jpg"), ExportType.SAVEFORWEB, options);
}

// Reset the ruler units
app.preferences.rulerUnits = myRulerUnits;

No comments:

Post a Comment

technique - How credible is wikipedia?

I understand that this question relates more to wikipedia than it does writing but... If I was going to use wikipedia for a source for a res...