Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 11

import java.awt.

Canvas;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {


private static Canvas canvas;
private static Graphics ctx;
private static Image userimage;
private static String userfilename;
private static Canvas selected_canvas;
private static Graphics selected_ctx;
private static Image selected_placeholder;
private static String[] input_ids = {"projectname", "firstpage", "lastpage",
"cm", "inch", "bookheight", "singleprecision", "smoothe"};
private static Map<String, String> entries = new HashMap<>();

public static void main(String[] args) {


JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.add(panel);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

canvas = new Canvas();


ctx = canvas.getGraphics();
userimage = null;
userfilename = "";
selected_canvas = new Canvas();
selected_ctx = selected_canvas.getGraphics();
selected_placeholder = null;

for (String input_id : input_ids) {


entries.put(input_id, "");
}

canvas.setSize(500, 500);
ctx = canvas.getGraphics();
selected_canvas.setSize(500, 500);
selected_ctx = selected_canvas.getGraphics();

selected_placeholder = new BufferedImage(500, 500,


BufferedImage.TYPE_INT_ARGB);
display_selected_image(null, userimage = selected_placeholder);
processEntries(false);
}

public static void showValue(Event e) {


document.getElementById("smootheoutput").innerHTML = e.target.value;
}

public static void loadImage(Event e) {


e.preventDefault();
document.getElementById("userimage").parentElement.classList.remove("error");
empty_error("img_errorbox");
hide("result");
empty_error("errorbox");
String o = "";

if (typeof window.FileReader == "undefined") {


o += "The file API isn't supported on this browser yet.";
}

File file = document.getElementById("userimage").files[0];


if (file != null) {
if (!file.type.startsWith("image")) {
o += "The file you uploaded is not an image file. Please use a
valid file format, e.g. jpg, png, ...";
} else if (file.type.search("svg") != -1) {
o += "Sorry, I can't handle svg resizing yet. Please convert your
image file into a pixel based format.";
}
} else {
o += "Please select a file before clicking on 'Load image'.";
}

if (o != "") {
deactivate_startbutton();
print_error(o, "img_errorbox");
} else {
userfilename = file.name;
try {
ImageIO.read(file);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

public static void display_selected_image(Event e, Image t) {


if (t == null) {
userimage = selected_placeholder = t;
}
selected_ctx.clearRect(0, 0, selected_canvas.getWidth(),
selected_canvas.getHeight());
if (t.getWidth(null) / t.getHeight(null) < 1) {
int r = t.getWidth(null) * selected_canvas.getWidth() /
t.getHeight(null);
int a = selected_canvas.getHeight();
} else {
int r = selected_canvas.getWidth();
int a = t.getHeight(null) * selected_canvas.getWidth() /
t.getWidth(null);
}
int i = (selected_canvas.getWidth() - r) / 2;
int o = (selected_canvas.getHeight() - a) / 2;
selected_ctx.drawImage(t, i, o, r, a);
}

public static void checkEntry(Event e) {


String t = "";
hide("result");
e.parentElement.classList.remove("error");
remove_error(e.id + "_errorbox");

switch (e.id) {
case "projectname":
if (e.value != "") {
entries.put("projectname", e.value);
} else if (e.placeholder != "") {
entries.put("projectname", e.placeholder);
} else {
entries.put("projectname", "My Book Art Project");
}
if (entries.get("projectname").length() > 100) {
entries.put("projectname",
entries.get("projectname").substring(0, 100));
}
break;
case "firstpage":
if (e.value != "" && e.validity.valid != false) {
entries.put("firstpage", Integer.parseInt(e.value));
} else {
t = "The first page must be an even, positive number. ";
}
break;
case "lastpage":
if (e.value == "" || e.validity.valid == false ||
Integer.parseInt(e.value) <= entries.get("firstpage")) {
t = "The last page must be an even, positive number. It must be
larger than the number of the first page. (This will work with up to 2000 pages. If
you are working on a larger book, please contact the author of this website.) ";
} else {
entries.put("lastpage", Integer.parseInt(e.value));
}
break;
case "cm":
case "inch":
if (e.checked) {
entries.put("unit", e.id);
}
break;
case "bookheight":
if (e.value != "" && e.validity.valid != false) {
entries.put("bookheight", 100 * Float.parseFloat(e.value));
} else {
t = "The book's height must be a positive number with no more
than 1 digit after the decimal point. (This will work for heights between 1 and 40
cm/inch. If you are working on a larger book, please contact the author of this
website.) ";
}
break;
case "singleprecision":
if (e.checked) {
entries.put("singleprecision", true);
} else {
entries.put("singleprecision", false);
}
break;
case "smoothe":
if (e.value != "" && e.validity.valid != false) {
entries.put("smoothe", smoothe.value);
} else {
t = "The smoothing value you selected is invalid - please use a
number between 0 and 20. ";
}
break;
}

if (t != "") {
e.parentElement.classList.add("error");
Element r = document.createElement("p");
r.id = e.id + "_errorbox";
r.classList.add("errormsg");
Text a = document.createTextNode(t);
r.appendChild(a);
e.parentElement.appendChild(r);
return false;
}

return true;
}

public static void processEntries(Event e) {


if (e != false) {
e.preventDefault();
}
deactivate_startbutton();
boolean t = true;
for (String input_id : input_ids) {
if (checkEntry(document.getElementById(input_id)) == false) {
t = false;
}
}
entries.put("userimage", userimage);
if (entries.get("userimage") == null) {
t = false;
}
if (t == true) {
if (e != false && e.target.id == "startbutton") {
processImage();
}
activate_startbutton();
}
}

public static void processImage() {


entries.put("numsheets", (entries.get("lastpage") -
entries.get("firstpage")) / 2);
create_patterndata(entries);
if (e != null) {
createpatterntext(e, entries);
drawPreview(e, entries.get("bookheight"));
show("result");
}
}

public static void create_patterndata() {


canvas.setSize(entries.get("numsheets"), entries.get("bookheight"));
ctx.drawImage(entries.get("userimage"), 0, 0, entries.get("numsheets"),
entries.get("bookheight"));
Image t = image_to_bw();
int r = createrawpattern(t);
if (checkrawpattern(r)) {
return createalternatingpattern(smootherawpattern(r,
entries.get("smoothe")));
}
}

public static Image image_to_bw() {


Image o = ctx.getImageData(0, 0, canvas.getWidth(), canvas.getHeight());
int[] s = o.getData();
for (int l = 0; l < s.length; l += 4) {
int e = s[l];
int t = s[l + 1];
int r = s[l + 2];
int alpha = s[l + 3];
if (alpha != 0) {
if (alpha != 255) {
float h = alpha / 255;
float d = (1 - h) * 255;
e = h * e + d;
t = h * t + d;
r = h * r + d;
}
int a = (299 * e + 587 * t + 114 * r) / 1000;
} else {
a = 255;
}
if (a >= 128) {
s[l] = 255;
s[l + 1] = 255;
s[l + 2] = 255;
} else {
s[l] = 0;
s[l + 1] = 0;
s[l + 2] = 0;
}
s[l + 3] = 255;
}
return o;
}

public static int createrawpattern(Image e) {


int[][] g = new int[e.getWidth()][e.getHeight()];
for (int a = 0; a < e.getWidth(); a += 1) {
g[a] = new int[e.getHeight()];
for (int i = 0; i < e.getHeight(); i += 1) {
g[a][i] = e.getData()[(a + i * e.getWidth()) * 4];
}
}
int[][] f = new int[e.getWidth()][];
for (int a = 0; a < e.getWidth(); a += 1) {
int[][] o = null;
f[a] = new int[e.getHeight()];
for (int i = 0; i < e.getHeight();) {
int s = g[a][i];
while (s == 0 && i < e.getHeight()) {
if ((o == null || o.length == 0) && s == 0) {
l = i;
}
i += 1;
s = g[a][i];
}
while (s != 0 && i < e.getHeight()) {
if (o != null && o.length != 0 && s == 0) {
f[a].push([l, i]);
}
i += 1;
o = g[a][i];
s = g[a][i];
}
}
}
return f;
}

public static boolean checkrawpattern(int[][] e) {


String t = "";
boolean a = false;
boolean i = false;
int o = getlength(e);
for (int r = 0; r < o; r++) {
if (e[r].length > 5) {
a = true;
t = "Your picture has an awful lot of detail! This results in more
than 5 alternating folds in some area(s). Please reduce the details in your picture
and call this program again.";
break;
}
if (!a && e[r].length == 0) {
r += 1;
continue;
}
if (!a && e[r].length != 0) {
a = true;
r += 1;
continue;
}
if (a && e[r].length != 0 && !i) {
r += 1;
continue;
}
if (a && e[r].length == 0 && !i) {
i = true;
r += 1;
continue;
}
if (a && e[r].length == 0 && i) {
r += 1;
continue;
}
if (a && e[r].length != 0 && i) {
t = "Sorry, but your picture has vertical gaps (like space between
letters, for example: <a href=\"/posts/2018/May/prepare_bookart_text.html\">learn
how to get rid of it here</a>) in it, this won't look good!\nPlease use a different
picture!";
break;
}
}
if (a == false) {
t += "Ooops - you gave me a picture which is only white (or has too
little contrast)!";
}
if (t != "") {
print_error(t, "errorbox");
return false;
}
return true;
}

public static int[][] smootherawpattern(int[][] e, int t) {


String s = "";
int[][] c = new int[getlength(e)][];
int d = getlength(e);
for (int x = 0; x < d; x += 1) {
int[][] h = [];
boolean r = false;
if (e[x].length > 1) {
for (int l = 0; l < e[x].length - 1; l += 1) {
if (!r) {
a = e[x][l][0];
}
i = e[x][l][1];
if ((o = e[x][l + 1][0]) - i < t) {
i = e[x][l + 1][1];
r = true;
if (t > 0) {
s = "Smoothed one or more folds, because the distance
between one dark area and the dark area below it was shorter than the selected
smoothing value. Please check the pattern thoroughly for correctness. If it looks
wrong, try to use a better picture, or try to enter different values for page
numbers. If the tiny gaps are intentional, then don't use smoothing.";
}
} else {
h.push([a, i]);
r = false;
}
if (l == e[x].length - 2) {
if (!r) {
h.push([e[x][l + 1][0], e[x][l + 1][1]]);
} else {
h.push([a, i]);
}
}
}
} else {
h = e[x].slice();
}
c[x] = h.slice();
}
if (s != "") {
print_error(s, "errorbox");
}
return c;
}
public static int[][] createalternatingpattern(int[][] e) {
int[][] r = new int[getlength(e)][];
int a = getlength(e);
for (int x = 0; x < a; x += 1) {
int num_bands;
int[][] t = e[x];
if (t.length == 0) {
r[x] = [];
} else if (t.length == 1) {
r[x] = t[0].slice();
} else {
r[x] = t[x % t.length].slice();
}
}
return r;
}

public static void createpatterntext(int[][] e) {


String t = "";
String textarea = document.getElementById("patterntext");
String page_formatted;
for (int x = 0; x < entries.get("numsheets"); x++) {
int page = 2 * x + entries.get("firstpage");
page_formatted = (" " + page.toString()).slice(-4);
if (e[x][0] == 0 && e[x][1] == entries.get("bookheight")) {
t += page_formatted + " No folds.\n";
} else if (e[x].length == 0) {
t += page_formatted + " Fold back completely.\n";
} else {
float uppercorner = e[x][0] / 100;
float lowercorner = e[x][1] / 100;
if (entries.get("singleprecision") == true) {
uppercorner = uppercorner.toFixed(1);
lowercorner = lowercorner.toFixed(1);
} else {
uppercorner = uppercorner.toFixed(2);
lowercorner = lowercorner.toFixed(2);
}
t += page_formatted + " " + (" " + uppercorner).slice(-7)
+ " " + (" " + lowercorner).slice(-7) + "\n";
}
if (page % 10 == 0) {
t += "------------------------------------------\n";
}
}
t += "\n\n\nThis Book Art pattern was created using the free
BookArtGenerator service at:\n";
t += "https://vektorrascheln.de/bookart\n\n";
t += "As the author of the open source service, I would be very happy to
see your cool creations!\n";
t += "Please send me a mail with a photo (licensed under CC-By-SA 4.0,
allowing to show the\n";
t += "photo on the website, to modify it if necessary, always quoting you
as the originator,\n";
t += "allowing commercial use) to moini@goos-habermann.de.\n\n";
t += "------------ HAVE FUN FOLDING :-) ------------ !\n\n";
textarea.value = t;
}
public static void drawPreview(int[][] e, int t) {
canvas.setSize(6 * e.length + 36, t + 50);
ctx.setColor(Color.WHITE);
ctx.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
ctx.setStroke(new BasicStroke(2));
ctx.setColor(Color.BLACK);
ctx.setFont(new Font("Arial", Font.PLAIN, 18));
ctx.setTextAlign(TextAlign.CENTER);
for (int r = 0; r < e.length; r++) {
if ((r + entries.get("firstpage") / 2) % 10 == 0) {
ctx.setColor(Color.Thistle);
} else {
ctx.setColor(Color.Gainsboro);
}
ctx.beginPath();
ctx.moveTo(6 * r + 18, 0);
ctx.lineTo(6 * r + 18, t);
ctx.stroke();
}
for (int r = 0; r < e.length; r++) {
if ((r + entries.get("firstpage") / 2) % 10 == 0) {
ctx.setColor(Color.PaleVioletRed);
} else {
ctx.setColor(Color.DimGray);
}
ctx.beginPath();
ctx.moveTo(6 * r + 18, e[r][0]);
ctx.lineTo(6 * r + 18, e[r][1]);
ctx.stroke();
}
for (int r = 0; r < e.length; r++) {
int a = 2 * r + entries.get("firstpage");
if (a % 20 == 0) {
ctx.fillText(a, 6 * r + 18, canvas.getHeight() - 30);
}
}
ctx.fillText("Print this picture with a height of " + canvas.getHeight() /
100 + " " + entries.get("unit") + ".", canvas.getWidth() / 2, canvas.getHeight() -
5);
}

public static void downloadImage() {


String e = canvas.toDataURL("image/png");
if (window.navigator.userAgent.indexOf("Edge") > -1 ||
window.navigator.userAgent.indexOf("Trident") > -1) {
window.open().document.write("<img src='" + e + "' alt='canvas image'
title='Right-click on image to download!'/>");
} else {
this.download = userfilename.substr(0, userfilename.lastIndexOf(".")) +
"_preview.png";
this.href = e;
}
}

public static void downloadText() {


String text = document.getElementById("patterntext").value;
if (window.navigator.userAgent.indexOf("Edge") > -1 ||
window.navigator.userAgent.indexOf("Trident") > -1) {
String e = "<pre>" + text + "</pre>";
window.open().document.write(e);
} else {
this.download = userfilename.substr(0, userfilename.lastIndexOf(".")) +
"_pattern.txt";
this.href = "data:text/plain;charset=utf-8," +
encodeURIComponent(text);
}
}

public static void print_error(String e, String t) {


Element r = document.getElementById(t);
r.innerHTML = e;
r.style.display = "block";
}

public static void empty_error(String e) {


Element t = document.getElementById(e);
t.innerHTML = "";
t.style.display = "none";
}

public static void remove_error(String e) {


Element t = document.getElementById(e);
if (t != null) {
t.parentElement.removeChild(t);
}
}

public static void deactivate_startbutton() {


document.getElementById("startbutton").addEventListener("click", show_hint,
"false");
document.getElementById("startbutton").classList.add("disabled");
}

public static void activate_startbutton() {


Element e = document.getElementById("startbutton");
e.removeEventListener("click", show_hint, "false");
e.classList.remove("disabled");
}

public static void show_hint(Event e) {


e.preventDefault();
alert("Fill in all the fields, and fix all errors to activate the button.
If all is filled in, and there are no errors, and you still cannot click on the
button, try using a different browser, or switch to a desktop computer. Firefox,
Edge and Chrome on desktop are known to work.");
}

public static int getlength(int[][] e) {


int r = 0;
for (int t : e) {
r++;
}
return r;
}

public static void show(String e) {


Element toshow = document.getElementById(e);
toshow.style.display = "block";
}

public static void hide(String e) {


Element tohide = document.getElementById(e);
tohide.style.display = "none";
}
}

You might also like