Skip to content

Instantly share code, notes, and snippets.

@denkspuren
Last active March 27, 2023 19:46
Show Gist options
  • Save denkspuren/c68b69624d57547a5bfa to your computer and use it in GitHub Desktop.
Save denkspuren/c68b69624d57547a5bfa to your computer and use it in GitHub Desktop.
Barcode generator in Processing
/*
Barcode Generator (EAN-13) by @denkspuren, 2014-08-27, 14:22
Minor update for Processing 3, 2015-11-19, 00:44
New BSD License: http://opensource.org/licenses/BSD-3-Clause
http://en.wikipedia.org/wiki/International_Article_Number_(EAN)
http://de.wikipedia.org/wiki/European_Article_Number
Use: Press number keys to input a sequence of digits or use
right/left arrow for navigation.
Note: Rightmost digit is checksum digit.
*/
final int START_X = 30;
final int START_Y = 20;
final int LINE_LENGTH = 100;
final int LINE_EXTRA = 20;
final int LINE_WEIGHT = 3;
final int TEXT_PT = 20;
int pos = 0; // ranges from 0..11
Digit[] digits = new Digit[13];
final int ASCII_NULL = 48;
final int ASCII_NINE = 57;
final color WHITE = color(255,255,255);
final color RED = color(255,0,0);
final color BLUE = color(0,0,255);
String[] encoding = // encoding for digits 0..9 on right side
{
"1110010", "1100110", "1101100", "1000010", "1011100",
"1001110", "1010000", "1000100", "1001000", "1110100"
};
String[] pattern = // 1st digit is encoded via pattern for digits on left side
{
"OOOOOO", "OOEOEE", "OOEEOE", "OOEEEO", "OEOOEE", // 'O' means "odd"
"OEEOOE", "OEEEOO", "OEOEOE", "OEOEEO", "OEEOEO" // 'E' means "even"
};
String reverseEncoding(String s) { // required for digits on left side (even)
if ((s == null) || s.isEmpty()) return s;
return reverseEncoding(s.substring(1)) + s.charAt(0);
}
String inverseEncoding(String s) { // required for digits on left side (odd)
if ((s == null) || s.isEmpty()) return s;
return ((s.charAt(0) == '1') ? '0' : '1') + inverseEncoding(s.substring(1));
}
int calc_checksumDigit(int[] digits) {
int sum = 0;
int multiplier = 3;
for (int i=digits.length-1; i>=0; i--) {
sum += digits[i] * multiplier;
multiplier = (multiplier == 3) ? 1 : 3;
}
return (10 - sum % 10) % 10;
}
int draw_encoding(int x, int y, int length, String encoding) {
for (int i=0; i<encoding.length (); i++) {
if (encoding.charAt(i) == '1') line(x, y, x, y+length);
x += LINE_WEIGHT;
}
return x;
}
void draw_barcode(int x, int y, int[] digits) {
String code;
String schema = pattern[digits[0]];
x = draw_encoding(x, y, LINE_LENGTH+LINE_EXTRA, "101");
for (int i=1; i<=6; i++) {
code = (schema.charAt(i-1) == 'O') ?
inverseEncoding(encoding[digits[i]]) :
reverseEncoding(encoding[digits[i]]);
x = draw_encoding(x, y, LINE_LENGTH, code);
}
x = draw_encoding(x, y, LINE_LENGTH+LINE_EXTRA, "01010");
for (int i=7; i<=12; i++) {
code = encoding[digits[i]];
x = draw_encoding(x, y, LINE_LENGTH, code);
}
x = draw_encoding(x, y, LINE_LENGTH+LINE_EXTRA, "101");
}
class Digit {
int x, y, value;
Digit(int x, int y, int value) {
this.x = x;
this.y = y;
this.value = value;
draw(false);
}
void draw(boolean active) {
fill(active ? RED : BLUE);
text(value, x, y);
}
}
void draw_digits(Digit[] digits) {
for (Digit d: digits) d.draw(false);
}
Digit[] initDigits() {
int x = START_X - TEXT_PT/2;
int y = START_Y + LINE_LENGTH + LINE_EXTRA;
Digit[] digits = new Digit[13];
digits[0] = new Digit(x, y, 0);
x += 3 * LINE_WEIGHT + 2 * TEXT_PT/2;
for (int i=1; i<=6; i++) {
digits[i] = new Digit(x, y, 0);
x += 7 * LINE_WEIGHT;
}
x += 4 * LINE_WEIGHT; // + TEXT_PT/2;
for (int i=7; i<=12; i++) {
digits[i] = new Digit(x, y, 0);
x += 7 * LINE_WEIGHT;
}
return digits;
}
void set_ChecksumDigit(Digit[] digits) {
int[] values = new int[12];
for (int i=0; i<=11; i++) values[i] = digits[i].value;
digits[12].value = calc_checksumDigit(values);
}
int[] get_DigitValues(Digit[] digits) {
int[] values = new int[13];
for (int i=0; i<=12; i++) values[i] = digits[i].value;
return values;
}
void setup() {
// Formerly defined at top of the file; incompatible with Processing 3
// final int SIZE_X = 2*START_X + (3 + 6*7 + 5 + 6*7 + 3) * LINE_WEIGHT;
// final int SIZE_Y = 2*START_Y + LINE_LENGTH + LINE_EXTRA;
// size(SIZE_X, SIZE_Y); // if used, must be first line of code in setup
size(345, 160);
textSize(TEXT_PT);
textAlign(CENTER);
strokeWeight(LINE_WEIGHT);
strokeCap(SQUARE);
draw_barcode(START_X, START_Y, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0});
digits = initDigits();
digits[pos].draw(true);
}
void keyPressed() {
if (key >= ASCII_NULL && key <= ASCII_NINE) {
background(WHITE);
digits[pos].value = key - ASCII_NULL;
set_ChecksumDigit(digits);
draw_barcode(START_X, START_Y, get_DigitValues(digits));
draw_digits(digits);
pos = (pos + 1) % 12;
digits[pos].draw(true);
}
else if (key == CODED) {
if (keyCode == RIGHT) {
digits[pos].draw(false);
pos = (pos + 1) % 12;
digits[pos].draw(true);
}
else if (keyCode == LEFT) {
digits[pos].draw(false);
pos = (pos + 11) % 12;
digits[pos].draw(true);
}
}
}
void draw() {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment