src/BarcodeCommand.h
branchv_0
changeset 5 8f434dc38444
parent 4 500ce0b934e7
equal deleted inserted replaced
4:500ce0b934e7 5:8f434dc38444
       
     1 /**
       
     2  * Relational pipes
       
     3  * Copyright © 2021 František Kučera (Frantovo.cz, GlobalCode.info)
       
     4  *
       
     5  * This program is free software: you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation, version 3 of the License.
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
       
    16  */
       
    17 #pragma once
       
    18 
       
    19 #include <codecvt>
       
    20 #include <memory>
       
    21 #include <algorithm>
       
    22 #include <iostream>
       
    23 #include <stdexcept>
       
    24 
       
    25 #include <Magick++.h>
       
    26 #include <zbar.h>
       
    27 
       
    28 #include "Configuration.h"
       
    29 
       
    30 namespace relpipe {
       
    31 namespace in {
       
    32 namespace barcode {
       
    33 
       
    34 class BarcodeCommand {
       
    35 private:
       
    36 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: use platform encoding as default / check zbar encoding
       
    37 
       
    38 
       
    39 public:
       
    40 
       
    41 	void process(Configuration& configuration, std::shared_ptr<writer::RelationalWriter> writer, std::function<void() > relationalWriterFlush) {
       
    42 
       
    43 		// TODO: require PNM input and get rid off the ImageMagick dependency?
       
    44 		Magick::Image magick("/dev/stdin");
       
    45 		int width = magick.columns();
       
    46 		int height = magick.rows();
       
    47 		Magick::Blob blob;
       
    48 		magick.modifyImage();
       
    49 		magick.write(&blob, "GRAY", 8);
       
    50 		const void *raw = blob.data();
       
    51 
       
    52 		zbar::Image image(width, height, "Y800", raw, width * height);
       
    53 		zbar::ImageScanner scanner;
       
    54 
       
    55 		writer->startRelation(L"symbol",{
       
    56 			{L"id", relpipe::writer::TypeId::INTEGER},
       
    57 			{L"type", relpipe::writer::TypeId::STRING},
       
    58 			// {L"addon_name", relpipe::writer::TypeId::STRING},
       
    59 			{L"value", relpipe::writer::TypeId::STRING},
       
    60 			// {L"xml", relpipe::writer::TypeId::STRING},
       
    61 			{L"x", relpipe::writer::TypeId::INTEGER},
       
    62 			{L"y", relpipe::writer::TypeId::INTEGER},
       
    63 			{L"width", relpipe::writer::TypeId::INTEGER},
       
    64 			{L"height", relpipe::writer::TypeId::INTEGER},
       
    65 		}, true);
       
    66 
       
    67 		int n = scanner.scan(image);
       
    68 
       
    69 		relpipe::common::type::Integer id = 0;
       
    70 		for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol, id++) {
       
    71 			writer->writeAttribute(&id, typeid (id));
       
    72 			writer->writeAttribute(convertor.from_bytes(symbol->get_type_name()));
       
    73 			// writer->writeAttribute(convertor.from_bytes(symbol->get_addon_name()));
       
    74 			writer->writeAttribute(convertor.from_bytes(symbol->get_data()));
       
    75 			// writer->writeAttribute(convertor.from_bytes(symbol->xml()));
       
    76 
       
    77 			relpipe::common::type::Integer minX = 0;
       
    78 			relpipe::common::type::Integer minY = 0;
       
    79 			relpipe::common::type::Integer maxX = 0;
       
    80 			relpipe::common::type::Integer maxY = 0;
       
    81 
       
    82 			// TODO: return original polygon in XML
       
    83 			for (int i = 0, locationSize = symbol->get_location_size(); i < locationSize; i++) {
       
    84 				relpipe::common::type::Integer x = symbol->get_location_x(i);
       
    85 				relpipe::common::type::Integer y = symbol->get_location_y(i);
       
    86 				minX = minX ? std::min(minX, x) : x;
       
    87 				minY = minY ? std::min(minY, y) : y;
       
    88 				maxX = std::max(maxX, x);
       
    89 				maxY = std::max(maxY, y);
       
    90 			}
       
    91 
       
    92 			relpipe::common::type::Integer width = maxX - minX;
       
    93 			relpipe::common::type::Integer height = maxY - minY;
       
    94 
       
    95 			writer->writeAttribute(&minX, typeid (minX));
       
    96 			writer->writeAttribute(&minY, typeid (minY));
       
    97 			writer->writeAttribute(&width, typeid (width));
       
    98 			writer->writeAttribute(&height, typeid (height));
       
    99 		}
       
   100 
       
   101 		if (configuration.listPolygonPoints) {
       
   102 			relpipe::common::type::Integer id = 0;
       
   103 
       
   104 			writer->startRelation(L"polygon_point",{
       
   105 				{L"symbol", relpipe::writer::TypeId::INTEGER},
       
   106 				{L"point", relpipe::writer::TypeId::INTEGER},
       
   107 				{L"x", relpipe::writer::TypeId::INTEGER},
       
   108 				{L"y", relpipe::writer::TypeId::INTEGER},
       
   109 			}, true);
       
   110 
       
   111 			for (zbar::Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol, id++) {
       
   112 				for (relpipe::common::type::Integer i = 0, locationSize = symbol->get_location_size(); i < locationSize; i++) {
       
   113 					relpipe::common::type::Integer x = symbol->get_location_x(i);
       
   114 					relpipe::common::type::Integer y = symbol->get_location_y(i);
       
   115 					writer->writeAttribute(&id, typeid (id));
       
   116 					writer->writeAttribute(&i, typeid (i));
       
   117 					writer->writeAttribute(&x, typeid (x));
       
   118 					writer->writeAttribute(&y, typeid (y));
       
   119 				}
       
   120 			}
       
   121 		}
       
   122 
       
   123 		image.set_data(nullptr, 0);
       
   124 	}
       
   125 };
       
   126 
       
   127 }
       
   128 }
       
   129 }