Skip to content

Commit ece5804

Browse files
committed
Add two basic meson unit tests. They don't compare the output yet.
Also extract hex conversion to separate method.
1 parent 4f63fe4 commit ece5804

File tree

10 files changed

+168
-106
lines changed

10 files changed

+168
-106
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ jobs:
132132

133133
- name: Release add build(${{ matrix.os-name }})
134134
id: release_build
135-
if: ${{ matrix.os != 'windows-latest' }}
135+
if: ${{ matrix.os-name != 'windows' }}
136136
uses: actions/upload-release-asset@v1
137137
env:
138138
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -144,7 +144,7 @@ jobs:
144144

145145
- name: Release add build(${{ matrix.os-name }})
146146
id: release_windows_build
147-
if: ${{ matrix.os == 'windows-latest' }}
147+
if: ${{ matrix.os-name == 'windows' }}
148148
uses: actions/upload-release-asset@v1
149149
env:
150150
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test.yml

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Tests whether the source code can be built with meson compile.
2-
# This would also be the workflow that runs unit tests, if I had written any.
2+
# Compiles the source code and runs unit tests.
33
# All tests are run on windows, ubuntu, macos, and linux-arm64.
44
name: meson test
55

@@ -98,9 +98,30 @@ jobs:
9898
- name: Meson test
9999
run: meson test -C builddir/ -v
100100

101-
- name: Upload Log
101+
- name: Upload Binary
102102
uses: actions/upload-artifact@v2
103-
if: failure()
103+
if: ${{ matrix.os-name != 'windows' }}
104104
with:
105-
name: ${{ matrix.os-name }}_meson_testlog
106-
path: build/meson-logs/testlog.txt
105+
name: meson_testlog_${{ matrix.os-name }}
106+
path: builddir/src/hex-to-image
107+
108+
- name: Upload Binary(Windows)
109+
uses: actions/upload-artifact@v2
110+
if: ${{ matrix.os-name == 'windows' }}
111+
with:
112+
name: meson_testlog_${{ matrix.os-name }}
113+
path: builddir/src/hex-to-image.exe
114+
115+
- name: Upload Test Log
116+
uses: actions/upload-artifact@v2
117+
if: always()
118+
with:
119+
name: meson_testlog_${{ matrix.os-name }}
120+
path: builddir/meson-logs/testlog.txt
121+
122+
- name: Upload Output
123+
uses: actions/upload-artifact@v2
124+
if: always()
125+
with:
126+
name: output_${{ matrix.os-name }}
127+
path: builddir/*.png

meson.build

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
project('hex-to-image', 'cpp', default_options: ['cpp_std=c++11'], license: 'MIT')
22

33
subdir('src')
4-

src/hex-to-image.cpp

Lines changed: 104 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#include <fstream>
1010
#include <iostream>
1111
#include <sstream>
12-
#include <string>
13-
#include <vector>
1412

1513
#define STB_IMAGE_WRITE_IMPLEMENTATION
1614
#include "stb_image_write.h"
@@ -101,11 +99,6 @@ int main(const int argc, char **argv) {
10199
hex_length = 8;
102100
}
103101

104-
uint8_t channels = 3;
105-
if (hex_length % 4 == 0) {
106-
channels = 4;
107-
}
108-
109102
if (output_file.find(".png") != std::string::npos) {
110103
output_file = output_file.substr(0, output_file.find(".png"));
111104
}
@@ -118,103 +111,15 @@ int main(const int argc, char **argv) {
118111

119112
if (hex_input.is_open()) {
120113
std::string line;
121-
uint16_t max_len = 0;
122114

123115
std::vector<std::string> lines;
124116
while (getline(hex_input, line)) {
125117
lines.push_back(line);
126-
if (line.length() > max_len) {
127-
max_len = line.length();
128-
}
129118
}
130119

131120
hex_input.close();
132121

133-
bool ignore_linebreaks = true;
134-
double pixels_per_line = double(max_len) / hex_length;
135-
if (width == 0) {
136-
if (height == 0) {
137-
width = ceil(pixels_per_line);
138-
ignore_linebreaks = false;
139-
height = lines.size();
140-
} else {
141-
width = ceil(double(lines.size()) / height * pixels_per_line);
142-
}
143-
}
144-
145-
if (height == 0) {
146-
height = ceil(lines.size() / (width / pixels_per_line));
147-
}
148-
149-
printf("Output image size: %d x %d pixels.\n", width, height);
150-
151-
uint8_t *pixel_colors = new uint8_t[width * height * channels];
152-
153-
for (uint32_t i = 0; i < width * height * channels; i++) {
154-
pixel_colors[i] = 0;
155-
}
156-
157-
std::string temp;
158-
std::string color;
159-
std::istringstream stream;
160-
uint32_t array_pos = 0;
161-
uint32_t parsed;
162-
for (size_t y = 0; y < lines.size(); y++) {
163-
line = lines[y];
164-
165-
if (ignore_linebreaks && temp.length() > 0) {
166-
line = temp + line;
167-
temp = "";
168-
}
169-
170-
while (line.length() > 0) {
171-
for (uint16_t x = 0; x < width; x++) {
172-
if (line.length() < uint32_t((x + 1) * hex_length)) {
173-
temp = line.substr(x * hex_length, line.length() - x * hex_length);
174-
line = "";
175-
break;
176-
}
177-
178-
if (ignore_linebreaks) {
179-
if (y != 0) {
180-
array_pos += channels;
181-
}
182-
} else {
183-
array_pos = y * width * channels + x * channels;
184-
}
185-
186-
color = line.substr(x * hex_length, hex_length);
187-
if (hex_length <= 4) {
188-
color.resize(hex_length * 2);
189-
for (int8_t i = hex_length - 1; i >= 0; i--) {
190-
color[i * 2 + 1] = color[i * 2] = color[i];
191-
}
192-
}
193-
194-
stream.str(color);
195-
stream >> std::hex >> parsed;
196-
197-
if (stream.rdbuf()->in_avail() > 0) {
198-
cerr << line.substr(x * hex_length, hex_length) << " can't be parsed as hex input!" << endl;
199-
} else {
200-
pixel_colors[array_pos] = (parsed >> 16) & 0xFF;
201-
pixel_colors[array_pos + 1] = (parsed >> 8) & 0xFF;
202-
pixel_colors[array_pos + 2] = parsed & 0xFF;
203-
if (channels == 4) {
204-
pixel_colors[array_pos + 3] = (parsed >> 24) & 0xFF;
205-
}
206-
}
207-
208-
stream.clear();
209-
}
210-
211-
if (line.length() > width * hex_length) {
212-
line = line.substr(width * hex_length, line.length() - width * hex_length);
213-
} else {
214-
line = "";
215-
}
216-
}
217-
}
122+
uint8_t *pixel_colors = convert(lines, hex_length, width, height);
218123

219124
if (FILE *file = fopen(std::string(output_file).append(".png").c_str(), "r")) {
220125
fclose(file);
@@ -243,6 +148,8 @@ int main(const int argc, char **argv) {
243148
output_file.append(".png");
244149
}
245150

151+
uint8_t channels = hex_length % 4 == 0 ? 4 : 3;
152+
246153
stbi_write_png(output_file.c_str(), width, height, channels, pixel_colors, width * channels);
247154
cout << "Image saved as \"" << output_file << "\"." << endl;
248155
delete[] pixel_colors;
@@ -254,6 +161,107 @@ int main(const int argc, char **argv) {
254161
}
255162
}
256163

164+
uint8_t* convert(const std::vector<std::string> lines, const uint8_t hex_len, uint16_t &width, uint16_t &height) {
165+
size_t max_len = 0;
166+
for (std::string line : lines) {
167+
max_len = std::max(max_len, line.length());
168+
}
169+
170+
uint8_t channels = hex_len % 4 == 0 ? 4 : 3;
171+
172+
bool ignore_linebreaks = true;
173+
double pixels_per_line = double(max_len) / hex_len;
174+
if (width == 0) {
175+
if (height == 0) {
176+
width = ceil(pixels_per_line);
177+
ignore_linebreaks = false;
178+
height = lines.size();
179+
} else {
180+
width = ceil(double(lines.size()) / height * pixels_per_line);
181+
}
182+
}
183+
184+
if (height == 0) {
185+
height = ceil(lines.size() / (width / pixels_per_line));
186+
}
187+
188+
printf("Output image size: %d x %d pixels.\n", width, height);
189+
190+
uint8_t *pixel_colors = new uint8_t[width * height * channels];
191+
192+
for (uint32_t i = 0; i < width * height * channels; i++) {
193+
pixel_colors[i] = 0;
194+
}
195+
196+
std::string line;
197+
std::string temp;
198+
std::string color;
199+
std::istringstream stream;
200+
uint32_t array_pos = 0;
201+
uint32_t parsed;
202+
for (size_t y = 0; y < lines.size(); y++) {
203+
line = lines[y];
204+
205+
if (ignore_linebreaks && temp.length() > 0) {
206+
line = temp + line;
207+
temp = "";
208+
}
209+
210+
while (line.length() > 0) {
211+
for (uint16_t x = 0; x < width; x++) {
212+
if (line.length() < uint32_t((x + 1) * hex_len)) {
213+
temp = line.substr(x * hex_len,
214+
line.length() - x * hex_len);
215+
line = "";
216+
break;
217+
}
218+
219+
if (ignore_linebreaks) {
220+
if (y != 0) {
221+
array_pos += channels;
222+
}
223+
} else {
224+
array_pos = y * width * channels + x * channels;
225+
}
226+
227+
color = line.substr(x * hex_len, hex_len);
228+
if (hex_len <= 4) {
229+
color.resize(hex_len * 2);
230+
for (int8_t i = hex_len - 1; i >= 0; i--) {
231+
color[i * 2 + 1] = color[i * 2] = color[i];
232+
}
233+
}
234+
235+
stream.str(color);
236+
stream >> std::hex >> parsed;
237+
238+
if (stream.rdbuf()->in_avail() > 0) {
239+
cerr << line.substr(x * hex_len, hex_len)
240+
<< " can't be parsed as hex input!" << endl;
241+
} else {
242+
pixel_colors[array_pos] = (parsed >> 16) & 0xFF;
243+
pixel_colors[array_pos + 1] = (parsed >> 8) & 0xFF;
244+
pixel_colors[array_pos + 2] = parsed & 0xFF;
245+
if (channels == 4) {
246+
pixel_colors[array_pos + 3] = (parsed >> 24) & 0xFF;
247+
}
248+
}
249+
250+
stream.clear();
251+
}
252+
253+
if (line.length() > width * hex_len) {
254+
line = line.substr(width * hex_len,
255+
line.length() - width * hex_len);
256+
} else {
257+
line = "";
258+
}
259+
}
260+
}
261+
262+
return pixel_colors;
263+
}
264+
257265
void printHelp() {
258266
cout << "Hex to image Help" << endl;
259267
cout << "=================" << endl;

src/hex-to-image.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#ifndef SRC_HEX_TO_IMAGE_H_
77
#define SRC_HEX_TO_IMAGE_H_
88

9+
#include <string>
10+
#include <vector>
11+
912
enum class Commands {
1013
Null,
1114
Help,
@@ -20,6 +23,17 @@ enum class Commands {
2023

2124
int main(const int argc, char **argv);
2225

26+
/**
27+
* Converts the content of the input to pixel colors.
28+
*
29+
* @param lines One std::string per line of input hex codes.
30+
* @param hex_len The number of hexadecimal digits per pixel.
31+
* @param width The width of the output image in pixels. Will be modified depending on the input.
32+
* @param height The height of the output image in pixels. Will be modified depending on the input.
33+
* @return An uint8_t array containing the color codes. One value per channel per pixel.
34+
*/
35+
uint8_t *convert(const std::vector<std::string> lines, const uint8_t hex_len, uint16_t &width, uint16_t &height);
36+
2337
/**
2438
* Prints the command help output to the standard output.
2539
*/

src/meson.build

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
if get_option('dynamic')
2-
executable('hex-to-image', ['hex-to-image.cpp', 'stb_image_write.h'])
2+
exe = executable('hex-to-image', ['hex-to-image.cpp', 'stb_image_write.h'])
33
else
4-
executable('hex-to-image', ['hex-to-image.cpp', 'stb_image_write.h'], cpp_args : ['-static', '-static-libgcc', '-static-libstdc++'], link_args: ['-static', '-static-libgcc', '-static-libstdc++'])
4+
exe = executable('hex-to-image', ['hex-to-image.cpp', 'stb_image_write.h'], cpp_args : ['-static', '-static-libgcc', '-static-libstdc++'], link_args: ['-static', '-static-libgcc', '-static-libstdc++'])
55
endif
6+
7+
hello_world_in = join_paths(join_paths(meson.source_root(), 'test'), 'hello-world.txt')
8+
test('hello world test(3 digits)', exe, args: ['-d', '3', '-i', hello_world_in, '-o', 'hello-world.png', '--override'])
9+
10+
test_in = join_paths(join_paths(meson.source_root(), 'test'), 'test.txt')
11+
test('test test(3 digits)', exe, args: ['-i', test_in, '-o', 'test.png', '--override'])

test/hello-world.png

184 Bytes
Loading

test/hello-world.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2+
000FFF000000FFF000FFFFFFFFF000FFF000000000FFF000000000000FFFFFF000000000000FFF000000000FFF000000FFFFFF000000FFFFFF000000FFF000000000FFFFFF000000
3+
000FFF000000FFF000FFF000000000FFF000000000FFF000000000FFF000000FFF000000000FFF000FFF000FFF000FFF000000FFF000FFF000FFF000FFF000000000FFF000FFF000
4+
000FFFFFFFFFFFF000FFFFFF000000FFF000000000FFF000000000FFF000000FFF000000000FFF000FFF000FFF000FFF000000FFF000FFFFFF000000FFF000000000FFF000FFF000
5+
000FFF000000FFF000FFF000000000FFF000000000FFF000000000FFF000000FFF000000000000FFF000FFF000000FFF000000FFF000FFF000FFF000FFF000000000FFF000FFF000
6+
000FFF000000FFF000FFFFFFFFF000FFFFFFFFF000FFFFFFFFF000000FFFFFF000000000000000FFF000FFF000000000FFFFFF000000FFF000FFF000FFFFFFFFF000FFFFFF000000
7+
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

test/test.png

119 Bytes
Loading

test/test.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2+
00000000ff0000ff0000ff0000ff0000ff0000000000ff0000ff0000ff0000000000000000ff0000ff0000ff0000000000ff0000ff0000ff0000ff0000ff00000000
3+
00000000000000000000ff0000000000000000000000ff0000000000000000000000ff0000000000000000000000000000000000000000ff00000000000000000000
4+
00000000000000000000ff0000000000000000000000ff0000ff0000000000000000000000ff0000ff0000000000000000000000000000ff00000000000000000000
5+
00000000000000000000ff0000000000000000000000ff0000000000000000000000000000000000000000ff0000000000000000000000ff00000000000000000000
6+
00000000000000000000ff0000000000000000000000ff0000ff0000ff0000000000ff0000ff0000ff0000000000000000000000000000ff00000000000000000000
7+
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

0 commit comments

Comments
 (0)