Sips is a lifesaver!

I just recently found out that macOS comes with a terminal-based batch processing application called sips, the scriptable image processing system.

One thing I found out I can do is write:

for i in *.NEF; do sips -s format jpeg $i --out "${i%.*}.jpg"; done

And convert all files in a directory from Nikon Raw files to jpeg.

Another useful option is

sips -Z 1000 *.jpg

This changes the size of all the images in a directory so that the longest size is 1000px at maximum, note that this will overwrite the files with the new resized files, so be sure to work on a copy of the directory and not the original.

What week is this?

Today I was a bit impulsive and registered the domain name weeknum.org.

Then I made a little php-application showing the day of the week, with the background color calculated using the week number, month and day to create a hex code.

I might even try out some AJAX and jQuery on this page and see if I can make it a little more stylish and interactive.

If you want to check start and end dates of another week number, just add the suffix /[week number] to the URL.

For example, if you want to find information about week number 42, then go to weeknum.org/42.

Logo, Website, WordPress and Menu Items

Designing logos and setting up websites is starting to get a routine.

Today I was asked by my boss to set up the website www.bellonordic.no, he had a few logo design suggestions and a general idea of the website layout.

It seems one of my earlier designs caught on since his new design suggestion hinted toward having three “mountains” in the background, so all I had to do was slightly alter my design, create a few alternative logos and I was done.

 

Then I had to set up the WordPress site. So I picked a theme, dug up some stock photos for menu items and used the art-boards to keep a consistent design.

I really wish Serif would release their upcoming desktop publishing tool “Affinity Publisher”, as much as I like Affinity Designer, I’d prefer to use more proper layout tools when doing layout work.

Column Switcher

Yesterday I met a problem where I needed to replace the columns of a csv-file separated by whitespace, since this was some pretty basic stuff I wrote a simple program in Java fairly easily.

Today when I woke up I thought that maybe I should try and see how I could do the same with Shell Scripting, so here goes (the programs are available at my github here):

import java.util.Scanner;
import java.io.*;

public class Cols {

    /**
     * This program takes a csv file separated by whitespace and replaces the first with the second column.
     * @name Cols
     * @author tcarisland
     * @date 6.sep.2017
     */

    public static void main(String args[]) {
	try {
	    Scanner in = new Scanner(new File(args[0]));
	    PrintWriter out = new PrintWriter(new File(args[1]));
	    while(in.hasNextLine()) {
		String cols[] = in.nextLine().split("\\s+");
		if(cols.length > 1)
		    out.println(cols[1] + " " + cols[0]);
	    }
	    in.close();
	    out.close();
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

}

 

And the Bash program:

 

#/bin/bash

#A minimal version of the cols program to do exactly the same as the java program.
#Needs two arguments.

rm -f $2 && touch $2;

while IFS=" " read c1 c2
do
    echo $c2" "$c1 >>$2;
done < $1

HashMapMaker

While working on a problem today I found I wanted to simplify the process of creating predefined HashMaps.

So I made this little utility program to take two files and create a HashMap<String, String> from such a file.

Nothing much, but I put it up on my GitHub here nonetheless.

import java.util.Scanner;
import java.io.*;

public class HashMapMaker {

    /**
     * A simple program that creates a HashMap from a file with fields separated by whitespace.
     * @name HashMapMaker
     * @author tcarisland
     * @date 5.sep.2017
     */
    
    public static void main(String args[]) {
	try {
	    Scanner in = new Scanner(new File(args[0]));
	    PrintWriter out = new PrintWriter(new File(args[1]));
	    out.println("private static final Map<String, String> m = new HashMap<String, String>() {{");
	    while(in.hasNextLine()) {
		String pair[] = in.nextLine().split("\\s+");
		if(pair.length > 1)
		    out.println("put (\"" + pair[0] + "\", \"" + pair[1] + "\");");
	    }
	    in.close();
	    out.println("}};");
	    out.close();
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }
    
}

GlyphSize – an SVG resizing tool.

Click here to download the program.

As I’ve learned how to create fonts using Affinity Designer and FontForge, I’ve come across a few situations that require unnecessary monkey work. With some experimenting I’ve found that the simplest way to export multiple curves from Affinity Designer into Fontforge is to use the Export Persona in Affinity Designer and export curves as SVG files.

Note: Because macOS and newer operating systems are extremely paranoid these days, this program will not be able to run unless you set the security settings to allow running programs from “Anywhere”. To make matters worse – newer versions of macOS have completely removed this option. To disable this child protection lock, just follow these instructions. Be aware though, that running programs from “anywhere” is a security risk, but still necessary since both Apple and Microsoft will raise a red flag for very common applications if that particular application is something they don’t sell in their “App Store” or “Microsoft Store”.

The problem here is that when exporting the slices, the viewbox height and width is set to the size of the curve and this will cause FontForge to resize the letter you designed to fit the Glyph.

To fix this problem I made a simple Java batch processing application that resizes the viewbox to a square canvas to the size of your liking.

This application is based on my own workflow which means that to understand the why and how, a tutorial explaining how I design a font is necessary.

Step 1: Design the font in a large Affinity Designer document.

I start out with a canvas the size of an individual glyph, since I prefer working with TrueType fonts, I select a size of 2048X2048px (or 1024X1024px), and define a descender, x-height and ascender by creating semi-transparent coloured rectangles.

Screen Shot 2017-06-08 at 16.39.03

After this, I make the document larger (using “anchor to page” – not “resize”) so as to fit multiple glyphs and design all my characters.

A font designed in AD (Affinity Designer) looks something like this:

designedfont

Step 2: Resize the document

(if you didn’t design the letters according to the proper glyph size). 

If I want to change the size of the letters after this (if – for example, you find you want the cap height to be lower than the ascender – which is common in fonts since some space is required for accents in characters such as “Å” “Ë” and “Ú”, you can create a new document with the desired glyph size (in this case 2048).

2048

After this you select two characters, one upper case (such as A) and one lower case with a descender (such as g, y, p or q), place the g so that it comes at a tangent to the bottom of the canvas and use this to find the baseline, then place the upper case letter (A) on the baseline.

You can now group these together and resize the characters, after resizing them you need to change the position of the baseline.

Ag

With the resized letters, copy one of the selected letters into the document, and compare the height of these letters.

AAg

In the “Transform” window, you can see that the smaller letter has a height of “1344px” and the taller one has a height of “1536px”, with this information you find the the factor you want to resize the document to. My document has a width of 16348px, I can then calculate: 16348 * (1344/1536) = 14304 (approximately, the answer needs to be an integer).

I note this down in my document so that I can resize my document back to its original size if I want.

note

Step 3: Export the individual glyphs using the export persona.

With the document and letters set according to the right size so that they fit into a predetermined em-size (this is what it’s called in FontForge). Select the export persona (also make sure that all letters are in the form of a single curve, use the boolean “add” operation to create a union of all the overlapping shapes).

Export

In the layers tab – select all the relevant curves (all letters, numbers and symbols you want to export), and click “create slice”, the slices should be set to the “SVG” file format, but none of the SVG presets in AD have the correct settings, so I suggest you create a new Preset called something like “GlyphExport”.

The settings for exporting the glyphs are:

  • The “Set viewBox” should be checked
  • File format should be set to “SVG”
  • “Rasterise:” should be set to “Nothing”

Then click Export slices into a separate directory of your choice.

I normally name the directory “glyphs” and put them into a project directory along with the AD document file.

Step 4: Resize the viewBox using GlyphSize.

With the glyphs exported, you can open the folder and see how they look like.

Note: If you planned well, you should have renamed the “curves” in AD to their appropriate letter. When the curves have names, this becomes their filename instead of just “slice1.svg”, “slice2.svg” etc.

My lettering scheme for individual letters is taken from the FontForge Glyph Names, other than that, I name upper case letters according to their letter – so “A” is named simply “A”, but lower case letters have the l-suffix so that “a” is named “al”, this makes importing into FontForge a lot easier.

You can download the GlyphSize program here.

At the moment (June 8 2017), the program looks a little something like this:

Screen Shot 2017-06-08 at 17.04.07

To select your directory, just click the “Choose Folder” button and locate your directory, you can either click the directory and click “choose”, or click on any file inside the directory and it will automatically select the directory that the file is in.

Screen Shot 2017-06-08 at 17.06.05

With the directory selected, all there is left is to supply the desired em-size (labeled GlyphSize) and click “Resize Items”, it will create a directory within that directory named “resized”, take every SVG-file within that directory and write a copy of that SVG file with the desired canvas size.

Screen Shot 2017-06-08 at 17.06.12

Step 5: Import into FontForge.

The individual SVG files are now ready to be imported into FontForge, use the “Ctrl + I” as a hotkey for faster access to the Import dialog.

If you followed Step 1 or Step 2 and made a semi-transparent rectangle representing the descender and baseline, you can use the height of this rectangle as the “Descent” in Element=>Font Info=>General, after this you can fill in the Ascent by calculating 2048 – 450 = 1598.

Do this before you import your SVG files.

Screen Shot 2017-06-08 at 20.10.25

Write in C

The last couple of months has been all about Calculus, Agorithms and Datastructures, Data modelling with Object Role Modelling and SQL.

After finally getting familiar with the basics of PostgreSQL I found myself curious about using the MySQL databases supplied by my web hosting service, and today I got around to making a program to insert .csv files (with whitespace as delimiter) into my own tables.

As an added challenge I thought I’d use C rather than Java, which means I had to use sscanf instead of split to collect individual integers from an input file separated by whitespace.

This bit of code reads an input file, calculates the size of the file, the number of rows and columns and then proceeds to read the entire file. It then uses sscanf to collect each integer now that we know the number of rows and columns and then creates an sql script based on that information.

There’s probably an easier way of doing this, but in my experience, always looking for shortcuts takes time, so I might as well just use what I know already to get the job done:

 

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define pline printf("\n")

void tsize(char filename[], int ans[]);

int main(int argc, char *argv[]) {
if(argc < 4) {
   printf("too few arguments");
   return -1;
}
char *typename = argv[3];
int tablesize[4];
bzero(tablesize, sizeof(int) * 4);
tsize(argv[1], tablesize);
int row, col, i, q, inp, siz, pos, totalpos;
row = col = i = q = inp = siz = pos = totalpos = 0;
col = tablesize[0];
row = tablesize[1];
siz = tablesize[2];
int table[row][col];
FILE *in = fopen(argv[1], "r");
char *text = malloc(sizeof(char) * siz);
bzero(text, sizeof(char) * siz);
while((inp = fgetc(in)) != EOF) {
   text[i++] = inp;
}
fclose(in);
for(i = 0; i < row; i++) {
   for(q = 0; q < col; q++) {
      int val = 0;
      sscanf(text + totalpos, "%d%n", &val, &pos);
      totalpos += pos;
      table[i][q] = val;
}
}
FILE *out = fopen(argv[2], "w");
fprintf(out, "CREATE TABLE rammepris (\n");
fprintf(out, "meterpris INT NOT NULL,\n");
fprintf(out, "halvmaal INT NOT NULL,\n");
fprintf(out, "utpris INT NOT NULL,\n");
fprintf(out, "rammetype VARCHAR NOT NULL UNIQUE,\n");
fprintf(out, "PRIMARY KEY(meterpris, halvmaal)\n");
fprintf(out, ");\n");
for(i = 1; i < row; i++) {
   for(q = 1; q < col; q++) {
      int meterpris = table[i][0];
      int halvmaal = table[0][q];
      fprintf(out, "INSERT INTO rammepris(meterpris, halvmaal, utpris, rammetype) \   
      values(%d, %d, %d, %s);\n", meterpris, halvmaal, table[i][q], typename);
   }
}
fclose(out);
}

void tsize(char filename[], int ans[]) {
FILE *in = fopen(filename, "r");
int col, inp, siz;
col = inp = siz = 0;
while((inp = fgetc(in)) != EOF) {
   ans[2]++;
   if(inp == ' ' || inp == '\n')
      col++;
   if(inp == '\n') {
      ans[0] = max(col, ans[0]);
      col = 0;
      (ans[1])++;
   }
}
fclose(in);
}

Click Here

More Barcodes

I’ve been working more with my barcode application and am finally close to a working solution.

Adding start and stop characters is more or less dependent on which charset you want to use, unless you’re going to use special characters or some other special functionality, you’ll be using Code128 B – which supports most normal alphanumeric characters and punctuation characters in the ASCII table. The rest is just basic String concatenation, which you can do in LibreOffice Calc or through programming.

The first stretch was developing the checksum method in Java, which was pretty easy thanks to the information provided by wikipedia here.

What I did was simply to make an array with the characters listed for Code 128 B, disregarding special characters since I won’t be using them anyway. The array looks a little something like this…

private String code128B_table[] = {
" ","!","\"","#","$"," %","&","'","(",")","*","+",",","-",".","/",
"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?",
"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
"Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`",
"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p",
"q","r","s","t","u","v","w","x","y","z","{","|","}","~","DEL","FNC3",
"FNC2","ShiftA","CodeC","FNC4","CodeA","FNC1","StartCodeA","StartCodeB","StartCodeC"
};
private String code128_table[] = code128B_table;

With the Array in place, all I needed to do to calculate the checksum was write this method:

/**
* Calculates the checksum
* @param input String input for calculating checksum
* @return the checksum in integer form
*/
public int checksumInt(String input) {
int checksum = STARTCODE;
for(int i = 0; i < input.length(); i++) {
int value = charNumber(input.charAt(i));
if(value < 0)
return value;
int position = i+1;
checksum += (value * position);
}
return checksum % 103;
}

/**
* Helper function for checksumInt
* Finds the number of the particular character using the Code128B table
* @param c
* @return
*/
public int charNumber(char c) {
for(int i = 0; i < code128_table.length; i++) {
if(code128_table[i].charAt(0) == c)
return i;
}
System.out.println("Could not find " + c);
return -1;
}

But wait, there’s more. The checksum itself isn’t enough, it needs to be in the form of a character, but since we already have the table for Code128B in array form, we just convert the integer to character for printing.

/**
* Converts calculated checksum into character
* @param i calculated checksum
* @return character for printing checksum
*/
public char checksumChar(int i) {
if(i < 95)
return (char) (i + 32);
else
return (char) (i+ 100);
}

Since the computers come with Norwegian keyboards and the barcode scanner will read barcodes as if receiving keyboard input, I had to do a few cheap hacks to remap the characters according to Norwegian keyboards, this isn’t a problem with alphanumeric data, but characters like { [ ] and } will read on a computer set with  a Norwegian keyboard layout as receiving the letters Æ Ø and Å or some other character because of this, I made a function with way too many if/else tests rather than using a HashMap or other key-value pair since it just seemed simpler to write at the time.

The class file is available on github here.

Beginning Barcodes

About a year ago, I made a bit of an impulse buy on eBay and purchased a barcode scanner for a little less than a dollar (little did I know that shipping and handling would cost me 9 dollars more, but 10 bucks isn’t really anything to worry about).

BarcodeScanner

Why you ask?

Because for some reason I thought it might be a good idea to have a barcode scanner available so I could learn a bit about programming applications using barcodes.

What have I learned so far?

Well there’s a lot of talk on how you need permission to use certain barcodes. Especially EAN and UPC seem to be regulated if you want to distribute your product, but EAN is only the tip of the iceberg.

Some of the simplest barcodes to work with today can be installed as fonts and these include Code 39, Code 93 and Code 128.

But you can’t just download a font and think it’ll work like that – barcodes usually need some way of knowing where to start and stop reading, so the name “Studio Black” would have to be written “ÌStudioÂBlack{Δ to work in Code 128.

Luckily, several websites, like this one, can help translate for you.

So how does this work?

Barcodes are actually an incredibly simple and efficient input method and isn’t really all that different from a computer keyboard. Think of it as a mix between a keyboard and a scanner. When it reads any barcode it supports, your computer will pretty much only act as if it received keyboard input in the form of a string or number.

Some barcodes support alphanumeric data (like Code 39 and Code 128), which means it can contain both text and numbers, while others are simply numeric (like EAN and UPC).

Because of this, programming an application that reads barcodes require next to nothing extra and you can probably just use the same old text fields and forms as always. The USB barcode scanner I have is pretty simple to use and drivers were as easy and automatic as when connecting a keyboard or mouse – just plug and play.

In the long run, the biggest hassle is probably getting familiar with the legal issues of it all.

You can find the fonts for the different barcode systems:

Here: Code 39

Here: Code 93 and

Here: Code 128

As of yet I’ve had the best luck using Code 128, with the type of barcode scanner you can find for about 10 bucks off eBay. My model is called X-9100 and works like a charm.

By the way, make sure to never use bold or italic with barcode fonts, they mess up everything.

Sudoku

Finished the Sudoku-puzzle solver about two weeks ago, I might publish part of the solution later on when the course is finished, but at the moment here’s a few snapshots of how it looked like.