Bash, c++, Snapfish: Batch add borders to images to make-up the 4R ratio

Programming: [more]Programming: [more]

Today I used a couple of bash commands, a small C++ program, and ImageMagick to add borders to images to get them into the 3:2 ratio of 4R. I need them at this size because I don't want them auto-cropped, and I want them photo printed (via snapfish).

All my images are in one directory, and they're all jpgs (with extension .jpg). They're mostly different sizes and shapes, portrait and landscape.

The identify command from ImageMagick lets us query the resolution of the image, and writes the result to stdout:

identify image.jpg

results in:

image.jpg JPEG 1224x1632 1224x1632+0+0 DirectClass 8-bit 610.512kb

being printed in the shell.

 

We need just the name, and the resolution, and we need this for all images in the directory:

for i in `ls *.jpg` ; do
indentify $i | cut -f1,3 --delimiters=' ' >> list
done

The file list will now contain something like:

image1.jpg 1224x1632
image2.jpg 600x600
image3.jpg 1280x776

Which is succinct enough for us to work with.

 

Next we need to calculate the size of the border to add vertically or horizontally to the image. Because my bash scripting knowledge is limited, I'm using C++ for the next part. This step is:

read each line of the file, convert 1280x776 into it's x and y components.
Decide whether we're growing horizontally or vertically
calculate the new border in that direction
generate the ImageMagick command line to perform the operation

 

The C++ is here:

		#include 
	#include 
	#include 
	#include 
	#include 
	using namespace std;
	const double XRAT = 3.0;
	const double YRAT = 2.0;
	struct str_res {
	string name;
	int x, y;
	};
	void delete_str_res( str_res *in) {
	delete in;
	}
	void conversion_string( str_res *in) {
	bool bSwap = in->y > in->x;
	if (bSwap) {
	swap(in->y, in->x);
	}
	int newy = max( in->y , (int) (((double) in->x) * XRAT / YRAT ));
	newy-= in->y;
	newy/=2;
	if (bSwap) {
	swap(in->y, in->x);
	}
	cout << "convert " 
	<< in->name 
	<< " -bordercolor white -quality 95 -border " << (int) (bSwap ? newy : 0 )
	<< "x" << ((int) bSwap ? 0: newy )
	<< " " << in->name << "_resize.jpg" << endl;
	}
	int main (int argc, char **argv) {
	vector< str_res * > imgs;
	string res;
	ifstream ifs("./list"); // closed when out of scope , hardcoded
	while (ifs.good()) {
	str_res *str = new str_res;
	ifs >> str->name;
	if (str->name.empty()) {
	continue;
	}
	ifs >> res;
	replace( res.begin(), res.end(), 'x', ' ');
	istringstream cnv(res);
	cnv >> str->x;
	cnv >> str->y;
	imgs.push_back( str );
	}
	for_each( imgs.begin(), imgs.end(), conversion_string);
	for_each( imgs.begin(), imgs.end(), delete_str_res );
	return 0;
	}
	
	

 

The output needs to be redirected, as per:

./make_up_photo_proportions > run_list

run_list will contain a conversion command line for each image:

convert image1.jpg -bordercolor white -quality 95 -border 612x0 image1.jpg_resize.jpg
convert image2.jpg -bordercolor white -quality 95 -border 0x150 image2.jpg_resize.jpg
convert image3.jpg -bordercolor white -quality 95 -border 0x572 image3.jpg_resize.jpg

Run this with bash ./run_list. The new files will populate alongside the old.

 

The last step is to send these to Snapfish. Luckily, snapfish provides an email interface, so we don't have to deal with uploading these via the web.
Tips:

  • It's probably best if you try this a couple of times manually first, before scripting it. Make sure your photos get into your account, and don't need confirmation (there's an option, after you email your first photo through).
  • There's a 5MB limit per email (I think), and it takes a few minutes, so be patient. Your email address (From) should correspond to your snapfish login.
  • I think this is all ok, w.r.t. the Terms and conditions of the service, but verify this for yourself, especially if you'll use this interface heavily.

In gentoo the command line mailing package which suits this best is mutt (I tried mailx and uuencode / mimencode, but their mails weren't picked up by Snapfish):

emerge mutt

To mail them off (again, try this with 1 before running the for loop):

for i in `ls *_resize.jpg` ; do
echo $i > body.txt
mutt -s "$i" -a $i save@snapfish.com < body.txt
sleep 15
done

The sleep 15 throttles our mail sending here.

 

After this completes, log in to your snapfish account, and order your prints.

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.