Compare commits

..

No commits in common. 'master' and 'v1.0.0' have entirely different histories.

  1. 24
      CMakeLists.txt
  2. 53
      README.md
  3. BIN
      docs/logo_qr.png
  4. 232
      docs/logo_qr.svg
  5. 98
      main.cpp
  6. 11
      src/ConsoleRenderer.hpp
  7. 61
      src/PNGRenderer.hpp
  8. 58
      src/QR.cpp
  9. 37
      src/QR.hpp
  10. 8
      src/Renderer.hpp
  11. 33
      src/SVGRenderer.hpp
  12. 21
      src/renderers/BMPRenderer.hpp
  13. 21
      src/renderers/JPGRenderer.hpp
  14. 21
      src/renderers/PNGRenderer.hpp
  15. 59
      src/renderers/PixelRenderer.hpp
  16. 12
      src/util.hpp

@ -1,10 +1,6 @@
cmake_minimum_required(VERSION 3.14...3.25)
project(
qr
VERSION 1.1.0
LANGUAGES CXX
)
set (CXX_STANDARD 23)
if (DEFINED ENV{ARCH})
set(ARCH $ENV{ARCH})
@ -14,24 +10,20 @@ endif()
set(EXE_NAME "qr_${CMAKE_PROJECT_VERSION}-${ARCH}")
message(STATUS "ARCH:: ${ARCH}")
project(
qr
VERSION 1.0.0
LANGUAGES CXX
)
configure_file(main.cpp main_substitute.cpp)
message(STATUS "ARCH:: ${ARCH}")
file(GLOB_RECURSE sources main_substitute.cpp src/*.hpp src/*.cpp lib/*.hpp lib/*.cpp)
file(GLOB_RECURSE sources main.cpp src/*.hpp src/*.cpp lib/*.hpp lib/*.cpp)
add_executable(qr ${sources})
set_target_properties(qr PROPERTIES OUTPUT_NAME ${EXE_NAME})
target_compile_options(qr PUBLIC -Wall -std=c++20 -arch ${ARCH})
target_include_directories(qr PRIVATE src lib)
add_custom_target(man ALL)
add_custom_command(
TARGET man
COMMAND help2man -h "-h" -v "-v" -o qr.7 ./${EXE_NAME}
COMMAND gzip -f qr.7
)
install(TARGETS qr RUNTIME DESTINATION bin)
install(PROGRAMS build/${EXE_NAME} DESTINATION bin RENAME qr)
install(FILES build/qr.7.gz DESTINATION /usr/local/share/man/man7/)

@ -1,56 +1,3 @@
# qr
– a QR code generator for the command line
![qr](docs/logo_qr.svg)
## Usage
This software currently supports outputting to the following formats:
* svg
* PNG
* JPG
* Bitmap
or directly to the console, as kind of an *"ascii art"*.
after installing via `make install`, you can read more in the man page by calling `man qr`.
### Options
```
-f --format output file format. can be one of "cli, png, svg, jpg, bmp"
-h --help show this help
-i --input take data from this argument instead of stdin
-o --output output file name without extension
-s --size desired output file size in pixels
-t --type output QR code type. can be one of "small, medium, large"
-v --version shows version info
```
### Examples
```bash
bash> qr -i "this is from parameter" -f png -s 512 -o my_qrcode_file
bash> echo "this is from stdin" | qr -t small -f png -s 512 -o my_qrcode_file_with_low_ecc
```
## Installation
You can just pick the newest version from the ["Releases" page][releases], or build the software yourself.
### Building
You will need:
* cmake
* make
* a modern C++ compiler that supports `c++20`
```bash
# clone the repo
bash ~/> git clone https://git.mike-ochmann.de/MassiveDynamic/qr.git
# move into the repository
bash ~/> cd qr
# create the build directory and move into it
bash ~/qr> mkdir build && cd build
# run `cmake`
bash ~/qr/build> cmake ..
# make and install the software
bash ~/qr/build> make install
```
[releases]: releases/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

@ -1,232 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Massive Dynamic qr, massivedynamic::SVGRenderer -->
<svg version="1.1" id="qrcode" xmlns="http://www.w3.org/2000/svg" x="0" y="0"
viewBox="0 0 128 128" width="128" height="128" xml:space="preserve">
<rect x="0" y="0" width="128" height="128" style="fill: white;" />
<rect x="5.56522" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="11.1304" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="33.3913" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="89.0435" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="5.56522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="11.1304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="16.6957" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="22.2609" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="27.8261" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="33.3913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="33.3913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="33.3913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="33.3913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="33.3913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="33.3913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="11.1304" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="33.3913" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="89.0435" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="38.9565" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="44.5217" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="44.5217" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="44.5217" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="44.5217" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="50.087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="11.1304" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="33.3913" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="44.5217" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="77.913" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="55.6522" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="61.2174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="33.3913" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="44.5217" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="77.913" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="66.7826" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="11.1304" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="72.3478" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="89.0435" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="77.913" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="11.1304" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="33.3913" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="77.913" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="89.0435" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="83.4783" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="89.0435" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="89.0435" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="77.913" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="89.0435" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="94.6087" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="50.087" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="55.6522" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="61.2174" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="72.3478" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="77.913" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="100.174" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="105.739" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="83.4783" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="94.6087" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="111.304" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="116.87" y="111.304" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="5.56522" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="11.1304" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="16.6957" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="22.2609" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="27.8261" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="33.3913" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="38.9565" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="66.7826" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="77.913" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="100.174" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
<rect x="105.739" y="116.87" width="5.56522" height="5.56522" style="fill: black; stroke: black; stroke-width: 0.1%;" />
</svg>

Before

Width:  |  Height:  |  Size: 28 KiB

@ -3,50 +3,25 @@
#include <iostream>
#include <sstream>
#include <qrcodegen.hpp>
#include "util.hpp"
#include "QR.hpp"
// Version is injected through cmake
constexpr const char* VERSION = "@qr_VERSION@";
#define UNUSED(var) (void) var;
constexpr const char* VERSION = "1.0.0";
void printHelp() {
std::string helpText = R"EOF(
qr is a tool for generating QR codes from the commandline
Usage: qr [OPTION]... --input "data to encapsulate"
*Caveats*
With no `--input` parameter defined, read STDIN
In pixel based renderers (i.e. PNG), the output code may not be exactly
centered, as the amount of segment may not correspond to the specified
output size.
Options:
-f --format output file format. can be one of "cli, png, svg, jpg, bmp"
-h --help show this help
-i --input take data from this argument instead of stdin
-o --output output file name without extension
-s --size desired output file size in pixels
-t --type output QR code type. can be one of "small, medium, large"
-v --version shows version info
Examples:
qr -i "this is from parameter" -f png -s 512 -o my_qrcode_file
echo "this is from stdin" | qr -t small -f png -s 512 -o my_qrcode_file_with_low_ecc
Copyright:
(C) 2023, MikO <miko@massivedynamic.eu>
*License*
Released under MIT license
Report bugs and issues at out issue tracker:
https://git.mike-ochmann.de/MassiveDynamic/qr/issues
(C) 2023, MikO <miko@massivedynamic.eu>
a tool for generating QR codes
Released under MIT license.
Usage:
-f --format output file format. can be one of "cli, png, svg"
-h --help show this help
-i --input take data from this argument instead of stdin
-o --output output file name
-s --size desired output file size in pixels
-t --type output QR code type. can be one of "small, medium, large"
)EOF";
std::cout << "qr " << VERSION;
std::cout << helpText << std::endl;
@ -58,32 +33,28 @@ int main(int argc, char* argv[]) {
exit(1);
}
const option options[] = {
{"help", no_argument, nullptr, 'h'},
{"input", required_argument, nullptr, 'i'},
{"output", required_argument, nullptr, 'o'},
{"size", required_argument, nullptr, 's'},
{"type", required_argument, nullptr, 't'},
{"format", required_argument, nullptr, 'f'},
{"version", no_argument, nullptr, 'v'},
{"help", no_argument, nullptr, 'h'},
{"input", required_argument, nullptr, 'i'},
{"output", required_argument, nullptr, 'o'},
{"size", required_argument, nullptr, 's'},
{"type", required_argument, nullptr, 't'},
{"format", required_argument, nullptr, 'f'},
{nullptr}
};
std::string outputFile;
std::string paramData;
size_t segmentSize = 0;
bool fromStdin = true;
bool anyParameterSet = false;
qrcodegen::QrCode::Ecc type = qrcodegen::QrCode::Ecc::LOW;
massivedynamic::Type type = massivedynamic::Type::MEDIUM;
massivedynamic::Format format = massivedynamic::Format::CONSOLE;
bool fromStdin = true;
std::string paramData = "";
for(;;) {
int index = -1;
int result = getopt_long(argc, argv, "vho:s:t:f:i:", options, &index);
int result = getopt_long(argc, argv, "ho:s:t:f:i:", options, &index);
if (result == -1)
break;
anyParameterSet = true;
const option* opt = &options[index];
UNUSED(opt);
switch(result) {
@ -99,13 +70,12 @@ int main(int argc, char* argv[]) {
case 't': {
std::string value = optarg;
if (value == "small")
type = qrcodegen::QrCode::Ecc::LOW;
type = massivedynamic::Type::SMALL;
else if (value == "medium")
type = qrcodegen::QrCode::Ecc::MEDIUM;
type = massivedynamic::Type::MEDIUM;
else if (value == "large")
type = qrcodegen::QrCode::Ecc::HIGH;
type = massivedynamic::Type::LARGE;
else {
std::cerr << "ERROR: type (-t, --type) has to be one of 'small', 'medium' or 'large'" << std::endl;
printHelp();
return 1;
}
@ -113,17 +83,12 @@ int main(int argc, char* argv[]) {
}
case 'f': {
std::string value = optarg;
static_assert(massivedynamic::FormatLength == 5, "exhaustive formats: did you miss to add something here?");
if (value == "cli")
format = massivedynamic::Format::CONSOLE;
else if (value == "svg")
format = massivedynamic::Format::SVG;
else if (value == "png")
format = massivedynamic::Format::PNG;
else if (value == "jpg")
format = massivedynamic::Format::JPG;
else if (value == "bmp")
format = massivedynamic::Format::BMP;
else {
printHelp();
return 1;
@ -135,10 +100,6 @@ int main(int argc, char* argv[]) {
paramData = optarg;
break;
}
case 'v': {
std::cout << "qr " << VERSION << std::endl;
exit(0);
}
case 'h':
default:
printHelp();
@ -162,8 +123,6 @@ int main(int argc, char* argv[]) {
if (isatty(fileno(stdin)) || data.str().empty()) {
std::cerr << "ERROR: no data from stdinput." << std::endl;
if(!anyParameterSet)
printHelp();
exit(1);
}
} else
@ -179,8 +138,7 @@ int main(int argc, char* argv[]) {
return 1;
}
std::unique_ptr<massivedynamic::QR> qr = std::make_unique<massivedynamic::QR>(data.str(), outputFile, segmentSize, type);
qr->render(format);
std::unique_ptr<massivedynamic::QR> qr = std::make_unique<massivedynamic::QR>(data.str(), outputFile, segmentSize, type, format);
return 0;
}

@ -1,7 +1,5 @@
#pragma once
#include <iomanip>
#include "Renderer.hpp"
namespace massivedynamic {
@ -12,17 +10,18 @@ class ConsoleRenderer : public Renderer {
virtual void render(const std::string&) override {
int border = 1;
std::cout << std::setfill('\n') << std::setw(border) << "";
std::cout << std::string(border, '\n');
for (int y = 0; y < sourceSize; y++) {
std::cout << std::string(border * 2, ' ');
for (int x = 0; x < sourceSize; x++) {
bool isFilled = pixels.at(y * sourceSize + x);
std::cout << (isFilled ? "██" : " ");
}
std::cout << std::setfill(' ') << std::setw(border * 2) << '\n';
std::cout << std::string(border * 2, ' ');
std::cout << '\n';
}
std::cout << std::setfill('\n') << std::setw(border) << "";
std::cout.flush();
std::cout << std::string(border, '\n');
std::cout << std::endl;
}
};

@ -0,0 +1,61 @@
#pragma once
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <vector>
#include <string>
#include <iostream>
#include "stb_image_write.hpp"
#include "Renderer.hpp"
namespace massivedynamic {
typedef uint32_t Color;
class PNGRenderer : public Renderer {
private:
constexpr static Color BLACK = 0xFF000000;
constexpr static Color WHITE = 0xFFFFFFFF;
std::vector<Color> bitmap;
void drawPixelScaled(size_t x, size_t y, Color color) {
size_t pixelSize = this->targetSize / (this->sourceSize + 2);
if (pixelSize < 1) {
std::cerr << "ERROR: output file size is too small" << std::endl;
exit(1);
}
size_t absoluteX = pixelSize * x;
size_t absoluteY = pixelSize * y;
for (size_t localY = absoluteY + pixelSize; localY < absoluteY + pixelSize + pixelSize; localY++) {
for (size_t localX = absoluteX + pixelSize; localX < absoluteX + pixelSize + pixelSize; localX++) {
size_t absPos = localY * this->targetSize + localX;
this->bitmap.at(absPos) = color;
}
}
}
public:
PNGRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : Renderer(pixels, sourceSize, targetSize) {
if (this->targetSize == 0)
this->targetSize = sourceSize;
this->bitmap = std::vector<Color>(targetSize * targetSize, 0xFFFFFFFF);
}
virtual void render(const std::string& filename) override {
for (size_t y = 0; y < sourceSize; y++) {
for (size_t x = 0; x < sourceSize; x++) {
Color color = pixels.at(y * sourceSize + x) ? PNGRenderer::BLACK : PNGRenderer::WHITE;
this->drawPixelScaled(x, y, color);
}
}
stbi_write_png(filename.c_str(), targetSize, targetSize, 4, this->bitmap.data(), targetSize * sizeof(Color));
}
};
}

@ -1,39 +1,45 @@
#include <iostream>
#include <vector>
#include <cassert>
#include "qrcodegen.hpp"
#include "QR.hpp"
#include "renderers/ConsoleRenderer.hpp"
#include "renderers/PNGRenderer.hpp"
#include "renderers/SVGRenderer.hpp"
#include "renderers/JPGRenderer.hpp"
#include "renderers/BMPRenderer.hpp"
#include "ConsoleRenderer.hpp"
#include "PNGRenderer.hpp"
#include "SVGRenderer.hpp"
namespace massivedynamic {
QR::QR(const std::string& data, std::string outputFile, size_t size, qrcodegen::QrCode::Ecc type) : outputFile(std::move(outputFile)),
qr(qrcodegen::QrCode::encodeText(data.c_str(), type)), size(size) {
this->pixels.reserve(this->qr.getSize() * this->qr.getSize());
// this is inherently stupid, but "qrcodegen::QrCode" does not give access to the
// `segments` vector member and the class itself is marked final.
for (int y = 0; y < qr.getSize(); y++) {
for (int x = 0; x < qr.getSize(); x++)
this->pixels.push_back(qr.getModule(x, y));
QR::QR(const std::string& data, std::string outputFile, size_t size, Type type, Format format) : outputFile(std::move(outputFile)) {
qrcodegen::QrCode::Ecc errorCorrectionLevel = qrcodegen::QrCode::Ecc::HIGH;
switch(type) {
case Type::SMALL:
errorCorrectionLevel = qrcodegen::QrCode::Ecc::LOW;
break;
case Type::MEDIUM:
errorCorrectionLevel = qrcodegen::QrCode::Ecc::MEDIUM;
break;
default:
case Type::LARGE:
errorCorrectionLevel = qrcodegen::QrCode::Ecc::HIGH;
break;
}
}
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(data.c_str(), errorCorrectionLevel);
this->renderers.insert({Format::CONSOLE, std::make_unique<ConsoleRenderer>(this->pixels, qr.getSize(), size)});
this->renderers.insert({Format::PNG, std::make_unique<PNGRenderer>(this->pixels, qr.getSize(), size)});
this->renderers.insert({Format::SVG, std::make_unique<SVGRenderer>(this->pixels, qr.getSize(), size)});
void QR::render(Format format) {
static_assert(FormatLength == 5, "exhaustive formats: did you miss to add something here?");
switch(format) {
case Format::CONSOLE : this->renderTyped<ConsoleRenderer>(); break;
case Format::PNG : this->renderTyped<PNGRenderer>(); break;
case Format::SVG : this->renderTyped<SVGRenderer>(); break;
case Format::JPG : this->renderTyped<JPGRenderer>(); break;
case Format::BMP : this->renderTyped<BMPRenderer>(); break;
UNUSED_CASE(Format::END);
for (int y = 0; y < qr.getSize(); y++) {
for (int x = 0; x < qr.getSize(); x++) {
bool isFilled = qr.getModule(x, y);
this->pixels.push_back(isFilled ? true : false);
}
}
this->renderers.at(format)->render(this->outputFile);
}
}

@ -2,42 +2,33 @@
#include <vector>
#include <string>
#include <qrcodegen.hpp>
#include "util.hpp"
#include <memory>
#include <unordered_map>
#include "qrcodegen.hpp"
#include "Renderer.hpp"
namespace massivedynamic {
typedef uint32_t Color;
enum class Type {
SMALL,
MEDIUM,
LARGE
};
enum class Format {
CONSOLE,
SVG,
PNG,
JPG,
BMP,
END
PNG
};
constexpr size_t FormatLength = static_cast<size_t>(Format::END);
class QR {
private:
std::string outputFile;
std::vector<bool> pixels;
qrcodegen::QrCode qr;
size_t size;
std::unordered_map<Format, std::unique_ptr<Renderer>> renderers;
public:
QR(const std::string& data, std::string outputFile, size_t size, qrcodegen::QrCode::Ecc type);
QR(const QR&&) = delete;
QR(QR&) = delete;
~QR() = default;
QR& operator=(const QR&) = delete;
void render(Format format);
template<typename T>
void renderTyped() {
T renderer = T(this->pixels, this->qr.getSize(), this->size);
renderer.render(this->outputFile);
}
QR(const std::string& data, std::string outputFile, size_t size, Type type, Format format);
};
}

@ -1,8 +1,6 @@
#pragma once
#include <vector>
#include <string>
#include <cstddef>
namespace massivedynamic {
@ -13,11 +11,7 @@ class Renderer {
size_t targetSize;
public:
Renderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : pixels(pixels), sourceSize(sourceSize), targetSize(targetSize) {}
Renderer(const Renderer&&) = delete;
Renderer(Renderer&) = delete;
virtual ~Renderer() = default;
Renderer& operator=(const Renderer&) = delete;
virtual ~Renderer() = default;
virtual void render(const std::string& filename) = 0;
};

@ -2,47 +2,42 @@
#include <sstream>
#include <fstream>
#include <math.h>
#include "Renderer.hpp"
namespace massivedynamic {
class SVGRenderer : public Renderer {
private:
constexpr static float BORDER_WIDTH = 0.1f;
public:
SVGRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : Renderer(pixels, sourceSize, targetSize) {
if (this->targetSize == 0)
this->targetSize = sourceSize * (2 * SVGRenderer::BORDER_WIDTH);
}
SVGRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : Renderer(pixels, sourceSize, targetSize) {}
virtual void render(const std::string& filename) override {
std::ofstream file;
file.open(filename + ".svg");
std::stringstream file;
std::string base = R"EOF(<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Massive Dynamic qr, massivedynamic::SVGRenderer -->
<svg version="1.1" id="qrcode" xmlns="http://www.w3.org/2000/svg" x="0" y="0"
)EOF";
<svg version="1.1" id="qrcode" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
)EOF";
file << base;
file << "viewBox=\"0 0 " << this->targetSize << " " << this->targetSize << "\" width=\"" << this->targetSize << "\" height=\"" << this->targetSize << "\" xml:space=\"preserve\">" << '\n';
file << "viewBox=\"0 0 " << this->targetSize << " " << this->targetSize << "\" xml:space=\"preserve\">" << '\n';
file << " <rect x=\"0\" y=\"0\" width=\"" << this->targetSize << "\" height=\"" << this->targetSize << "\" style=\"fill: white;\" />" << '\n';
float pixelSize = static_cast<float>(this->targetSize) / static_cast<float>(this->sourceSize + 2);
size_t pixelSize = this->targetSize / (this->sourceSize + 2);
for (size_t y = 0; y < this->sourceSize; y++) {
for (size_t x = 0; x < this->sourceSize; x++) {
if (!this->pixels.at(y * this->sourceSize + x))
continue;
float rectX = x * pixelSize + pixelSize;
float rectY = y * pixelSize + pixelSize;
file << " <rect x=\"" << rectX << "\" y=\"" << rectY << "\" width=\"" << pixelSize << "\" height=\"" << pixelSize << "\" style=\"fill: black; stroke: black; stroke-width: " << SVGRenderer::BORDER_WIDTH << "%;\" />" << '\n';
size_t rectX = x * pixelSize + pixelSize;
size_t rectY = y * pixelSize + pixelSize;
file << " <rect x=\"" << rectX << "\" y=\"" << rectY << "\" width=\"" << pixelSize << "\" height=\"" << pixelSize << "\" style=\"fill: black; stroke: black; stroke-width: 3;\" />" << '\n';
}
}
file << "</svg>\n";
file << "</svg>" << std::endl;
file.close();
std::ofstream outFile;
outFile.open(filename);
outFile << file.str();
outFile.close();
}
};

@ -1,21 +0,0 @@
#pragma once
#include <string>
#include "PixelRenderer.hpp"
namespace massivedynamic {
class BMPRenderer final : public PixelRenderer {
public:
BMPRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : PixelRenderer(pixels, sourceSize, targetSize) {}
virtual void render(const std::string& filename) override {
this->generateBuffer();
stbi_write_bmp((filename + ".bmp").c_str(), targetSize, targetSize, 4, this->bitmap.data());
}
};
}

@ -1,21 +0,0 @@
#pragma once
#include <string>
#include "PixelRenderer.hpp"
namespace massivedynamic {
class JPGRenderer final: public PixelRenderer {
public:
JPGRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : PixelRenderer(pixels, sourceSize, targetSize) {}
virtual void render(const std::string& filename) override {
this->generateBuffer();
stbi_write_jpg((filename + ".jpg").c_str(), targetSize, targetSize, 4, this->bitmap.data(), sizeof(Color) * targetSize);
}
};
}

@ -1,21 +0,0 @@
#pragma once
#include <string>
#include "PixelRenderer.hpp"
namespace massivedynamic {
class PNGRenderer final: public PixelRenderer {
public:
PNGRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) : PixelRenderer(pixels, sourceSize, targetSize) {}
virtual void render(const std::string& filename) override {
this->generateBuffer();
stbi_write_png((filename + ".png").c_str(), targetSize, targetSize, 4, this->bitmap.data(), sizeof(Color) * targetSize);
}
};
}

@ -1,59 +0,0 @@
#pragma once
#include <math.h>
#include <iostream>
#include <cassert>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.hpp>
#include "util.hpp"
#include "Renderer.hpp"
namespace massivedynamic {
class PixelRenderer : public Renderer {
protected:
size_t pixelSize;
size_t border;
std::vector<Color> bitmap;
void drawPixelScaled(size_t x, size_t y, Color color) {
size_t pixelSize = this->pixelSize;
assert(pixelSize > 1 && "ERROR: output file size is too small");
size_t absoluteX = pixelSize * x + this->border;
size_t absoluteY = pixelSize * y + this->border;
for (size_t localY = absoluteY; localY < absoluteY + pixelSize; localY++) {
for (size_t localX = absoluteX; localX < absoluteX + pixelSize; localX++) {
this->bitmap.at(localY * this->targetSize + localX) = color;
}
}
}
public:
enum Colors : Color {
BLACK = 0xFF000000,
WHITE = 0xFFFFFFFF
};
PixelRenderer(const std::vector<bool>& pixels, size_t sourceSize, size_t targetSize) :
Renderer(pixels, sourceSize, targetSize == 0 ? (sourceSize + 2) * 2 : targetSize),
pixelSize(round(static_cast<float>(this->targetSize) / static_cast<float>(this->sourceSize + 2))),
border(round(static_cast<float>(this->targetSize - this->pixelSize * this->sourceSize) / 2.0f)),
bitmap(std::vector<Color>(this->targetSize * this->targetSize, Colors::WHITE)) {}
virtual void generateBuffer() {
for (size_t y = 0; y < sourceSize; y++) {
for (size_t x = 0; x < sourceSize; x++) {
if (!pixels.at(y * sourceSize + x))
continue;
this->drawPixelScaled(x, y, Colors::BLACK);
}
}
}
};
}

@ -1,12 +0,0 @@
#pragma once
#include <stdint.h>
#define UNUSED(var) (void) var;
#define UNUSED_CASE(name) case name: break;
namespace massivedynamic {
using Color = uint32_t;
}
Loading…
Cancel
Save