This program generates a colour scheme from an image using K-Means clustering and allows the user to save it as a PDF file.
Table of Contents
On a wonderful day, the 9th of August 2022 to be exact, during a wonderful holiday in Rostock, Germany to clear my mind from that summer's extreme stress and all things uni, I decided that taking a break is for losers, only the strong shall survive and how better to practice my tolerance to constant exposure to stress than to start a coding project during my four days of vacation for the whole year?
So I stood there in the ocean, gently being rocked back and forth by the waves, intently staring at some water insect that had been trying to swim toward me for several minutes at this point, when I decided to look back at the beach and noticed the white houses, green grass, blue ocean and golden sand. And I thought "How nice would it be if I could paint this scene with exactly those colours?", well knowing that I hadn't touched paint in ages and that landscape painting was absolutely not my thing.
But that did not matter. My mind had already started racing.
There were a few problems though. The Wi-Fi of the place we were staying had died and so did my high speed, leaving me with no quick way to read up on anything related to creating a colour scheme from an image.
So there I was, armed with only my phone, my tablet I used for drawing, OneNote and my mind going at 100 km/h. I started thinking and writing wild concepts and ideas until some sort of idea had formed. And because planning is for people who don't know where they are going, I started writing code, since I definitely absolutely knew what I was doing and where I was going.
I remembered my professor's words, that we needed to know how to write code on paper as we wouldn't always have a computer and an IDE available, and I cursed my arrogance as I had thought, that if I needed to code, I would use my PC or an online IDE and if I had neither available, I would just not code. So I had to fall back on my very limited memory of my first programming classes. Luckily for me, due to my bad memory, I write down everything, so I had at least some code snippets I could use as a reference for my first lines of code.
I spent my holiday reading up on K-Means Clustering, three-dimensional spaces in Java and different forms of visualizations of colour spaces. And if I am honest, those holidays were amazing. There is a difference between sitting at home and researching and sitting in the sun at the beach in a different city and researching.
When I came home, I transferred my code into my IDE and to my surprise and joy, I had only very few issues to fix until version 1.0 of my Color Scheme Generator was working.
Since then, I incorporated the iTextPDF library to be able to save the resulting colour scheme, I became friends or at least decided to call a truce with Gradle to better manage my dependencies and recently even cautiously approached maths to add a colour wheel to the file.
I have also learned a ton about Java, gained a lot of experience with managing a project, Code Conventions and most importantly, patience and determination and can finally say: I am incredibly proud of my project. It might not be a revolutionary tool that people are in dire need of, but it is my first large project that I have kept up with and improved as I continued my studies and that is the result of my determination, patience with myself and my love for coding, which I discovered a few months into my first semester at the University of Applied Sciences in Wernigerode, Germany.
To get a local copy up and running, follow these steps.
This program requires Java 18+ to run properly. How to install Java will be explained in the following steps. If your device is not running on a 64-bit operating system, you cannot use this program. You will also need administrator privileges to install Java.
-
Find out which bit-version your operating system is running on:
-
- Click on the Apple Logo in the upper-left corner
- Open the
About This Mac
page - You will see your processor below the operating system and computer model name. If your processor appears on the following list, your device is running on a 64-bit operating system. If you have a processor not listed here, your device is running on a 32-bit operating system.
- Core 2 Duo
- Dual-core Xeon
- Quad-core Xeon
- Core i3
- Core i5
- Core i7
-
-
Open your Spotlight, search
Terminal
and open it -
You should now see two lines of text: your last login and in line 2
[device name]:~ [username]$
-
Place your cursor at the end of line 2 (make sure to leave a whitespace between the cursor and the
$
) -
Type
getconf LONG_BIT
and hit Enter -
The number being displayed in the following line is the bit-version of your device
-
-
- Press
Ctrl + Alt + T
to open the terminal - Type
getconf LONG_BIT
and hit Enter - The number being displayed in the following line is the bit-version of your device
- Press
-
Install Java from the Oracle Archive by downloading the following
- Windows:
Windows x64 Installer
- Mac:
macOS x64 DMG Installer
- Linux:
Linux x64 Compressed Archive
- Windows:
-
Execute the JDK Installer by double-clicking it, and clicking
yes
if it requests system permission -
Now, the Installer Welcome Screen should open. Click on
Next
to change the installation location if required. ClickNext
again to start the installation. After successfully installing Java, you can clickClose
.
The following steps might not be necessary but should be followed if the program does not work.
-
To verify the installation, open the Terminal (on Windows, press the Windows key and search for
Terminal
) -
Type
java -version
and hit enter. You should see this: -
If the version number matches the version you installed, you can skip the following steps. If not, here is how to proceed:
- Windows:
-
Windows 11: Press the Windows key and enter
environment variables
, then openEdit the system environment variables
(left image)
Windows 10: PressWindows key + R
and entersysdm.cpl
into the dialogue, then hit enter (right image) -
A window
System Properties
should have opened. Switch to theAdvanced
Tab -
Click on
Environment Variables
-
Under
System Variables
look forJAVA_HOME
-
If it is there, double-click it and verify that the variable value is the path to the installed Java version. This is usually
C:\Program Files\Java\[jdk-##]
with the##
representing the version number (e.g., Java 18 would be jdk-18) -
If it is not there, click
New
, enterJAVA_HOME
as the variable name and the path to the installed Java version (usuallyC:\Program Files\Java\[jdk-##]
with the##
representing the version number) as the variable value
-
-
Then look for
PATH
and double-click it -
If not already there, click
New
and add%JAVA_HOME%\bin
-
Close the windows with the
OK
buttons -
Press the Windows key and type in
Terminal
, but run it as an administrator by right-clicking it and then clickingRun as administrator
-
Then enter
javac --version
and hit enter again. The Java version should now be displayed. -
Press the Windows key and type in
Control Panel
, open thePrograms
page and click onJava
-
Switch to the
Java
tab in the window that should have opened and click onView
-
A new window with a table should now open. Click on
Find
and then onNext
in the JRE Finder -
Enter the file path to the Java installation as determined in Step 4 and click on
Finish
-
Should there be more than your downloaded version of Java in the table, disable the old one by unselecting the checkbox in the column titled
Enabled
-
Click
Okay
, thenApply
and pat yourself on the shoulder because Good job! You did it! (Maybe restart your PC though)
-
- MacOS:
-
Open your Spotlight, search
Terminal
and open it -
If you don’t know where the JDK was installed, enter
/usr/libexec/java_home
and press enter
It’s usually under/Library/Java/JavaVirtualMachines
-
Find the path to the target file by typing
~/.bash-profile
and hitting enter -
The file will be opened automatically
-
The current Java Home variable will usually be in the first line and looks like this (
[jdk-##]
is the Java version, e.g., Java 18 would be jdk-18) -
Add the following to the file (the file path may vary but usually is at this location)
export %JAVA_HOME%=C:\Program Files\Java\[jdk-##]
-
Save the file with
CMD + S
(the original file should now be modified) and close it -
Execute the new file by reopening the Terminal
-
Verify that the new Java version was set by entering java -version and hitting enter. The Java version that will be displayed should match the version you set
-
- Windows:
See the documentation for specifics.
Warning
NEVER download or open unknown .exe, .jar or other executable files!
If you open this without knowing what it is, that is on you.
(the file will be saved in your Downloads folder with the name “ColorScheme_[Filename].pdf”)
If you decided to add harmonic colours,
the dropdown will open where you will be able to select one or more types of colour harmonies.
See here for an explanation of the different types.
7. When the process has finished, the download button will be enabled, and you’ll be able to download your colour scheme.
Page 1 shows the file name right below the header. Right next to the selected image (or below, depending on the image size), the chosen number of main colours are listed. Their colour values are specified in hexadecimal format, as an HSB triplet and as an RGB triplet. Below the colours are the colour scheme averages, listing the average colour (more precisely, the average hue), the average saturation and the average brightness. Note, that this table might be on page 2 if the image is in landscape format.
Page 2 shows the extracted main colours on a colour wheel. Additionally, the selected images meta-data is listed.
Pages 3 and 4 list the selected colour harmonics for the main colours.
The file name and extension of the chosen image as displayed in the file explorer.
The image chosen by the user that is used to generate the colour scheme.
The color scheme generated from the image along with the colour codes in HEX, RGB and HSB.
Shows the main colors of the colour scheme in a colour wheel.
Shows the average colour, whether the colours are saturated or unsaturated on average along the average saturation and whether the colours are bright or dark on average along the average brightness.
Shows the metadata of the image, if available.
The display name of the file, which is also displayed in the file explorer. The file title set in the details tab of the file properties may differ.
Shows you the file type of your file. This is either a "JPG"/"JPEG" (no difference) or a "PNG" since the program only accepts files of that type.
Shows the file size in the appropriate unit, meaning it is within the 1 - 999.99 range of the unit, except for MB, which is in the 0–999.99 range.
Shows the date and time of the creation of the file according to the time zone of the user.
Shows the date and time of the last modification of the file according to the time zone of the user. This includes modifications that change the files' metadata, such as editing the name, owner or permissions.
Shows the date and time of the last time the file has been accessed, meaning it has been opened. This can mean the file was opened by the user or a program.
Shows the height of the image in pixels. This value might change according to the rotation of the image.
Shows the width of the image in pixels. This value might change according to the rotation of the image.
A colour space is a range of colours on a spectrum that can be displayed visually.
Example of the visualization of the RGB color space
R stands for red, G stands for green and B stands for blue. When the image supports transparency, the A stands for
alpha (transparency value).
These colours have to be stored in a format readable to a computer. Usually, color spaces are 8-bit large, which can be imagined as 8 boxes holding a single colour value.
3 bits store red, 3 bits store green and 2 bits store blue, since the human eye is less sensitive to blue light.
If the image supports transparency, each colour only gets two bits and the alpha value is stored in the 7th and 8th boxes.
Usually, the colour space name will contain an A somewhere, like in RGBA.
The boxes holding the colors can be moved around to create different colour spaces like the BGR colour space. This only means that the order of the boxes holding the colours is reversed.
Shows the number of colour components of the image. This includes red, green and blue, making for three colour components. If the image supports transparency, the alpha channel is counted as the fourth colour component.
This shows the number of bits used to indicate the colour of a pixel. The higher the bit depth, the more bits (boxes) are used to store the colour. With more bits, gradual changes in colour can be displayed more accurately.
Bit depth is most notable when working with gradients as gradients will start showing clear steps in colour as the bit depth goes down.
Shows, how the image supports transparency. If the image does not support transparency, this will be displayed
as "completely opaque". If transparency is supported, the image is either completely transparent or allows gradual
steps in transparency (value between 0 and 1).
Shows, whether the image supports transparency. If the image does not support transparency, this will be displayed as "Transparency not supported by colour model". If transparency is supported, this will be displayed as "Transparency supported by colour model".
Shows whether the alpha is premultiplied. This can easily be explained by this quick example, where we want to add a tree (image 1) to an image of a landscape (image 2).
Now, the background of the image with the tree is not transparent, so if we were to add that image onto image 2, it would cover image 2 completely. To fix this, we need to create an alpha mask. The alpha value controls the transparency of an area, so an alpha mask specifies which areas should remain opaque and which ones should be transparent. Transparent areas are usually shown as black in the mask, while opaque areas are white. These masks are applied to the image by multiplying the mask with the image.
Then, we need to cut out space for the tree on the new background by using the same, but inverted mask. Now everything but the area of the tree is white, meaning only the space, where the tree will be added is transparent.
Finally, we can add the masked first image into the masked second image, where it will fill the transparent area.
For the first two steps, I used a multiplication symbol to show the mask being applied. This is because masking means multiplied. Therefore, premultiplied is pre-masked. An image with premultiplied alpha already has information about the individual image components. This could look like this:
Left: Not masked/not premultiplied, Right: Masked/premultiplied
- Finish README
- Add Usage Examples
- Add License
- Create Bug Template
- Add documentation
-
Create Commit message guidelines - Add history
- Add Metadata to the image
- Better incorporate colour wheel
- Implement multiple languages (maybe)
- Create an interface using JavaFX
-
Implement the possibility of seeing the result in the interface already - Write a file explaining the mathematical structures used (see: Documentation)
- Write a file explaining the mathematical structures used in simple terms (see: Documentation)
- Explain code (maybe, JavaDocs exist) (see: Documentation)
See the open issues for a full list of proposed features (and known issues).
To report an issue, please use the issue template.
Elisa Johanna Woelk
Project Link: https://github.com/Fenris22127/ColorSchemeGenerator