QR-CODE

 Paket io.nayuki.fastqrcodegen;

 java.util.Arrays importieren ;
 java.util.Objects importieren ;


 // Eine anfügbare Folge von Bits (0 und 1), die hauptsächlich von QrSegment verwendet wird. letzte Klasse BitBuffer {

 /*---- Felder ----*/

 int[] Daten; // In jedem 32-Bit-Wort werden die Bits von oben nach unten gefüllt.
 int bitLength; // Immer nicht negativ.


 /*---- Konstrukteur ----*/

 // Erstellt einen leeren Bitpuffer. 
öffentlicher BitBuffer() {
 data = new int[64];
 bitLength = 0;
 }



 /*---- Methoden ----*/

 // Gibt das Bit am angegebenen Index zurück und ergibt 0 oder 1. public int getBit( int index) {
 if (index < 0 || index >= bitLength)
 throw new IndexOutOfBoundsException(); 
return (data[index >>> 5] >>> ~index) & 1;
 }


 // Gibt ein neues Array zurück, das die Bits dieses Puffers darstellt, // gepackt in Bytes in Big Endian. Die aktuelle Bitlänge muss ein Vielfaches von 8 sein. public byte[] getBytes() {
 if (bitLength % 8 != 0)
 throw new IllegalStateException( „Daten sind keine ganze Anzahl von Bytes“ );
 byte[] result = new byte[bitLength / 8]; 
for ( int i = 0; i < result.length; i++)
 result[i] = ( byte )(data[i >>> 2] >>> (~i << 3));
 Ergebnis zurückgeben ;
 }


 // Hängt die angegebene Anzahl niederwertiger Bits des angegebenen Werts // an diesen Puffer an. Erfordert 0 <= len <= 31 und 0 <= val < 2^len. public void appendBits( int val, int len) { 
if (len < 0 || len > 31 || val >>> len != 0)
 throw new IllegalArgumentException( „Wert außerhalb des Bereichs“ );
 if (len > Integer.MAX_VALUE - bitLength)
 throw new IllegalStateException( „Maximale Länge erreicht“ );

 if (bitLength + len + 1 > data.length << 5)
 data = Arrays.copyOf(data, data.length * 2);
 behaupten bitLength + len <= data.length << 5;

 int keep = 32 - (bitLength & 0x1F); 
behaupten 1 <= bleiben && bleiben <= 32;
 if (remain < len) {
 data[bitLength >>> 5] |= val >>> (len - verbleiben);
 bitLength += bleiben;
 behaupten (bitLength & 0x1F) == 0;
 len -= bleiben;
 val &= (1 << len) - 1;
 bleiben = 32;
 }
 data[bitLength >>> 5] |= val << (remain - len);
 bitLength += len;
 }


 // Hängt an diesen Puffer die Bitfolge an, die durch das angegebene // Wortarray und die angegebene Bitlänge dargestellt wird. Erfordert 0 <= len <= 32 * vals.length. 
public void appendBits(int[] vals, int len) {
 Objects.requireNonNull(vals);
 if (len == 0)
 zurückkommen ;
 if (len < 0 || len > vals.length * 32L)
 throw new IllegalArgumentException( „Wert außerhalb des Bereichs“ );
 int WholeWords = len / 32;
 int tailBits = len % 32;
 if (tailBits > 0 && vals[wholeWords] << tailBits != 0) 
throw new IllegalArgumentException( „Letztes Wort muss niedrige Bits löschen“ );
 if (len > Integer.MAX_VALUE - bitLength)
 throw new IllegalStateException( „Maximale Länge erreicht“ );

 while (bitLength + len > data.length * 32)
 data = Arrays.copyOf(data, data.length * 2);

 int shift = bitLength % 32;
 if (shift == 0) {
 System.arraycopy(vals, 0, data, bitLength / 32, (len + 31) / 32);
 bitLength += len; 
} sonst {
 for ( int i = 0; i < WholeWords; i++) {
 int word = vals[i];
 data[bitLength >>> 5] |= word >>> shift;
 bitLength += 32;
 data[bitLength >>> 5] = Wort << (32 - Verschiebung);
 }
 if (tailBits > 0)
 appendBits(vals[wholeWords] >>> (32 - tailBits), tailBits);
 }
 }

 }

 /* * Schnelle QR-Code-Generatorbibliothek 
*
 * Copyright (c) Projekt Nayuki. (MIT-Lizenz)
 * https://www.nayuki.io/page/fast-qr-code-generator-library
 *
 * Hiermit wird jeder Person, die eine Kopie davon erhält, kostenlos die Erlaubnis erteilt
 * diese Software und zugehörige Dokumentationsdateien (die „Software“) zum Handel
 * die Software ohne Einschränkung, einschließlich und ohne Einschränkung der Rechte an
 * Kopien davon verwenden, kopieren, ändern, zusammenführen, veröffentlichen, verteilen, unterlizenzieren und/oder verkaufen
 * die Software und um Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten,
 *vorbehaltlich der folgenden Bedingungen:
 * - Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk müssen darin enthalten sein
 * alle Kopien oder wesentlichen Teile der Software.
 * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges 
* Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt:
 * aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;


 /** * Wird ausgelöst, wenn die bereitgestellten Daten zu keiner QR-Code-Version passen. Zu den Möglichkeiten zur Behandlung dieser Ausnahme gehören: * <ul> * <li><p>Verringern Sie die Fehlerkorrekturstufe, wenn sie größer als {@code Ecc.LOW} war.</p></li> * <li><p >Wenn die erweiterte {@code encodeSegments()}-Funktion mit 6 Argumenten oder die * {@code makeSegmentsOptimally()}-Funktion aufgerufen wurde, dann erhöhen Sie das maxVersion-Argument *, wenn es kleiner als {@link QrCode#MAX_VERSION} war. (Dieser Hinweis gilt nicht für die anderen * Factory-Funktionen, da diese alle Versionen bis {@code QrCode.MAX_VERSION} durchsuchen.)</p></li> 
* <li><p>Teilen Sie die Textdaten in bessere oder optimale Segmente auf, um die Anzahl zu reduzieren
 * Bits erforderlich. (Siehe {@link QrSegmentAdvanced#makeSegmentsOptimally(String,QrCode.Ecc,int,int)
 * QrSegmentAdvanced.makeSegmentsOptimally()}.)</p></li>
 * <li><p>Ändern Sie den Text oder die Binärdaten, um sie kürzer zu gestalten.</p></li>
 * <li><p>Ändern Sie den Text so, dass er zum Zeichensatz eines bestimmten Segmentmodus passt (z. B. alphanumerisch).</p></li>
 * <li><p>Gib den Fehler an den Anrufer/Benutzer weiter.</p></li>
 * </ul>
 * @see QrCode#encodeText(String, QrCode.Ecc)
 * @see QrCode#encodeBinary(byte[], QrCode.Ecc)
 * @see QrCode#encodeSegments(java.util.List, QrCode.Ecc)
 * @see QrCode#encodeSegments(java.util.List, QrCode.Ecc, int, int, int, boolean)
 * @see QrSegmentAdvanced#makeSegmentsOptimally(String, QrCode.Ecc, int, int)
 */ 
öffentliche Klasse DataTooLongException erweitert IllegalArgumentException {

 public DataTooLongException() { }


 public DataTooLongException(String msg) {
 super (Nachricht);
 }

 }

 /* * Schnelle QR-Code-Generatorbibliothek * * Copyright (c) Project Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * 
* Hiermit wird jeder Person, die eine Kopie davon erhält, kostenlos die Erlaubnis erteilt
 * diese Software und zugehörige Dokumentationsdateien (die „Software“) zum Handel
 * die Software ohne Einschränkung, einschließlich und ohne Einschränkung der Rechte an
 * Kopien davon verwenden, kopieren, ändern, zusammenführen, veröffentlichen, verteilen, unterlizenzieren und/oder verkaufen
 * die Software und um Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten,
 *vorbehaltlich der folgenden Bedingungen:
 * - Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk müssen darin enthalten sein
 * alle Kopien oder wesentlichen Teile der Software.
 * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt: 
* aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;

 import java.lang.ref.SoftReference;
 import java.util.HashSet;
 java.util.Map importieren ;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;


 // Ein Thread-sicherer Cache basierend auf Soft-Referenzen. Abschlussklasse Memoizer<T , R> {
 
private final Function<T,R> function;
 Map<T,SoftReference<R>> Cache = new ConcurrentHashMap<>();
 private Set<T> pending = new HashSet<>();


 // Erstellt einen Memoizer basierend auf der angegebenen Funktion, der eine Eingabe benötigt, um eine Ausgabe zu berechnen. public Memoizer(Function<T,R> func) {
 Funktion = Funktion;
 }


 // Berechnet function.apply(arg) oder gibt eine zwischengespeicherte Kopie eines vorherigen Aufrufs zurück. 
öffentliches R get(T arg) {
 // Nicht blockierender schneller Pfad {
 SoftReference<R> ref = cache.get(arg);
 if (ref != null ) {
 R result = ref.get();
 if (Ergebnis != null )
 Ergebnis zurückgeben ;
 }
 }

 // Sequentielle langsame Pfad 
while ( true ) {
 synchronisiert ( dies ) {
 SoftReference<R> ref = cache.get(arg);
 if (ref != null ) {
 R result = ref.get();
 if (Ergebnis != null )
 Ergebnis zurückgeben ;
 Cache.remove(arg);
 }
 behaupten !cache.containsKey(arg);
 
if (pending.add(arg))
 Pause ;

 versuche es mit {
 this.wait();
 } Catch (InterruptedException e) {
 throw new RuntimeException(e);
 }
 }
 }

 versuche es mit {
 R result = function.apply(arg); 
Cache.put(arg, new SoftReference<>(result));
 Ergebnis zurückgeben ;
 } endlich {
 synchronisiert ( dies ) {
 pending.remove(arg);
 this.notifyAll();
 }
 }
 }

 }

 /** * Erzeugt QR-Codes aus Textzeichenfolgen und Byte-Arrays. * 
* <p>Dieses Projekt zielt darauf ab, die beste und übersichtlichste QR-Code-Generator-Bibliothek zu sein. Die primären Ziele sind flexible Möglichkeiten und absolute Korrektheit. Sekundäre Ziele sind eine kompakte Implementierungsgröße und gute Dokumentationskommentare.</p>
 * <p>Homepage dieser schnellen Bibliothek mit Designerklärungen und Benchmarks: <a href="https://www.nayuki.io/page/fast-qr-code-generator-library">https://www. nayuki.io/page/fast-qr-code-generator-library</a></p>
 * <p>Homepage für das Hauptprojekt mit Live-JavaScript-Demo, ausführlichen Beschreibungen und Mitbewerbervergleichen: <a href="https://www.nayuki.io/page/qr-code-generator-library">https: //www.nayuki.io/page/qr-code-generator-library</a></p>
 *
 * <h2>Funktionen</h2>
 * <p>Kernfunktionen:</p>
 * <ul>
 * <li><p>Etwa 1,5× bis 10× schneller als andere Java-Implementierungen</p></li> 
* <li><p>Kürzerer Code, aber mehr Dokumentationskommentare im Vergleich zu konkurrierenden Bibliotheken</p></li>
 * <li><p>Unterstützt die Kodierung aller 40 Versionen (Größen) und aller 4 Fehlerkorrekturstufen gemäß dem QR Code Model 2-Standard</p></li>
 * <li><p>Ausgabeformat: Rohmodule/Pixel des QR-Symbols</p></li>
 * <li><p>Erkennt Finder-ähnliche Strafmuster genauer als andere Implementierungen</p></li>
 * <li><p>Kodiert numerischen und speziell alphanumerischen Text auf weniger Platz als allgemeiner Text</p></li>
 * <li><p>Kodiert japanischen Unicode-Text im Kanji-Modus, um im Vergleich zu UTF-8-Bytes viel Platz zu sparen</p></li>
 * <li><p>Berechnet die optimale Segmentmodusumschaltung für Text mit gemischten numerischen/alphanumerischen/allgemeinen/Kanji-Teilen</p></li>
 * <li><p>Open-Source-Code unter der freizügigen MIT-Lizenz</p></li>
 * </ul> 
* <p>Manuelle Parameter:</p>
 * <ul>
 * <li><p>Der Benutzer kann die zulässige Mindest- und Höchstversionsnummer angeben, dann wählt die Bibliothek automatisch die kleinste Version im Bereich aus, die zu den Daten passt</p></li>
 * <li><p>Der Benutzer kann das Maskenmuster manuell angeben, andernfalls wertet die Bibliothek automatisch alle 8 Masken aus und wählt die optimale aus</p></li>
 * <li><p>Der Benutzer kann eine absolute Fehlerkorrekturstufe angeben oder der Bibliothek erlauben, diese zu erhöhen, wenn dadurch die Versionsnummer nicht erhöht wird</p></li>
 * <li><p>Benutzer können manuell eine Liste von Datensegmenten erstellen und ECI-Segmente hinzufügen</p></li>
 * </ul>
 * <p>Weitere Informationen zur QR-Code-Technologie und zum Design dieser Bibliothek finden Sie auf der Projekthomepage.</p>
 *
 * <h2>Beispiele</h2>
 * <p>Einfache Bedienung:</p>
 * <pre style="margin-left:2em">import java.awt.image.BufferedImage;
 *java.io.File importieren; 
*import javax.imageio.ImageIO;
 *import io.nayuki.fastqrcodegen.*;
 *
 *QrCode qr = QrCode.encodeText("Hallo Welt!", QrCode.Ecc.MEDIUM);
 *BufferedImage img = toImage(qr, 4, 10); // Siehe QrCodeGeneratorDemo
 *ImageIO.write(img, "png", new File("qr-code.png"));</pre>
 * <p>Manueller Betrieb:</p>
 * <pre style="margin-left:2em">import java.util.List;
 *import io.nayuki.fastqrcodegen.*;
 *
 *List<QrSegment> segs = QrSegment.makeSegments("3141592653589793238462643383");
 *QrCode qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, 5, 5, 2, false);
 *for (int y = 0; y < qr.size; y++) {
 * for (int x = 0; x < qr.size; x++) {
 * (... paint qr.getModule(x, y) ...)
 * }
 *</pre>
 */
 Paket io.nayuki.fastqrcodegen;

 /* * Schnelle QR-Code-Generatorbibliothek * * Copyright (c) Project Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * 
* Hiermit wird jeder Person, die eine Kopie davon erhält, kostenlos die Erlaubnis erteilt
 * diese Software und zugehörige Dokumentationsdateien (die „Software“) zum Handel
 * die Software ohne Einschränkung, einschließlich und ohne Einschränkung der Rechte an
 * Kopien davon verwenden, kopieren, ändern, zusammenführen, veröffentlichen, verteilen, unterlizenzieren und/oder verkaufen
 * die Software und um Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten,
 *vorbehaltlich der folgenden Bedingungen:
 * - Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk müssen darin enthalten sein
 * alle Kopien oder wesentlichen Teile der Software.
 * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt: 
* aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;

 java.util.Arrays importieren ;
 java.util.List importieren ;
 java.util.Objects importieren ;


 /** * Ein QR-Code-Symbol, bei dem es sich um eine Art zweidimensionalen Barcode handelt. * Von Denso Wave erfunden und im ISO/IEC 18004-Standard beschrieben. * <p>Instanzen dieser Klasse stellen ein unveränderliches quadratisches Gitter aus dunklen und hellen Zellen dar. * Die Klasse bietet statische Factory-Funktionen zum Erstellen eines QR-Codes aus Text- oder Binärdaten. * Die Klasse deckt die QR-Code-Modell-2-Spezifikation ab und unterstützt alle Versionen (Größen) * von 1 bis 40, alle 4 Fehlerkorrekturstufen und 4 Zeichenkodierungsmodi.</p> * <p>Möglichkeiten zum Erstellen eines QR-Code-Objekts :</p> * <ul> 
* <li><p>Hohe Ebene: Nehmen Sie die Nutzdaten und rufen Sie {@link QrCode#encodeText(String,Ecc)} auf.
 * oder {@link QrCode#encodeBinary(byte[],Ecc)}.</p></li>
 * <li><p>Mittlere Ebene: Erstellen Sie die Liste der {@link QrSegment-Segmente} individuell.
 * und rufen Sie {@link QrCode#encodeSegments(List,Ecc)} auf oder
 * {@link QrCode#encodeSegments(List,Ecc,int,int,int,boolean)</p></li>
 * <li><p>Niedrige Ebene: Passen Sie das Array der Datencodewortbytes (einschließlich Segmentheader und) individuell an
 * endgültige Auffüllung, ausgenommen Fehlerkorrektur-Codewörter), geben Sie die entsprechende Versionsnummer an,
 * und rufen Sie den {@link QrCode#QrCode(int,Ecc,byte[],int)-Konstruktor} auf.</p></li>
 * </ul>
 * <p>(Beachten Sie, dass für alle Methoden die Angabe der gewünschten Fehlerkorrekturstufe erforderlich ist.)</p>
 * @see QrSegment
 */ 
öffentliche Abschlussklasse QrCode {

 /*---- Statische Werksfunktionen (hohe Ebene) ----*/

 /** * Gibt einen QR-Code zurück, der die angegebene Unicode-Textzeichenfolge mit der angegebenen Fehlerkorrekturstufe darstellt. * Als konservative Obergrenze ist der Erfolg dieser Funktion für Zeichenfolgen mit 738 oder weniger * Unicode-Codepunkten (nicht UTF-16-Codeeinheiten) garantiert, wenn die niedrige Fehlerkorrekturstufe verwendet wird. Für die Ausgabe wird automatisch die kleinstmögliche * QR-Code-Version gewählt. Der ECC-Level des Ergebnisses kann höher sein als das *ecl-Argument, wenn dies ohne Erhöhung der Version möglich ist. * @param text der zu kodierende Text (nicht {@code null}), der eine beliebige Unicode-Zeichenfolge sein kann 
* @param ecl die zu verwendende Fehlerkorrekturstufe (nicht {@code null}) (boostbar)
 * @return einen QR-Code (nicht {@code null}), der den Text darstellt
 * @throws NullPointerException, wenn die Text- oder Fehlerkorrekturstufe {@code null} ist
 * @throws DataTooLongException, wenn der Text nicht in die Datei passt
 * Größte Version des QR-Codes am ECL, was bedeutet, dass er zu lang ist
 */
 public static QrCode encodeText(String text, Ecc ecl) {
 Objects.requireNonNull(text);
 Objects.requireNonNull(ecl);
 List<QrSegment> segs = QrSegment.makeSegments(text);
 return encodeSegments(segs, ecl);
 }


 /** * Gibt einen QR-Code zurück, der die angegebenen Binärdaten mit der angegebenen Fehlerkorrekturstufe darstellt. 
* Diese Funktion kodiert immer im Binärsegmentmodus, nicht im Textmodus. Die maximale Anzahl von
 * Zulässige Bytes sind 2953. Für die Ausgabe wird automatisch die kleinstmögliche QR-Code-Version ausgewählt.
 * Der ECC-Level des Ergebnisses kann höher sein als das ecl-Argument, wenn dies ohne Erhöhung der Version möglich ist.
 * @param data die zu kodierenden Binärdaten (nicht {@code null})
 * @param ecl die zu verwendende Fehlerkorrekturstufe (nicht {@code null}) (boostbar)
 * @return einen QR-Code (nicht {@code null}), der die Daten darstellt
 * @throws NullPointerException, wenn die Daten- oder Fehlerkorrekturstufe {@code null} ist
 * @throws DataTooLongException, wenn die Daten nicht in die passen
 * Größte Version des QR-Codes am ECL, was bedeutet, dass er zu lang ist
 */
 öffentlicher statischer QrCode encodeBinary(byte[] data, Ecc ecl) {
 Objects.requireNonNull(data); 
Objects.requireNonNull(ecl);
 QrSegment seg = QrSegment.makeBytes(data);
 return encodeSegments(Arrays.asList(seg), ecl);
 }


 /*---- Statische Werksfunktionen (mittlere Ebene) ----*/

 /** * Gibt einen QR-Code zurück, der die angegebenen Segmente mit der angegebenen Fehlerkorrekturstufe * darstellt. Für die Ausgabe wird automatisch die kleinstmögliche QR-Code-Version gewählt. Der ECC-Level * des Ergebnisses kann höher sein als das ecl-Argument, wenn dies ohne Erhöhung der Version möglich ist. * <p>Mit dieser Funktion kann der Benutzer eine benutzerdefinierte Sequenz von Segmenten erstellen, die * zwischen Modi (z. B. alphanumerisch und byteweise) wechselt, um Text auf weniger Platz zu kodieren. * Dies ist eine API mittlerer Ebene. Die High-Level-API ist {@link #encodeText(String,Ecc)} * und {@link #encodeBinary(byte[],Ecc)}.</p> * @param segmentiert die zu kodierenden Segmente 
* @param ecl die zu verwendende Fehlerkorrekturstufe (nicht {@code null}) (boostbar)
 * @return einen QR-Code (nicht {@code null}), der die Segmente darstellt
 * @throws NullPointerException, wenn die Liste der Segmente, ein beliebiges Segment oder die Fehlerkorrekturstufe {@code null} ist
 * @throws DataTooLongException, wenn die Segmente nicht in die passen
 * Größte Version des QR-Codes beim ECL, was bedeutet, dass sie zu lang sind
 */
 public static QrCode encodeSegments(List<QrSegment> segs, Ecc ecl) {
 return encodeSegments(segs, ecl, MIN_VERSION, MAX_VERSION, -1, true );
 }


 /** * Gibt einen QR-Code zurück, der die angegebenen Segmente mit den angegebenen Kodierungsparametern darstellt. 
* Die kleinstmögliche QR-Code-Version innerhalb des angegebenen Bereichs wird automatisch verwendet
 * für die Ausgabe ausgewählt. Wenn boostEcl {@code true} ist, dann ist der ECC-Level des
 * Das Ergebnis kann höher sein als das ecl-Argument, wenn es ohne Erhöhung durchgeführt werden kann
 * die Version. Um dies zu erzwingen, liegt die Maskennummer entweder zwischen 0 und 7 (einschließlich).
 * Maske oder −1, um automatisch eine geeignete Maske auszuwählen (was langsam sein kann).
 * <p>Mit dieser Funktion kann der Benutzer eine benutzerdefinierte Sequenz von Segmenten erstellen, die wechseln
 * zwischen Modi (z. B. alphanumerisch und Byte), um Text auf weniger Platz zu kodieren.
 * Dies ist eine API mittlerer Ebene. Die High-Level-API ist {@link #encodeText(String,Ecc)}
 * und {@link #encodeBinary(byte[],Ecc)}.</p>
 * @param trennt die zu kodierenden Segmente
 * @param ecl die zu verwendende Fehlerkorrekturstufe (nicht {@code null}) (boostbar)
 * @param minVersion die minimal zulässige Version des QR-Codes (mindestens 1)
 * @param maxVersion die maximal zulässige Version des QR-Codes (höchstens 40) 
* @param mask die zu verwendende Maskennummer (zwischen 0 und 7 (einschließlich)) oder −1 für die automatische Maske
 * @param boostEcl erhöht den ECC-Level, solange dadurch die Versionsnummer nicht erhöht wird
 * @return einen QR-Code (nicht {@code null}), der die Segmente darstellt
 * @throws NullPointerException, wenn die Liste der Segmente, ein beliebiges Segment oder die Fehlerkorrekturstufe {@code null} ist
 * @throws IllegalArgumentException, wenn 1 ≤ minVersion ≤ maxVersion ≤ 40
 * oder −1 ≤ Maske ≤ 7 wird verletzt
 * @throws DataTooLongException, wenn die Segmente nicht hineinpassen
 * der maxVersion-QR-Code am ECL, was bedeutet, dass sie zu lang sind
 */ 
public static QrCode encodeSegments(List<QrSegment> segs, Ecc ecl, int minVersion, int maxVersion, int mask, boolean boostEcl) {
 Objects.requireNonNull(segs);
 Objects.requireNonNull(ecl);
 if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
 throw new IllegalArgumentException( "Ungültiger Wert" );
 
// Finden Sie die minimale Versionsnummer, die verwendet werden soll int version, dataUsedBits;
 for (version = minVersion; ; version++) {
 int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Anzahl der verfügbaren Datenbits dataUsedBits = QrSegment.getTotalBits(segs, version);
 if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
 Pause ; // Diese Versionsnummer wurde als geeignet befunden 
if (version >= maxVersion) { // Alle Versionen im Bereich konnten nicht in die angegebenen Daten passen String msg = "Segment too long" ;
 if (dataUsedBits != -1)
 msg = String.format( "Datenlänge = %d Bits, maximale Kapazität = %d Bits" , dataUsedBits, dataCapacityBits);
 throw new DataTooLongException(msg);
 }
 }
 behaupten dataUsedBits != -1;

 // Erhöhen Sie die Fehlerkorrekturstufe, solange die Daten noch in die aktuelle Versionsnummer passen 
for (Ecc newEcl : Ecc.values()) { // Von niedrig nach hoch if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
 ecl = newEcl;
 }

 // Alle Segmente verketten, um die Datenbitzeichenfolge zu erstellen BitBuffer bb = new BitBuffer();
 for (QrSegment seg : segs) {
 bb.appendBits(seg.mode.modeBits, 4);
 bb.appendBits(seg.numChars, seg.mode.numCharCountBits(version));
 bb.appendBits(seg.data, seg.bitLength);
 } 
behaupten bb.bitLength == dataUsedBits;

 // Abschlusszeichen hinzufügen und gegebenenfalls auf ein Byte auffüllen int dataCapacityBits = getNumDataCodewords(version, ecl) * 8;
 behaupten bb.bitLength <= dataCapacityBits;
 bb.appendBits(0, Math.min(4, dataCapacityBits - bb.bitLength));
 bb.appendBits(0, (8 - bb.bitLength % 8) % 8);
 behaupten bb.bitLength % 8 == 0;

 // Mit abwechselnden Bytes auffüllen, bis die Datenkapazität erreicht ist für ( int padByte = 0xEC; bb.bitLength < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
 bb.appendBits(padByte, 8);

 // Erstelle das QR-Code-Objekt 
return new QrCode(version, ecl, bb.getBytes(), mask);
 }



 /*---- Instanzfelder ----*/

 // Öffentliche unveränderliche Skalarparameter:
 /** Die Versionsnummer dieses QR-Codes, die zwischen 1 und 40 (einschließlich) liegt. * Dies bestimmt die Größe dieses Barcodes. */
 öffentliche endgültige int- Version;

 /** Die Breite und Höhe dieses QR-Codes, gemessen in Modulen, zwischen * 21 und 177 (einschließlich). Dies entspricht Version × 4 + 17. */ 
öffentliche endgültige int- Größe;

 /** Die in diesem QR-Code verwendete Fehlerkorrekturstufe, die nicht {@code null} ist. */
 public final Ecc errorCorrectionLevel;

 /** Der Index des in diesem QR-Code verwendeten Maskenmusters, der zwischen 0 und 7 (einschließlich) liegt. * <p>Auch wenn ein QR-Code mit angeforderter automatischer Maskierung erstellt wird (Maske = * −1), hat das resultierende Objekt immer noch einen Maskenwert zwischen 0 und 7. */
 öffentliche finale int- Maske;

 // Privates Raster aus Modulen dieses QR-Codes, dicht in Stücke gepackt. 
// Unveränderlich nach Abschluss des Konstruktors. Zugriff über getModule(). private final int[] Module;



 /*---- Konstruktor (niedriges Level) ----*/

 /** * Erstellt einen QR-Code mit der angegebenen Versionsnummer, * Fehlerkorrekturstufe, Datencodewortbytes und Maskennummer. * <p>Dies ist eine Low-Level-API, die die meisten Benutzer nicht direkt verwenden sollten. Eine mittlere * API ist die Funktion {@link #encodeSegments(List,Ecc,int,int,int,boolean)}.</p> * @param gibt die zu verwendende Versionsnummer an, die im Bereich 1 liegen muss bis 40 (einschließlich) * @param ecl die zu verwendende Fehlerkorrekturstufe * @param dataCodewords die Bytes, die zu kodierende Segmente darstellen (ohne ECC) * @param msk das zu verwendende Maskenmuster, das entweder −1 für die automatische Auswahl oder von 0 ist bis 7 für feste Auswahl 
* @throws NullPointerException, wenn das Byte-Array oder die Fehlerkorrekturstufe {@code null} ist
 * @throws IllegalArgumentException, wenn der Versions- oder Maskenwert außerhalb des Bereichs liegt,
 * oder wenn die Daten die falsche Länge für die angegebene Version und Fehlerkorrekturstufe haben
 */
 public QrCode( int ver, Ecc ecl, byte[] dataCodewords, int msk) {
 // Argumente prüfen und Felder initialisieren, wenn (ver < MIN_VERSION || ver > MAX_VERSION)
 throw new IllegalArgumentException( „Versionswert außerhalb des gültigen Bereichs“ ); 
if (msk < -1 || msk > 7)
 throw new IllegalArgumentException( „Maskierungswert außerhalb des Bereichs“ );
 version = ver;
 Größe = Version * 4 + 17;
 errorCorrectionLevel = Objects.requireNonNull(ecl);
 Objects.requireNonNull(dataCodewords);

 QrTemplate tpl = QrTemplate.MEMOIZER.get(ver);
 module = tpl.template.clone();

 // ECC berechnen, Module zeichnen, maskieren byte[] allCodewords = addEccAndInterleave(dataCodewords);
 drawCodewords(tpl.dataOutputBitIndexes, allCodewords);
 mask = handleConstructorMasking(tpl.masks, msk);
 }



 /*---- Öffentliche Instanzmethoden ----*/

 /** * Gibt die Farbe des Moduls (Pixel) an den angegebenen Koordinaten zurück, also {@code false} 
* für hell oder {@code true} für dunkel. Die obere linke Ecke enthält die Koordinaten (x=0, y=0).
 * Wenn die angegebenen Koordinaten außerhalb der Grenzen liegen, wird {@code false} (hell) zurückgegeben.
 * @param x die x-Koordinate, wobei 0 die linke Kante und size−1 die rechte Kante ist
 * @param y die y-Koordinate, wobei 0 die Oberkante und size−1 die Unterkante ist
 * @return {@code true}, wenn die Koordinaten innerhalb der Grenzen liegen und das Modul
 * an dieser Stelle ist dunkel, andernfalls {@code false} (hell).
 */
 public boolean getModule( int x, int y) {
 if (0 <= x && x < Größe && 0 <= y && y < Größe) { 
int i = y * Größe + x;
 return getBit(modules[i >>> 5], i) != 0;
 } sonst
 return false ;
 }



 /*---- Private Hilfsmethoden für Konstruktor: Funktionsmodule zeichnen ----*/

 // Zeichnet zwei Kopien der Formatbits (mit eigenem Fehlerkorrekturcode) // basierend auf der angegebenen Maske und dem Fehlerkorrekturstufenfeld dieses Objekts. 
private void drawFormatBits( int msk) {
 // Fehlerkorrekturcode berechnen und Bits packen int data = errorCorrectionLevel.formatBits << 3 | msk; // errCorrLvl ist uint2, Maske ist uint3 int rem = data;
 for ( int i = 0; i < 10; i++)
 rem = (rem << 1) ^ ((rem >>> 9) * 0x537);
 int bits = (data << 10 | rem) ^ 0x5412; // uint15 
Assert- Bits >>> 15 == 0;

 // Erste Kopie zeichnen für ( int i = 0; i <= 5; i++)
 setModule(8, i, getBit(bits, i));
 setModule(8, 7, getBit(bits, 6));
 setModule(8, 8, getBit(bits, 7));
 setModule(7, 8, getBit(bits, 8));
 for ( int i = 9; i < 15; i++)
 setModule(14 - i, 8, getBit(bits, i));

 // Zweite Kopie zeichnen für ( int i = 0; i < 8; i++)
 setModule(size - 1 - i, 8, getBit(bits, i));
 for ( int i = 8; i < 15; i++) 
setModule(8, size - 15 + i, getBit(bits, i));
 setModule(8, size - 8, 1); // Immer dunkel }


 // Setzt das Modul an den angegebenen Koordinaten auf die angegebene Farbe. // Wird nur vom Konstruktor verwendet. Die Koordinaten müssen innerhalb der Grenzen liegen. private void setModule( int x, int y, int dark) {
 behaupten 0 <= x && x < size;
 behaupten 0 <= y && y < size;
 behaupte dunkel == 0 || dunkel == 1; 
int i = y * Größe + x;
 module[i >>> 5] &= ~(1 << i);
 module[i >>> 5] |= dunkel << i;
 }


 /*---- Private Hilfsmethoden für Konstruktor: Codewörter und Maskierung ----*/

 // Gibt eine neue Bytezeichenfolge zurück, die die angegebenen Daten mit den entsprechenden angehängten Fehlerkorrekturcodewörtern // basierend auf der Version und der Fehlerkorrekturstufe dieses Objekts darstellt. private byte[] addEccAndInterleave(byte[] data) {
 Objects.requireNonNull(data);
 if (data.length != getNumDataCodewords(version, errorCorrectionLevel)) 
throw new IllegalArgumentException();

 // Parameternummern berechnen int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.ordinal()][version];
 int blockEccLen = ECC_CODEWORDS_PER_BLOCK [errorCorrectionLevel.ordinal()][version];
 int rawCodewords = QrTemplate.getNumRawDataModules(version) / 8;
 int numShortBlocks = numBlocks - rawCodewords % numBlocks;
 int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen;

 // Teilen Sie Daten in Blöcke auf, berechnen Sie ECC und verschachteln Sie // (nicht verketten) Sie die Bytes in einer einzigen Sequenz 
byte[] result = new byte[rawCodewords];
 ReedSolomonGenerator rs = ReedSolomonGenerator.MEMOIZER.get(blockEccLen);
 byte[] ecc = neues byte[blockEccLen]; // Temporäre Speicherung pro Iteration für ( int i = 0, k = 0; i < numBlocks; i++) {
 int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1);
 rs.getRemainder(data, k, datLen, ecc);
 for ( int j = 0, l = i; j < datLen; j++, k++, l += numBlocks) { // Daten kopieren 
if (j == shortBlockDataLen)
 l -= numShortBlocks;
 Ergebnis[l] = Daten[k];
 }
 for ( int j = 0, l = data.length + i; j < blockEccLen; j++, l += numBlocks) // ECC kopieren result[l] = ecc[j];
 }
 Ergebnis zurückgeben ;
 }


 // Zeichnet die angegebene Folge von 8-Bit-Codewörtern (Daten- und Fehlerkorrektur) // auf den gesamten Datenbereich dieses QR-Codes, basierend auf den angegebenen Bitindizes. 
private void drawCodewords(int[] dataOutputBitIndexes, byte[] allCodewords) {
 Objects.requireNonNull(dataOutputBitIndexes);
 Objects.requireNonNull(allCodewords);
 if (allCodewords.length * 8 != dataOutputBitIndexes.length)
 throw new IllegalArgumentException();
 for ( int i = 0; i < dataOutputBitIndexes.length; i++) {
 int j = dataOutputBitIndexes[i];
 int bit = getBit(allCodewords[i >>> 3], ~i & 7); 
module[j >>> 5] |= bit << j;
 }
 }


 // XORs der Codewortmodule in diesem QR-Code mit dem angegebenen Maskenmuster. // Vor dem Maskieren müssen die Funktionsbausteine ​​markiert und die Codewortbits gezeichnet // werden. Aufgrund der Arithmetik von XOR wird ein zweiter Aufruf von applyMask() mit // demselben Maskenwert die Maske rückgängig machen. Auf einen endgültigen wohlgeformten // QR-Code muss genau eine (nicht null, zwei usw.) Maske angewendet werden. private void applyMask(int[] msk) {
 if (msk.length != module.length) 
throw new IllegalArgumentException();
 for ( int i = 0; i < msk.length; i++)
 module[i] ^= msk[i];
 }


 // Eine chaotische Hilfsfunktion für den Konstruktor. Dieser QR-Code muss sich in einem unmaskierten Zustand befinden, wenn diese // Methode aufgerufen wird. Das Argument „Maske“ ist die angeforderte Maske, die -1 für „Auto“ oder 0 bis 7 für „Fest“ ist. // Diese Methode wendet die tatsächlich ausgewählte Maske an und gibt sie zurück, von 0 bis 7. 
private int handleConstructorMasking(int[][] masks, int msk) {
 if (msk == -1) { // Automatische Auswahl der besten Maske int minPenalty = Integer.MAX_VALUE;
 for ( int i = 0; i < 8; i++) {
 applyMask(masks[i]);
 drawFormatBits(i);
 int Penalty = getPenaltyScore(); 
if (Strafe < minStrafe) {
 msk = i;
 minPenalty = Strafe;
 }
 applyMask(masks[i]); // Macht die Maske aufgrund von XOR rückgängig }
 }
 behaupten 0 <= msk && msk <= 7;
 applyMask(masks[msk]); // Die endgültige Auswahl der Maske anwenden drawFormatBits(msk); // Alte Formatbits überschreiben return msk; // Der Aufrufer soll diesen Wert dem endgültig deklarierten Feld zuweisen }

 
// Berechnet den Strafwert basierend auf dem Status der aktuellen Module dieses QR-Codes und gibt ihn zurück. // Dies wird vom Algorithmus zur automatischen Maskenauswahl verwendet, um das Maskenmuster zu finden, das die niedrigste Punktzahl ergibt. private int getPenaltyScore() {
 int Ergebnis = 0;
 int dunkel = 0;
 int[] runHistory = new int[7];

 // Iteriere über benachbarte Zeilenpaare für ( int index = 0, downIndex = size, end = size * size; index < end; ) { 
int runColor = 0;
 int runX = 0;
 Arrays.fill(runHistory, 0);
 int curRow = 0;
 int nextRow = 0;
 for ( int x = 0; x < size; x++, index++, downIndex++) {
 int c = getBit(modules[index >>> 5], index);
 if (c == runColor) {
 runX++;
 if (runX == 5)
 Ergebnis += PENALTY_N1;
 sonst wenn (runX > 5) 
Ergebnis++;
 } sonst {
 finderPenaltyAddHistory(runX, runHistory);
 if (runColor == 0)
 result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
 runColor = c;
 runX = 1;
 }
 dunkel += c;
 if (downIndex < end) {
 curRow = ((curRow << 1) | c) & 3;
 nextRow = ((nextRow << 1) | getBit(modules[downIndex >>> 5], downIndex)) & 3;
 // 2*2 Blöcke von Modulen mit derselben Farbe, wenn (x >= 1 && (curRow == 0 || curRow == 3) && curRow == nextRow)
 Ergebnis += PENALTY_N2; 
}
 }
 result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3;
 }

 // Über einzelne Spalten iterieren for ( int x = 0; x < size; x++) {
 int runColor = 0;
 int runY = 0;
 Arrays.fill(runHistory, 0);
 for ( int y = 0, index = x; y < size; y++, index += size) {
 int c = getBit(modules[index >>> 5], index); 
if (c == runColor) {
 runY++;
 if (runY == 5)
 Ergebnis += PENALTY_N1;
 sonst wenn (runY > 5)
 Ergebnis++;
 } sonst {
 finderPenaltyAddHistory(runY, runHistory);
 if (runColor == 0)
 result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3;
 runColor = c;
 runY = 1;
 }
 }
 result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3; 
}

 // Balance von dunklen und hellen Modulen int total = size * size; // Beachten Sie, dass die Größe ungerade ist, also dunkel/total != 1/2 // Berechnen Sie die kleinste ganze Zahl k >= 0, sodass (45-5k)% <= dunkel/total <= (55+5k)% int k = (Math.abs(dark * 20 - total * 10) + total - 1) / total - 1;
 Ergebnis += k * PENALTY_N4;
 Ergebnis zurückgeben ;
 }



 /*---- Private Hilfsfunktionen ----*/

 // Gibt die Anzahl der 8-Bit-Datencodewörter (d. h. keine Fehlerkorrektur) zurück, die in einem // QR-Code der angegebenen Versionsnummer und Fehlerkorrekturstufe enthalten sind, wobei die restlichen Bits verworfen werden. 
// Diese zustandslose reine Funktion könnte als Nachschlagetabelle für (40*4)-Zellen implementiert werden. static int getNumDataCodewords( int ver, Ecc ecl) {
 Rückgabe QrTemplate.getNumRawDataModules(ver) / 8
 - ECC_CODEWORDS_PER_BLOCK [ecl.ordinal()][ver]
 * NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal()][ver];
 }


 // Kann nur unmittelbar nach dem Hinzufügen eines leichten Laufs aufgerufen werden und // gibt entweder 0, 1 oder 2 zurück. Eine Hilfsfunktion für getPenaltyScore(). 
private int finderPenaltyCountPatterns(int[] runHistory) {
 int n = runHistory[1];
 behaupten n <= Größe * 3;
 boolean core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n;
 return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0)
 + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0);
 }


 // Muss am Ende einer Zeile (Zeile oder Spalte) von Modulen aufgerufen werden. Eine Hilfsfunktion für getPenaltyScore(). 
private int finderPenaltyTerminateAndCount( int currentRunColor, int currentRunLength, int[] runHistory) {
 if (currentRunColor == 1) { // Dark Run Finder beenden . PenaltyAddHistory(currentRunLength, runHistory);
 currentRunLength = 0;
 }
 currentRunLength += Größe; // Hellen Rand zum endgültigen Lauf hinzufügen finderPenaltyAddHistory(currentRunLength, runHistory);
 return finderPenaltyCountPatterns(runHistory);
 }

 
// Schiebt den angegebenen Wert nach vorne und lässt den letzten Wert fallen. Eine Hilfsfunktion für getPenaltyScore(). private void finderPenaltyAddHistory( int currentRunLength, int[] runHistory) {
 if (runHistory[0] == 0)
 currentRunLength += Größe; // Hellen Rand zum ersten Lauf hinzufügen System.arraycopy(runHistory, 0, runHistory, 1, runHistory.length - 1);
 runHistory[0] = currentRunLength;
 }


 // Gibt 0 oder 1 basierend auf dem (i mod 32)-ten Bit von x zurück. 
static int getBit( int x, int i) {
 return (x >>> i) & 1;
 }


 /*---- Konstanten und Tabellen ----*/

 /** Die minimale Versionsnummer (1), die im QR-Code-Modell-2-Standard unterstützt wird. */
 öffentliches statisches final int MIN_VERSION = 1;

 /** Die maximale Versionsnummer (40), die im QR Code Model 2-Standard unterstützt wird. */ 
öffentliches statisches final int MAX_VERSION = 40;


 // Zur Verwendung in getPenaltyScore(), wenn ermittelt wird, welche Maske die beste ist. privates statisches final int PENALTY_N1 = 3;
 privates statisches final int PENALTY_N2 = 3; 
privates statisches final int PENALTY_N3 = 40;
 privates statisches final int PENALTY_N4 = 10;


 privates statisches letztes Byte[][] ECC_CODEWORDS_PER_BLOCK = {
 // Version: (Beachten Sie, dass Index 0 zum Auffüllen dient und auf einen unzulässigen Wert gesetzt ist) 
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Fehlerkorrekturstufe { -1, 7, 10, 15, 20, 26 , 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 } , // Niedrig { -1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28 } , // Mittel 
{ -1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 } , // Quartil { -1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 } , // Hoch } ;

 privates statisches letztes Byte[][] NUM_ERROR_CORRECTION_BLOCKS = { 
// Version: (Beachten Sie, dass Index 0 zum Auffüllen dient und auf einen unzulässigen Wert gesetzt ist) //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13 , 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38 , 39, 40 Fehlerkorrekturstufe { -1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8 , 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25 } , // Niedrig { -1, 1 , 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23 , 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49 } , // Mittel 
{ -1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68 } , // Quartil { -1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81 } , // Hoch } ;



 /*---- Öffentliche Helferaufzählung ----*/

 /** * Die Fehlerkorrekturstufe in einem QR-Code-Symbol. */ 
öffentliche Enumeration Ecc {
 // Muss in aufsteigender Reihenfolge des Fehlerschutzes deklariert werden , // damit die impliziten ordinal()- und value()-Werte ordnungsgemäß funktionieren. /** Der QR-Code kann etwa 7 % fehlerhafte Codewörter tolerieren. */ NIEDRIG(1),
 /** Der QR-Code kann etwa 15 % fehlerhafte Codewörter tolerieren. */ MITTEL(0),
 /** Der QR-Code kann etwa 25 % fehlerhafte Codewörter tolerieren. */ QUARTIL(3),
 /** Der QR-Code kann etwa 30 % fehlerhafte Codewörter tolerieren. */ HIGH(2);

 // Im Bereich 0 bis 3 (vorzeichenlose 2-Bit-Ganzzahl). final int formatBits;
 
// Konstrukteur. private Ecc( int fb) {
 formatBits = fb;
 }
 }

 }

 /* * Schnelle QR-Code-Generator-Demo * * Führen Sie dieses Befehlszeilenprogramm ohne Argumente aus. Das Programm erstellt/überschreibt eine Reihe * PNG- und SVG-Dateien im aktuellen Arbeitsverzeichnis, um die Erstellung von QR-Codes zu demonstrieren. * * Copyright (c) Projekt Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * * Hiermit wird jeder Person kostenlos die Erlaubnis erteilt, eine Kopie * dieser Software und der zugehörigen Dokumentation zu erhalten Dateien (die „Software“), ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte daran 
* Kopien davon verwenden, kopieren, ändern, zusammenführen, veröffentlichen, verteilen, unterlizenzieren und/oder verkaufen
 * die Software und um Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten,
 *vorbehaltlich der folgenden Bedingungen:
 * - Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk müssen darin enthalten sein
 * alle Kopien oder wesentlichen Teile der Software.
 * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt:
 * aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;

 import java.awt.image.BufferedImage; 
java.io.File importieren ;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 java.util.Arrays importieren ;
 java.util.List importieren ;
 java.util.Objects importieren ;
 import javax.imageio.ImageIO;


 öffentliche Abschlussklasse QrCodeGeneratorDemo {

 // Das Hauptanwendungsprogramm. 
public static void main(String[] args) löst eine IOException {
 doBasicDemo();
 doVarietyDemo();
 doSegmentDemo();
 doMaskDemo();
 }



 /*---- Demo-Suite ----*/

 // Erstellt einen einzelnen QR-Code und schreibt ihn dann in eine PNG-Datei und eine SVG-Datei. private static void doBasicDemo() wirft IOException { 
String text = „Hallo Welt!“ ; // Vom Benutzer bereitgestellter Unicode-Text QrCode.Ecc errCorLvl = QrCode.Ecc.LOW; // Fehlerkorrekturstufe
 QrCode qr = QrCode.encodeText(text, errCorLvl); // Erstelle das QR-Code-Symbol
 BufferedImage img = toImage(qr, 10, 4); // In Bitmap-Bilddatei konvertieren imgFile = new File( "hello-world-QR.png" ); // Dateipfad für die Ausgabe ImageIO.write(img, "png" , imgFile); // Bild in Datei schreiben
 String svg = toSvgString(qr, 4, "#FFFFFF" , "#000000" ); // In SVG-XML-Code konvertieren 
Datei svgFile = new File( "hello-world-QR.svg" ); // Dateipfad für die Ausgabe Files.write(svgFile.toPath(), // Bild in Datei schreiben svg.getBytes(StandardCharsets.UTF_8));
 }


 // Erstellt eine Vielzahl von QR-Codes, die verschiedene Funktionen der Bibliothek nutzen, und schreibt jeden einzelnen in eine Datei. private static void doVarietyDemo() löst eine IOException { aus
 QrCode qr;

 // Numerische Moduskodierung (3,33 Bit pro Ziffer) 
qr = QrCode.encodeText( "314159265358979323846264338327950288419716939937510" , QrCode.Ecc.MEDIUM);
 writePng(toImage(qr, 13, 1), "pi-digits-QR.png" );

 // Kodierung im alphanumerischen Modus (5,5 Bit pro Zeichen) qr = QrCode.encodeText( "DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/" , QrCode.Ecc.HIGH);
 writePng(toImage(qr, 10, 2), "alphanumeric-QR.png" );

 // Unicode-Text als UTF-8 qr = QrCode.encodeText( "こんにちwa、世界! αβγδ" , QrCode.Ecc.QUARTILE);
 writePng(toImage(qr, 10, 3), "unicode-QR.png" );

 // Mäßig großer QR-Code mit längerem Text (aus Lewis Carrolls Alice im Wunderland) qr = QrCode.encodeText( 
„Alice hatte es langsam satt, neben ihrer Schwester am Ufer zu sitzen“,
 + „Und dass sie nichts zu tun hatte: Ein- oder zweimal hatte sie in das Buch geguckt, in dem ihre Schwester las.“
 + „aber es waren keine Bilder oder Gespräche drin, ‚und was nützt ein Buch‘, dachte Alice“
 + „‘Ohne Bilder oder Gespräche?’ Also überlegte sie in Gedanken (so gut sie konnte): „
 + „denn der heiße Tag machte sie sehr schläfrig und dumm), ob das Vergnügen, ein „
 + „Daisy Chain wäre die Mühe wert, aufzustehen und die Gänseblümchen zu pflücken, wenn plötzlich“
 + „Ein weißes Kaninchen mit rosa Augen rannte dicht an ihr vorbei.“ , QrCode.Ecc.HIGH);
 writePng(toImage(qr, 6, 10), "alice-wonderland-QR.png" ); 
}


 // Erstellt QR-Codes mit manuell angegebenen Segmenten für eine bessere Kompaktheit. private static void doSegmentDemo() löst eine IOException { aus
 QrCode qr;
 List<QrSegment> segs;

 // Illustration „silver“ String silver0 = „DIE QUADRATWURZEL VON 2 IST 1.“ ;
 String silver1 = "41421356237309504880168872420969807856967187537694807317667973799" ;
 qr = QrCode.encodeText(silver0 + silver1, QrCode.Ecc.LOW);
 writePng(toImage(qr, 10, 3), "sqrt2-monolithic-QR.png" );

 segs = Arrays.asList(
 QrSegment.makeAlphanumeric(silver0), 
QrSegment.makeNumeric(silver1));
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW);
 writePng(toImage(qr, 10, 3), "sqrt2-segmented-QR.png" );

 // Illustration „golden“ String golden0 = „Goldener Schnitt φ = 1.“ ;
 String golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374" ;
 String golden2 = "......" ;
 qr = QrCode.encodeText(golden0 + golden1 + golden2, QrCode.Ecc.LOW);
 writePng(toImage(qr, 8, 5), "phi-monolithic-QR.png" );

 segs = Arrays.asList(
 QrSegment.makeBytes(golden0.getBytes(StandardCharsets.UTF_8)),
 QrSegment.makeNumeric(golden1),
 QrSegment.makeAlphanumeric(golden2));
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW);
 writePng(toImage(qr, 8, 5), "phi-segmented-QR.png" );
 
// Illustration „Madoka“: Kanji, Kana, Kyrillisch, lateinische Zeichen in voller Breite, griechische Zeichen String madoka = „「魔法少女まどか☆マギカ」って、 ИАИ desu κα?“ ;
 qr = QrCode.encodeText(madoka, QrCode.Ecc.LOW);
 writePng(toImage(qr, 9, 4, 0xFFFFE0, 0x303080), "madoka-utf8-QR.png" );

 segs = Arrays.asList(QrSegmentAdvanced.makeKanji(madoka));
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.LOW);
 writePng(toImage(qr, 9, 4, 0xE0F0FF, 0x404040), "madoka-kanji-QR.png" );
 }


 // Erstellt QR-Codes mit derselben Größe und demselben Inhalt, aber unterschiedlichen Maskenmustern. 
private static void doMaskDemo() löst eine IOException { aus
 QrCode qr;
 List<QrSegment> segs;

 // Projekt-Nayuki-URL segs = QrSegment.makeSegments( "https://www.nayuki.io/" );
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, -1, true ); // Automatische Maske writePng(toImage(qr, 8, 6, 0xE0FFE0, 0x206020), "project-nayuki-automask-QR.png" ); 
qr = QrCode.encodeSegments(segs, QrCode.Ecc.HIGH, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 3, true ); // Maske 3 erzwingen writePng(toImage(qr, 8, 6, 0xFFE0E0, 0x602020), "project-nayuki-mask3-QR.png" );

 // Chinesischer Text als UTF-8 segs = QrSegment.makeSegments ( "維基百科(Wikipedia,聆聽i/ˌwɪkᵻˈpiːdi.ə/)是一個自由內容、公開編輯且多語言的網路百科全書協作計畫");
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 0, true ); // Maske 0 erzwingen writePng(toImage(qr, 10, 3), "unicode-mask0-QR.png" ); 
qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 1, true ); // Maske 1 erzwingen writePng(toImage(qr, 10, 3), "unicode-mask1-QR.png" );
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 5, true ); // Maske 5 erzwingen writePng(toImage(qr, 10, 3), "unicode-mask5-QR.png" );
 qr = QrCode.encodeSegments(segs, QrCode.Ecc.MEDIUM, QrCode.MIN_VERSION, QrCode.MAX_VERSION, 7, true ); // Maske 7 erzwingen writePng(toImage(qr, 10, 3), "unicode-mask7-QR.png" );
 }



 /*---- Dienstprogramme ----*/
 
privates statisches BufferedImage toImage(QrCode qr, int scale, int border) {
 return toImage(qr, scale, border, 0xFFFFFF, 0x000000);
 }


 /** * Gibt ein Rasterbild zurück, das den angegebenen QR-Code * mit dem angegebenen Modulmaßstab, den angegebenen Randmodulen und den angegebenen Modulfarben darstellt. * <p>Zum Beispiel bedeutet „scale=10“ und „border=4“, dass der QR-Code mit 4 hellen Randmodulen * auf allen vier Seiten aufgefüllt wird und 10×10 Pixel zur Darstellung jedes Moduls verwendet werden. * @param qr der zu rendernde QR-Code (nicht {@code null}) * @param skaliert die Seitenlänge (gemessen in Pixel, muss positiv sein) jedes Moduls 
* @param border gibt die Anzahl der hinzuzufügenden Grenzmodule an, die nicht negativ sein darf
 * @param lightColor die für Lichtmodule zu verwendende Farbe im 0xRRGGBB-Format
 * @param darkColor die für dunkle Module zu verwendende Farbe im 0xRRGGBB-Format
 * @return ein neues Bild, das den QR-Code darstellt, mit Auffüllung und Skalierung
 * @throws NullPointerException, wenn der QR-Code {@code null} ist
 * @throws IllegalArgumentException, wenn der Maßstab oder der Rand außerhalb des Bereichs liegt oder wenn
 * {scale, border, size} führt dazu, dass die Bildabmessungen Integer.MAX_VALUE überschreiten
 */
 privates statisches BufferedImage toImage(QrCode qr, int scale, int border, int lightColor, int darkColor) { 
Objects.requireNonNull(qr);
 if (scale <= 0 || border < 0)
 throw new IllegalArgumentException( „Wert außerhalb des Bereichs“ );
 if (border > Integer.MAX_VALUE / 2 || qr.size + border * 2L > Integer.MAX_VALUE / scale)
 throw new IllegalArgumentException( „Maßstab oder Rahmen zu groß“ );

 BufferedImage result = new BufferedImage((qr.size + border * 2) * scale, (qr.size + border * 2) * scale, BufferedImage.TYPE_INT_RGB); 
for ( int y = 0; y < result.getHeight(); y++) {
 for ( int x = 0; x < result.getWidth(); x++) {
 boolesche Farbe = qr.getModule(x / Skala – Grenze, y / Skala – Grenze);
 result.setRGB(x, y, color ? darkColor : lightColor);
 }
 }
 Ergebnis zurückgeben ;
 }


 // Hilfsfunktion zur Reduzierung der Codeduplizierung. 
private static void writePng(BufferedImage img, String filepath) löst eine IOException {
 ImageIO.write(img, "png" , new File(filepath));
 }


 /** * Gibt eine Zeichenfolge mit SVG-Code für ein Bild zurück, das den angegebenen QR-Code mit der angegebenen * Anzahl von Randmodulen darstellt. Die Zeichenfolge verwendet unabhängig von der Plattform immer Unix-Zeilenumbrüche (\n). * @param qr der zu rendernde QR-Code (nicht {@code null}) * @param border die Anzahl der hinzuzufügenden Randmodule, die nicht negativ sein darf * @param lightColor die Farbe, die für Lichtmodule in jedem Format verwendet werden soll wird von CSS unterstützt, nicht von {@code null} 
* @param darkColor die Farbe, die für dunkle Module verwendet werden soll, in jedem von CSS unterstützten Format, nicht {@code null}
 * @return eine Zeichenfolge, die den QR-Code als SVG-XML-Dokument darstellt
 * @throws NullPointerException, wenn ein Objekt {@code null} ist
 * @throws IllegalArgumentException, wenn der Rand negativ ist
 */
 privater statischer String toSvgString(QrCode qr, int border, String lightColor, String darkColor) {
 Objects.requireNonNull(qr);
 Objects.requireNonNull(lightColor);
 Objects.requireNonNull(darkColor);
 if (Grenze < 0)
 throw new IllegalArgumentException( „Grenze darf nicht negativ sein“ ); 
long brd = Grenze;
 StringBuilder sb = new StringBuilder()
 .append( "<?xml version=\"1.0\"kodierung=\"UTF-8\"?>\n" )
 .append( "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" >\n" )
 .append(String.format( "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 %1$d %1$d \" Stroke=\"none\">\n" ,
 qr.size + brd * 2))
 .append( "\t<rect width=\"100%\" height=\"100%\" fill=\"" + lightColor + "\"/>\n" )
 .append( "\t<path d=\"" ); 
for ( int y = 0; y < qr.size; y++) {
 for ( int x = 0; x < qr.size; x++) {
 if (qr.getModule(x, y)) {
 if (x != 0 || y != 0)
 sb.append( " " );
 sb.append(String.format( "M%d,%dh1v1h-1z" , x + brd, y + brd));
 }
 }
 }
 jdn. zurückgeben 
.append( "\" fill=\"" + darkColor + "\"/>\n" )
 .append( "</svg>\n" )
 .toString();
 }

 }

 /* * Schnelle QR-Code-Generatorbibliothek * * Copyright (c) Project Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * * Hiermit wird jeder Person kostenlos die Erlaubnis erteilt, eine Kopie * dieser Software und der zugehörigen Dokumentation zu erhalten Dateien (die „Software“), ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, Ändern, Zusammenführen, Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen von Kopien der Software und zu Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten, * unter den folgenden Bedingungen: * - Der obige Urheberrechtshinweis und dieser Genehmigungshinweis müssen enthalten sein 
* alle Kopien oder wesentlichen Teile der Software.
 * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt:
 * aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;

 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 java.util.Arrays importieren ;
 java.util.List importieren ; 
java.util.Objects importieren ;


 /** * Ein Segment von Zeichen-/Binär-/Steuerdaten in einem QR-Code-Symbol. * Instanzen dieser Klasse sind unveränderlich. * <p>Die mittlere Möglichkeit, ein Segment zu erstellen, besteht darin, die Nutzdaten zu nehmen und eine * statische Factory-Funktion wie {@link QrSegment#makeNumeric(String)} aufzurufen. Die einfache * Möglichkeit, ein Segment zu erstellen, besteht darin, den Bitpuffer individuell zu erstellen und den {@link * QrSegment#QrSegment(Mode,int,int[],int)-Konstruktor} mit den entsprechenden Werten aufzurufen.</p> * <p>Diese Segmentklasse unterliegt keinen Längenbeschränkungen, für QR-Codes gelten jedoch Beschränkungen. * Selbst unter den günstigsten Bedingungen kann ein QR-Code nur 7089 Zeichen an Daten enthalten. * Längere Segmente sind für die Generierung von QR-Codes bedeutungslos. * Diese Klasse kann Kanji-Modus-Segmente darstellen, bietet aber keine Hilfe bei der Codierung * – vollständige Kanji-Unterstützung finden Sie unter {@link QrSegmentAdvanced}.</p> */ 
öffentliche Abschlussklasse QrSegment {

 /*---- Statische Werksfunktionen (mittlere Ebene) ----*/

 /** * Gibt ein Segment zurück, das die angegebenen Binärdaten * im Bytemodus codiert darstellt. Alle Eingabebyte-Arrays sind akzeptabel. * <p>Jede Textzeichenfolge kann in UTF-8-Bytes ({@code * s.getBytes(StandardCharsets.UTF_8)}) konvertiert und als Byte-Modus-Segment codiert werden.</p> * @param data die Binärdaten ( nicht {@code null}) * @gibt ein Segment zurück (nicht {@code null}), das die Daten enthält * @throws NullPointerException, wenn das Array {@code null} ist */ 
öffentliches statisches QrSegment makeBytes(byte[] data) {
 Objects.requireNonNull(data);
 if (data.length * 8L > Integer.MAX_VALUE)
 throw new IllegalArgumentException( „Daten zu lang“ );
 int[] bits = new int[(data.length + 3) / 4];
 for ( int i = 0; i < data.length; i++)
 bits[i >>> 2] |= (data[i] & 0xFF) << (~i << 3); 
return new QrSegment(Mode.BYTE, data.length, bits, data.length * 8);
 }


 /** * Gibt ein Segment zurück, das die angegebene Folge von Dezimalziffern darstellt, die im numerischen Modus codiert sind. * @param nummeriert den Text (nicht {@code null}), wobei nur Ziffern von 0 bis 9 zulässig sind * @return ein Segment (nicht {@code null}), das den Text enthält * @throws NullPointerException, wenn die Zeichenfolge {@code null} * @throws IllegalArgumentException, wenn die Zeichenfolge nicht-stellige Zeichen enthält */
 öffentliches statisches QrSegment makeNumeric(String Ziffern) {
 Objects.requireNonNull(digits);
 BitBuffer bb = new BitBuffer(); 
int accumData = 0;
 int accumCount = 0;
 for ( int i = 0; i < digits.length(); i++) {
 char c = digits.charAt(i);
 if (c < '0' || c > '9' )
 throw new IllegalArgumentException( „String enthält nicht numerische Zeichen“ );
 accumData = accumData * 10 + (c - '0' );
 accumCount++; 
if (accumCount == 3) {
 bb.appendBits(accumData, 10);
 accumData = 0;
 accumCount = 0;
 }
 }
 if (accumCount > 0) // 1 oder 2 Ziffern übrig bb.appendBits(accumData, accumCount * 3 + 1);
 return new QrSegment(Mode.NUMERIC, digits.length(), bb.data, bb.bitLength);
 }


 /** * Gibt ein Segment zurück, das die angegebene Textzeichenfolge darstellt, die im alphanumerischen Modus codiert ist. * Zulässige Zeichen sind: 0 bis 9, A bis Z (nur Großbuchstaben), Leerzeichen, * Dollar, Prozent, Sternchen, Pluszeichen, Bindestrich, Punkt, Schrägstrich, Doppelpunkt. 
* @param text der Text (nicht {@code null}), wobei nur bestimmte Zeichen zulässig sind
 * @return ein Segment (nicht {@code null}), das den Text enthält
 * @throws NullPointerException, wenn die Zeichenfolge {@code null} ist
 * @throws IllegalArgumentException, wenn die Zeichenfolge nicht kodierbare Zeichen enthält
 */
 öffentliches statisches QrSegment makeAlphanumeric(String text) {
 Objects.requireNonNull(text);
 BitBuffer bb = new BitBuffer();
 int accumData = 0;
 int accumCount = 0;
 for ( int i = 0; i < text.length(); i++) { 
char c = text.charAt(i);
 if (c >= ALPHANUMERIC_MAP.length || ALPHANUMERIC_MAP[c] == -1)
 throw new IllegalArgumentException( „String enthält nicht kodierbare Zeichen im alphanumerischen Modus“ );
 accumData = accumData * 45 + ALPHANUMERIC_MAP[c];
 accumCount++;
 if (accumCount == 2) {
 bb.appendBits(accumData, 11);
 accumData = 0;
 accumCount = 0;
 }
 }
 if (accumCount > 0) // 1 Zeichen übrig bb.appendBits(accumData, 6); 
return new QrSegment(Mode.ALPHANUMERIC, text.length(), bb.data, bb.bitLength);
 }


 /** * Gibt eine Liste von null oder mehr Segmenten zurück, um die angegebene Unicode-Textzeichenfolge darzustellen. * Das Ergebnis kann verschiedene Segmentmodi und Switch-Modi verwenden, um die Länge des Bitstroms zu optimieren. * @param text der zu kodierende Text, der eine beliebige Unicode-Zeichenfolge sein kann * @return eine neue veränderbare Liste (nicht {@code null}) von Segmenten (nicht {@code null}), die den Text enthalten * @throws NullPointerException if the Text ist {@code null} */
 öffentliche statische Liste<QrSegment> makeSegments(String text) {
 Objects.requireNonNull(text);
 
// Die effizienteste Segmentkodierung automatisch auswählen List<QrSegment> result = new ArrayList<>();
 if (text.equals( "" )); // Ergebnis leer lassen else if (isNumeric(text))
 result.add(makeNumeric(text));
 else if (isAlphanumeric(text))
 result.add(makeAlphanumeric(text));
 anders
 result.add(makeBytes(text.getBytes(StandardCharsets.UTF_8)));
 Ergebnis zurückgeben ;
 }


 /** 
* Gibt ein Segment zurück, das eine erweiterte Kanalinterpretation darstellt
 * (ECI)-Bezeichner mit dem angegebenen Zuordnungswert.
 * @param askVal die ECI-Zuweisungsnummer (siehe AIM ECI-Spezifikation)
 * @return ein Segment (nicht {@code null}), das die Daten enthält
 * @throws IllegalArgumentException, wenn der Wert außerhalb des Bereichs [0, 10<sup>6</sup>) liegt.
 */
 öffentliches statisches QrSegment makeEci( int askVal) {
 BitBuffer bb = new BitBuffer();
 if (assignVal < 0)
 throw new IllegalArgumentException( „ECI-Zuweisungswert außerhalb des Bereichs“ ); 
sonst wenn (assignVal < (1 << 7))
 bb.appendBits(assignVal, 8);
 sonst if (assignVal < (1 << 14)) {
 bb.appendBits(2, 2);
 bb.appendBits(assignVal, 14);
 } else if (assignVal < 1_000_000) {
 bb.appendBits(6, 3);
 bb.appendBits(assignVal, 21);
 } sonst 
throw new IllegalArgumentException( „ECI-Zuweisungswert außerhalb des Bereichs“ );
 return new QrSegment(Mode.ECI, 0, bb.data, bb.bitLength);
 }


 /** * Testet, ob die angegebene Zeichenfolge im numerischen Modus als Segment codiert werden kann. * Eine Zeichenfolge ist kodierbar, wenn jedes Zeichen im Bereich von 0 bis 9 liegt. * @param text die Zeichenfolge, die auf Kodierbarkeit getestet werden soll (nicht {@code null}) * @return {@code true}, wenn jedes Zeichen im Bereich von 0 liegt bis 9. * @throws NullPointerException, wenn die Zeichenfolge {@code null} ist * @see #makeNumeric(String) */ 
öffentlicher statischer boolescher Wert isNumeric(String text) {
 for ( int i = 0; i < text.length(); i++) {
 char c = text.charAt(i);
 if (c < '0' || c > '9' )
 return false ;
 }
 return true ; 
}


 /** * Testet, ob die angegebene Zeichenfolge im alphanumerischen Modus als Segment codiert werden kann. * Eine Zeichenfolge ist kodierbar, wenn jedes Zeichen im folgenden Satz enthalten ist: 0 bis 9, A bis Z * (nur Großbuchstaben), Leerzeichen, Dollar, Prozent, Sternchen, Pluszeichen, Bindestrich, Punkt, Schrägstrich, Doppelpunkt. * @param text die Zeichenfolge, die auf Kodierbarkeit getestet werden soll (nicht {@code null}) * @return {@code true}, wenn jedes Zeichen im alphanumerischen Modus-Zeichensatz ist * @throws NullPointerException, wenn die Zeichenfolge {@code null} ist * @see #makeAlphanumeric(String) */
 public static boolean isAlphanumeric(String text) { 
for ( int i = 0; i < text.length(); i++) {
 char c = text.charAt(i);
 if (c >= ALPHANUMERIC_MAP.length || ALPHANUMERIC_MAP[c] == -1)
 return false ;
 }
 return true ;
 }



 /*---- Instanzfelder ----*/

 /** Der Modusindikator dieses Segments. Nicht {@code null}. */ 
öffentlicher Endmodusmodus ;

 /** Die Länge der uncodierten Daten dieses Segments. Gemessen in Zeichen für den numerischen/alphanumerischen/Kanji-Modus *, Bytes für den Byte-Modus und 0 für den ECI-Modus. * Immer Null oder positiv. Entspricht nicht der Bitlänge der Daten. */
 public final int numChars;

 // Die Datenbits dieses Segments. Nicht null. final int[] data;

 // Erfordert 0 <= bitLength <= data.length * 32. final int bitLength;


 /*---- Konstruktor (niedriges Level) ----*/
 
/** * Konstruiert ein QR-Code-Segment mit den angegebenen Attributen und Daten. * Die Zeichenanzahl (numCh) muss mit dem Modus und der Bitpufferlänge übereinstimmen, * die Einschränkung wird jedoch nicht überprüft. Der angegebene Bitpuffer wird geklont und gespeichert. * @param md der Modus (nicht {@code null}) * @param numCh die Datenlänge in Zeichen oder Bytes, die nicht negativ ist * @param data die Datenbits (nicht {@code null}) * @param bitLen die Anzahl der gültigen Präfixbits im Datenarray * @throws NullPointerException, wenn der Modus oder die Daten {@code null} sind * @throws IllegalArgumentException, wenn die Zeichenanzahl negativ ist */
 public QrSegment(Mode md, int numCh, int[] data, int bitLen) {
 mode = Objects.requireNonNull(md);
 this.data = Objects.requireNonNull(data); 
if (numCh < 0 || bitLen < 0 || bitLen > data.length * 32L)
 throw new IllegalArgumentException( "Ungültiger Wert" );
 numChars = numCh;
 bitLength = bitLen;
 }


 // Berechnet die Anzahl der Bits, die zum Codieren der angegebenen Segmente in der angegebenen Version erforderlich sind. // Gibt bei Erfolg eine nicht negative Zahl zurück. Andernfalls wird -1 zurückgegeben, wenn ein Segment // zu viele Zeichen hat, um in sein Längenfeld zu passen, oder wenn die Gesamtzahl der Bits Integer.MAX_VALUE überschreitet. 
static int getTotalBits(List<QrSegment> segs, int version) {
 Objects.requireNonNull(segs);
 langes Ergebnis = 0;
 for (QrSegment seg : segs) {
 Objects.requireNonNull(seg);
 int ccbits = seg.mode.numCharCountBits(version);
 if (seg.numChars >= (1 << ccbits))
 return -1; // Die Länge des Segments passt nicht zur Bitbreite des Felds result += 4L + ccbits + seg.bitLength; 
if (Ergebnis > Integer.MAX_VALUE)
 return -1; // Die Summe wird einen int-Typ überlaufen lassen }
 return ( int )result;
 }


 /*---- Konstanten ----*/

 static final int[] ALPHANUMERIC_MAP;

 statisch {
 final String ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" ; 
int maxCh = -1;
 for ( int i = 0; i < ALPHANUMERIC_CHARSET.length(); i++)
 maxCh = Math.max(ALPHANUMERIC_CHARSET.charAt(i), maxCh);
 ALPHANUMERIC_MAP = new int[maxCh + 1];
 Arrays.fill(ALPHANUMERIC_MAP, -1);
 for ( int i = 0; i < ALPHANUMERIC_CHARSET.length(); i++)
 ALPHANUMERIC_MAP[ALPHANUMERIC_CHARSET.charAt(i)] = i;
 }



 /*---- Öffentliche Helferaufzählung ----*/

 /** * Beschreibt, wie die Datenbits eines Segments interpretiert werden. */ 
öffentlicher Enumerationsmodus {

 /*-- Konstanten --*/

 NUMERISCH (0x1, 10, 12, 14),
 ALPHANUMERISCH(0x2, 9, 11, 13),
 BYTE (0x4, 8, 16, 16),
 KANJI (0x8, 8, 10, 12),
 ECI (0x7, 0, 0, 0);


 /*-- Felder --*/

 // Die Modusanzeigebits, die ein uint4-Wert sind (Bereich 0 bis 15). final int modeBits;

 // Anzahl der Zeichenzählbits für drei verschiedene Versionsbereiche. private final int[] numBitsCharCount;


 /*-- Konstrukteur --*/
 
privater Modus( int mode, int... ccbits) {
 modeBits = Modus;
 numBitsCharCount = ccbits;
 }


 /*-- Methode --*/

 // Gibt die Bitbreite des Zeichenzählfelds für ein Segment in diesem Modus // in einem QR-Code mit der angegebenen Versionsnummer zurück. Das Ergebnis liegt im Bereich [0, 16]. int numCharCountBits( int ver) {
 behaupten QrCode.MIN_VERSION <= ver && ver <= QrCode.MAX_VERSION;
 return numBitsCharCount[(ver + 7) / 17]; 
}

 }

 }

 /* * Schnelle QR-Code-Generatorbibliothek * * Copyright (c) Project Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * * Hiermit wird jeder Person kostenlos die Erlaubnis erteilt, eine Kopie * dieser Software und der zugehörigen Dokumentation zu erhalten Dateien (die „Software“), ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, Ändern, Zusammenführen, Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen von Kopien der Software und zu Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten, * unter den folgenden Bedingungen: * - Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk müssen in * allen Kopien oder wesentlichen Teilen der Software enthalten sein. * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art 
* stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt:
 * aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;

 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 java.util.Arrays importieren ;
 java.util.Base64 importieren ;
 java.util.List importieren ;
 java.util.Objects importieren ; 
import io.nayuki.fastqrcodegen.QrSegment.Mode;


 /** * Teilt Text in optimale Segmente auf und kodiert Kanji-Segmente. * Bietet nur statische Funktionen; nicht instanziierbar. * @see QrSegment * @see QrCode */
 öffentliche Abschlussklasse QrSegmentAdvanced {

 /*---- Optimale Liste der Segmente Encoder ----*/

 /** * Gibt eine Liste von null oder mehr Segmenten zurück, um die angegebene Unicode-Textzeichenfolge darzustellen. * Die resultierende Liste minimiert optimal die gesamte codierte Bitlänge, vorbehaltlich der Einschränkungen * in der angegebenen {Fehlerkorrekturstufe, minimale Versionsnummer, maximale Versionsnummer}. 
* <p>Diese Funktion kann alle vier Textkodierungsmodi nutzen: numerisch, alphanumerisch, Byte (UTF-8),
 * und Kanji. Dies kann als ausgefeilter, aber langsamerer Ersatz für {@link
 * QrSegment#makeSegments(String)}. Dies erfordert mehr Eingabeparameter, da nach a gesucht wird
 * Versionsbereich, wie {@link QrCode#encodeSegments(List,QrCode.Ecc,int,int,int,boolean)}.</p>
 * @param text der zu kodierende Text (nicht {@code null}), der eine beliebige Unicode-Zeichenfolge sein kann
 * @param ecl die zu verwendende Fehlerkorrekturstufe (nicht {@code null})
 * @param minVersion die minimal zulässige Version des QR-Codes (mindestens 1)
 * @param maxVersion die maximal zulässige Version des QR-Codes (höchstens 40)
 * @return eine neue veränderbare Liste (nicht {@code null}) von Segmenten (nicht {@code null})
 * enthält den Text und minimiert die Bitlänge im Hinblick auf die Einschränkungen
 * @throws NullPointerException, wenn die Text- oder Fehlerkorrekturstufe {@code null} ist 
* @throws IllegalArgumentException, wenn 1 ≤ minVersion ≤ maxVersion ≤ 40 verletzt wird
 * @throws DataTooLongException, wenn der Text nicht in den maxVersion-QR-Code am ECL passt
 */
 public static List<QrSegment> makeSegmentsOptimally(String text, QrCode.Ecc ecl, int minVersion, int maxVersion) {
 // Argumente prüfen Objects.requireNonNull(text);
 Objects.requireNonNull(ecl);
 if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION)) 
throw new IllegalArgumentException( "Ungültiger Wert" );

 // Versionsnummern durchlaufen und vorläufige Segmente erstellen List<QrSegment> segs = null ;
 int[] codePoints = toCodePoints(text);
 for ( int version = minVersion; ; version++) {
 if (Version == minVersion || Version == 10 || Version == 27)
 segs = makeSegmentsOptimally(codePoints, version);
 behaupten Segs != null ;

 // Prüfen, ob die Segmente passen 
int dataCapacityBits = QrCode.getNumDataCodewords(version, ecl) * 8; // Anzahl der verfügbaren Datenbits int dataUsedBits = QrSegment.getTotalBits(segs, version);
 if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
 Rückgabesegmente ; // Diese Versionsnummer wird als geeignet befunden, wenn (version >= maxVersion) { // Alle Versionen im Bereich konnten nicht in den angegebenen Text passen String msg = "Segment too long" ;
 if (dataUsedBits != -1) 
msg = String.format( "Datenlänge = %d Bits, maximale Kapazität = %d Bits" , dataUsedBits, dataCapacityBits);
 throw new DataTooLongException(msg);
 }
 }
 }


 // Gibt eine neue Liste von Segmenten zurück, die für den angegebenen Text mit der angegebenen Versionsnummer optimal sind. private static List<QrSegment> makeSegmentsOptimally(int[] codePoints, int version) {
 if (codePoints.length == 0) 
return new ArrayList<>();
 Mode[] charModes = computeCharacterModes(codePoints, version);
 return splitIntoSegments(codePoints, charModes);
 }


 // Gibt ein neues Array zurück, das den optimalen Modus pro Codepunkt basierend auf dem angegebenen Text und der angegebenen Version darstellt. private static Mode[] computeCharacterModes(int[] codePoints, int version) {
 if (codePoints.length == 0)
 throw new IllegalArgumentException(); 
final Mode[] modeTypes = { Mode.BYTE, Mode.ALPHANUMERIC, Mode.NUMERIC, Mode.KANJI } ; // Nicht ändern final int numModes = modeTypes.length;

 // Segment-Header-Größen, gemessen in 1/6 Bit final int[] headCosts = new int[numModes];
 for ( int i = 0; i < numModes; i++)
 headCosts[i] = (4 + modeTypes[i].numCharCountBits(version)) * 6;

 // charModes[i][j] stellt den Modus dar, in dem der Codepunkt codiert werden soll 
// i so indizieren, dass das letzte Segment in modeTypes[j] endet und die // Gesamtzahl der Bits über alle möglichen Auswahlmöglichkeiten hinweg minimiert wird Mode[][] charModes = new Mode[codePoints.length][numModes];

 // Zu Beginn jeder Iteration der folgenden Schleife // ist prevCosts[j] die genaue Mindestanzahl von 1/6 Bits, die zum // Codieren des gesamten String-Präfixes der Länge i erforderlich ist, und endet in modeTypes[j] int [] prevCosts = headCosts.clone();

 // Kosten mithilfe dynamischer Programmierung berechnen für ( int i = 0; i < codePoints.length; i++) { 
int c = codePoints[i];
 int[] curCosts = new int[numModes];
 { // Erweitern Sie immer ein Byte-Modus-Segment curCosts[0] = prevCosts[0] + countUtf8Bytes(c) * 8 * 6;
 charModes[i][0] = modeTypes[0];
 }
 // Ein Segment erweitern, wenn möglich if (QrSegment.ALPHANUMERIC_MAP[c] != -1) { // Ist alphanumerisch curCosts[1] = prevCosts[1] + 33; // 5,5 Bits pro alphanumerischem Zeichen charModes[i][1] = modeTypes[1];
 } 
if ( '0' <= c && c <= '9' ) { // Ist numerisch curCosts[2] = prevCosts[2] + 20; // 3,33 Bit pro Ziffer charModes[i][2] = modeTypes[2];
 }
 if (isKanji(c)) {
 curCosts[3] = prevCosts[3] + 78; // 13 Bit pro Shift JIS char charModes[i][3] = modeTypes[3];
 }

 // Neues Segment am Ende beginnen, um den Modus zu wechseln 
for ( int j = 0; j < numModes; j++) { // Zum Modus for ( int k = 0; k < numModes; k++) { // Vom Modus int newCost = (curCosts[k] + 5) / 6 * 6 + headCosts[j];
 if (charModes[i][k] != null && (charModes[i][j] == null || newCost < curCosts[j])) {
 curCosts[j] = newCost;
 charModes[i][j] = modeTypes[k]; 
}
 }
 }

 prevCosts = curCosts;
 }

 // Optimalen Endmodus finden Mode curMode = null ;
 for ( int i = 0, minCost = 0; i < numModes; i++) {
 if (curMode == null || prevCosts[i] < minCost) {
 minCost = prevCosts[i];
 curMode = modeTypes[i];
 }
 }
 
// Den optimalen Modus für jeden Codepunkt erhalten, indem man ihn rückwärts verfolgt. Mode[] result = new Mode[charModes.length];
 for ( int i = result.length - 1; i >= 0; i--) {
 for ( int j = 0; j < numModes; j++) {
 if (modeTypes[j] == curMode) {
 curMode = charModes[i][j];
 result[i] = curMode;
 Pause ;
 }
 } 
}
 Ergebnis zurückgeben ;
 }


 // Gibt eine neue Liste von Segmenten basierend auf dem angegebenen Text und den angegebenen Modi zurück, sodass // aufeinanderfolgende Codepunkte im gleichen Modus in das gleiche Segment eingefügt werden. private static List<QrSegment> splitIntoSegments(int[] codePoints, Mode[] charModes) {
 if (codePoints.length == 0)
 throw new IllegalArgumentException();
 List<QrSegment> result = new ArrayList<>();
 
// Lauf der Modi akkumulieren Mode curMode = charModes[0];
 int start = 0;
 for ( int i = 1; ; i++) {
 if (i < codePoints.length && charModes[i] == curMode)
 weiter ;
 String s = new String(codePoints, start, i - start);
 if (curMode == Mode.BYTE)
 result.add(QrSegment.makeBytes(s.getBytes(StandardCharsets.UTF_8)));
 sonst wenn (curMode == Mode.NUMERIC)
 result.add(QrSegment.makeNumeric(s)); 
sonst wenn (curMode == Mode.ALPHANUMERIC)
 result.add(QrSegment.makeAlphanumeric(s));
 sonst wenn (curMode == Mode.KANJI)
 result.add(makeKanji(s));
 anders
 throw new AssertionError();
 if (i >= codePoints.length)
 Ergebnis zurückgeben ;
 curMode = charModes[i];
 start = i;
 }
 }


 // Gibt ein neues Array von Unicode-Codepunkten zurück (effektiv 
// UTF-32 / UCS-4), der die angegebene UTF-16-Zeichenfolge darstellt. private static int[] toCodePoints(String s) {
 int[] result = s.codePoints().toArray();
 for ( int c : Ergebnis) {
 if (Character.isSurrogate(( char )c))
 throw new IllegalArgumentException( „Ungültige UTF-16-Zeichenfolge“ );
 }
 Ergebnis zurückgeben ; 
}


 // Gibt die Anzahl der UTF-8-Bytes zurück, die zum Codieren des angegebenen Unicode-Codepunkts erforderlich sind. private static int countUtf8Bytes( int cp) {
 if (cp < 0) throw new IllegalArgumentException( "Ungültiger Codepunkt" );
 sonst wenn (cp < 0x80) 1 zurückgeben ; 
sonst wenn (cp < 0x800) 2 zurückgeben ;
 sonst wenn (cp < 0x10000) 3 zurückgeben ;
 sonst wenn (cp < 0x110000) 4 zurückgeben ;
 else throw new IllegalArgumentException( "Ungültiger Codepunkt" );
 }



 /*---- Segment-Encoder im Kanji-Modus ----*/
 
/** * Gibt ein Segment zurück, das die angegebene Textzeichenfolge darstellt, die im Kanji-Modus codiert ist. * Im Großen und Ganzen handelt es sich bei den kodierbaren Zeichen um {in Japan verwendete Kanji, * Hiragana, Katakana, ostasiatische Interpunktion, ASCII in voller Breite, Griechisch, Kyrillisch}. * Beispiele für nicht kodierbare Zeichen sind {normales ASCII, Katakana halber Breite, * umfangreicheres chinesisches Hanzi}. * @param text den Text (nicht {@code null}), wobei nur bestimmte Zeichen zulässig sind * @return ein Segment (nicht {@code null}), das den Text enthält * @throws NullPointerException, wenn die Zeichenfolge {@code null} ist * @throws IllegalArgumentException, wenn die Zeichenfolge nicht kodierbare Zeichen enthält * @see #isEncodableAsKanji(String) */
 öffentliches statisches QrSegment makeKanji(String text) {
 Objects.requireNonNull(text); 
BitBuffer bb = new BitBuffer();
 text.chars().forEachOrdered(c -> {
 int val = UNICODE_TO_QR_KANJI[c];
 if (Wert == -1)
 throw new IllegalArgumentException( „String enthält Nicht-Kanji-Zeichen“ );
 bb.appendBits(val, 13);
 } );
 return new QrSegment(Mode.KANJI, text.length(), bb.data, bb.bitLength);
 }


 /** * Testet, ob die angegebene Zeichenfolge im Kanji-Modus als Segment codiert werden kann. 
* Im Großen und Ganzen handelt es sich bei den kodierbaren Zeichen um {Kanji, die in Japan verwendet werden,
 * Hiragana, Katakana, ostasiatische Zeichensetzung, ASCII in voller Breite, Griechisch, Kyrillisch}.
 * Beispiele für nicht kodierbare Zeichen sind {normales ASCII, Katakana halber Breite,
 * umfangreicheres chinesisches Hanzi}.
 * @param sendet einen Text an die Zeichenfolge, die auf Kodierbarkeit getestet werden soll (nicht {@code null})
 * @return {@code true}, wenn jedes Zeichen im Kanji-Modus-Zeichensatz enthalten ist
 * @throws NullPointerException, wenn die Zeichenfolge {@code null} ist
 * @see #makeKanji(String)
 */
 öffentlicher statischer boolescher Wert isEncodableAsKanji(String text) {
 Objects.requireNonNull(text);
 return text.chars().allMatch(
 c -> isKanji(( char )c)); 
}


 privater statischer boolescher Wert isKanji( int c) {
 return c < UNICODE_TO_QR_KANJI.length && UNICODE_TO_QR_KANJI[c] != -1;
 }


 // Daten abgeleitet von ftp://ftp.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/SHIFTJIS.TXT private static final String PACKED_QR_KANJI_TO_UNICODE = 
"MAAwATAC/wz/DjD7/xr/G/8f/wEwmzCcALT/QACo/z7/4/8/MP0w/jCdMJ4wA07dMAUwBjAHMPwgFSAQ/w8AXDAcIBb/XCAmICUgGCAZIBwgHf8I/wkwFDAV/zv/Pf9b/10wCDAJMAowCzAMMA0w DjAPMBAwEf8LIhIAsQDX//8A9/8dImD/HP8eImYiZyIeIjQmQiZA" +
 "ALAgMiAzIQP/5f8EAKIAo/8F/wP/Bv8K/yAApyYGJgUlyyXPJc4lxyXGJaEloCWzJbIlvSW8IDswEiGSIZAhkSGTMBP///////////////////////////IggiCyKGIocigiKDIioiKf// ////// ////////////8iJyIoAKwh0iHUIgAiA///////////////////" +
 "//////////8iICKlIxIiAiIHImEiUiJqImsiGiI9Ih0iNSIrIiz/////////////////yErIDAmbyZtJmogICAhALb//////////yXv//////// ///////////////////////////////////////xD/Ef8S/xP/FP8V/xb /F/8Y/xn///////////////////8h" +
 "/yL/I/8k/yX/Jv8n/yj/Kf8q/yv/LP8t/y7/L/8w/zH/Mv8z/zT/Nf82/zf/OP85/zr/////////// ////////9B/0L/Q/9E/0X/Rv9H/0j/Sf9K/0v/TP9N/07/T/9Q/1H/Uv9T/1T/Vf9W/1f/WP9Z/1r/// ///////zBBMEIwQzBEMEUwRjBHMEgwSTBKMEswTDBN" + 
„ME4wTzBQMFEwUjBTMFQwVTBWMFcwWDBZMFowWzBcMF0wXjBfMGAwYTBiMGMwZDBlMGYwZzBoMGkwajBrMGwwbTBuMG8wcDBxMHIwczB0MHUwdjB3MHgweTB6MHswfDB9MH4wfzCAMIEwgjCDMIQwhTCGMICwiDCJMIowizCMMI 0wjjCPMJAwkTCSMJP//////////////" +
 "//////////////////////////////MKEwojCjMKQwpTCmMKcwqDCpMKowqzCsMK0wrjCvMLAwsTCyMLMwtDC1MLYwtzC4MLkwujC7MLwwvTC+ML8wwDDBMMIwwzDEMMUwxjDHMMgwyTDKMMswzDDNMM4w zzDQMNEw0jDTMNQw1TDWMNcw2DDZMNow2zDcMN0w3jDf//8w4DDh" +
 "MOIw4zDkMOUw5jDnMOgw6TDqMOsw7DDtMO4w7zDwMPEw8jDzMPQw9TD2////////////////////wORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDowOkA6UDpgOnA6gDqf ///////////////////8DsQOyA7MDtAO1A7YDtwO4A7kDugO7A7wDvQO+" +
 "A78DwAPBA8MDxAPFA8YDxwPIA8n////////////////////////////////////////////// /////////////////////////////////////////////// ///////////BBAEEQQSBBMEFAQVBAEEFgQXBBgEGQQaBBsEHAQdBB4EHwQgBCEEigQjBCQEJQQm" + 
"BCcEKAQpBCoEKwQsBC0ELgQv////////////////////////////////////BDAEMQQyBDMENAQ1BFEENgQ3BDgEOQQ6BDsEPAQ9//8EPgQ/BEAEQQRCBEMERARFBEYERwRIBEkESgRLBEwETQROBE // ///////////////////////////////yUAJQIlDCUQ" +
 "JRglFCUcJSwlJCU0JTwlASUDJQ8lEyUbJRclIyUzJSslOyVLJSAllyUoJTclPyUdJTAlJSU4JUL//////////////////////////////////////////// /////////////////////////////////////////////// ////////////////////////////" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" + 
"///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" + 
"///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "//////////////////////////////////06cVRZaA5Y/VMBhG2MoWfaQIoR1gxx6UGCqY+FuJWXthGaCppv1aJNXJ2WhYnFbm1nQhnuY9H1ifb6bjmIWfJ+It1uJXrVjCWa XaEiVx5eNZ09O5U8KT01PnVBJVvJZN1nUWgFcCWDfYQ9hcGYTaQVwunVPdXB5+32t" + 
"fe+Aw4QOiGOLApBVkHpTO06VTqVX34CykMF4704AWPFuopA4ejKDKIKLnC9RQVNwVL1U4VbgWftfFZjybeuA5IUt////////lmKWcJagl/tUC1PzW4dwz3+9j8KW6FNvnVx6uk4ReJOB/G4mV hhVBGsdhRqcO1nlU6ltZnTclY9WQk6RkEuW8oNPmQxT4VW2WzBfcWYg" +
 "ZvNoBGw4bPNtKXRbdsh6Tpg0gvGIW4pgku1tsnWrdsqZxWCmiwGNipWyaY5TrVGG//9XElgwWURbtF72YChjqWP0bL9vFHCOcRRxWXHVcz9+AYJ2gtGFl5BgkludG1hpZbxsWnUlUflZLlllX4Bf3 GK8ZfpqKmsna7Rzi3/BiVadLJ0OnsRcoWyWg3tRBFxLYbaBxmh2" +
 "cmFOWU/6U3hgaW4pek+X804LUxZO7k9VTz1PoU9zUqBT71YJWQ9awVu2W+F50WaHZ5xntmtMbLNwa3PCeY15vno8e4eCsYLbgwSDd4Pvg9OHZoqyVimMqI/mkE6XHoaKT8Rc6GIRcll1O4Hlgr2 G/ozAlsWZE5nVTstPGonjVt5YSljKXvtf62AqYJRgYmHQYhJi0GU5" +
 "////////m0FmZmiwbXdwcHVMdoZ9dYKlh/mVi5aOjJ1R8VK+WRZUs1uzXRZhaGmCba94jYTLiFeKcpOnmrhtbJmohtlXo2f/hs6SDlKDVodUBF7TYuFkuWg8aDhru3NyeLp6a4maidKNa48DkO 2Vo5aUl2lbZlyzaX2YTZhOY5t7IGor//9qf2i2nA1vX1JyVZ1gcGLs" + 
"bTtuB27RhFuJEI9EThScOVP2aRtqOpeEaCpRXHrDhLKR3JOMVludKGgigwWEMXylUgiCxXTmTn5Pg1GgW9JSClLYUudd+1WaWCpZ5luMW5hb215yXnlgo2EfYWNhvmPbZWJn0WhTaPprPmtTbFdvIm+Xb 0V0sHUYduN3C3r/e6F8IX3pfzZ/8ICdgmaDnomzisyMq5CE" +
 "lFGVk5WRlaKWZZfTmSiCGE44VCtcuF3Mc6l2THc8XKl/640LlsGYEZhUmFhPAU8OU3FVnFZoV/pZR1sJW8RckF4MXn5fzGPuZzpl12XiZx9oy2jE////////al9eMGvFbBdsfXV/eUhbY3oA fQBfvYmPihiMtI13jsyPHZjimg6bPE6AUH1RAFmTW5xiL2KAZOxrOnKg" +
 "dZF5R3+ph/uKvItwY6yDypegVAlUA1WraFRqWIpweCdndZ7NU3RbooEahlCQBk4YTkVOx08RU8pUOFuuXxNgJWVR//9nPWxCbHJs43B4dAN6dnquewh9Gnz+fWZl53JbU7tcRV3oYtJi4GMZbiCGWo oxjd2S+G8BeaabWk6oTqtOrE+bT6BQ0VFHevZRcVH2U1RTIVN/" +
 "U+tVrFiDXOFFfN19KYC9gUGBtYx9lWWpLbMFywnLtd++A+IEFggiFTpD3k+GX/5lXmlpO8FHdXC1mgWltXEBm8ml1c4loUHyBUMVS5FdHXf6TJmWkayNrPXQ0eYF5vXtLfcqCuYPMiH+JX4s5 j9GR0VQfkoBOXVA2U+VTOnLXc5Z36YLmjq+ZxpnImdJRd2Eahl5VsHp6" + 
"UHZb05BHloVOMmrbkedcUVxI////////Y5h6n2yTl3SPYXqqcYqWiHyCaBd+cGhRk2xS8lQbhauKE3+kjs2Q4VNmiIh5QU/CUL5SEVFEVVNXLXPqV4tZUV9iX4RgdWF2YWdhqWOyZDplbGZvaE JuE3Vmej18+31MfZl+S39rgw6DSobNigiKY4tmjv2YGp2PgriPzpvo" +
 "//9Sh2IfZINvwJaZaEFQkWsgbHpvVHp0fVCIQIojZwhO9lA5UCZQZVF8UjhSY1WnVw9YBVrMXvphsmH4YvNjcmkcailyfXKscy54FHhvfXl3DICpiYuLGYzijtKQY5N1lnqYVZoTnnhRQ1OfU7Ne e18mbhtukHOEc/59Q4I3igCK+pZQTk5QC1PkVHxW+lnRW2Rd8V6r" +
 "XydiOGVFZ69uVnLQfMqItIChgOGD8IZOioeN6JI3lseYZ58TTpROkk8NU0hUSVQ+Wi9fjF+hYJ9op2qOdFp4gYqeiqSLd5GQTl6byU6kT3xPr1AZUBZRSVFsUp9SuVL+U5pT41QR////////VA 5ViVdRV6JZfVtUW11bj13lXedd9154XoNeml63XxhgUmFMYpdi2GOn" +
 "ZTtmAmZDZvRnbWghaJdpy2xfbSptaW4vbp11MnaHeGx6P3zgfQV9GH1efbGAFYADgK+AsYFUgY+CKoNSiEyIYYsbjKKM/JDKkXWScXg/kvyVpJZN//+YBZmZmtidO1JbUqtT91QIWNVi92/g jGqPX565UUtSO1RKVv16QJF3nWCe0nNEbwmBcHURX/1g2pqoctuPvGtk" + 
"mANOylbwV2RYvlpaYGhhx2YPZgZoOWixbfd11X06gm6bQk6bT1BTyVUGXW9d5l3uZ/tsmXRzeAKKUJOWiN9XUF6nYytQtVCsUY1nAFTJWF5Zu1uwX2liTWOhaD1rc24IcH2Rx3KAeBV4JnltZY 59MIPciMGPCZabUmRXKGdQf2qMoVG0V0KWKlg6aYqAtFSyXQ5X/HiV" +
 "nfpPXFJKVItkPmYoZxRn9XqEe1Z9IpMvaFybrXs5UxlRilI3////////W99i9mSuZOZnLWu6hamW0XaQm9ZjTJMGm6t2v2ZSTglQmFPCXHFg6GSSZWNoX3Hmc8p1I3uXfoKGlYuDjNuReJ kQZaxmq2uLTtVO1E86T39SOLP4U/JV41bbWOtZy1nJWf9bUFxNXgJeK1/X" +
 "YB1jB2UvW1xlr2W9ZehnnWti//9re2wPc0V5SXnBfPh9GX0rgKKBAoHziZaKXoppimaKjIrujMeM3JbMmPxrb06LTzxPjVFQW1db+mFIYwFmQmshbstsu3I+dL111HjBeTqADIAzgeqElI+ebFCef1 8Pi1idK3r6jvhbjZbrTgNT8Vf3WTFayVukYIluf28Gdb6M6luf" +
 "hQB74FByZ/SCnVxhhUp+HoIOUZlcBGNojWZlnHFueT59F4AFix2OypBuhseQqlAfUvpcOmdTcHxyNZFMkciTK4LlW8JfMWD5TjtT1luIYktnMWuKculz4HougWuNo5FSmZZRElPXVGpb/2OIajl9rJcaV tpTzlRo////////W5dcMV3eT+5hAWL+bTJ5wHnLfUJ+TX/S" + 
"ge2CH4SQiEaJcouQjnSPL5AxkUuRbJbGkZxOwE9PUUVTQV+TYg5n1GxBbgtzY34mkc2Sg1PUWRlbv23ReV1+LnybWH5xn1H6iFOP8E/KXPtmJXeseuOCHJn/UcZfqmXsaW9riW3z//9ulm 9kdv59FF3hkHWRh5gGUeZSHWJAZpFm2W4aXrZ90n9yZviFr4X3ivhSqVPZ" +
 „WXNej1+QYFWS5JZkULdRH1LdUyBTR1PsVOhVRlUxVhdZaFm+WjxbtVwGXA9cEVwaXoReil7gX3Bif2KEYttjjGN3ZgdmDGYtZnZnfmiiah9qNWy8bYhuCW5YcTxxJnFndcd3AXhdeQF5ZXnwe uB7EXynftmAloPWhIuFSYhdiPOKH4o8ilSKc4xhjN6RpJJmk36UGJac" +
 "l5hOCk4ITh5OV1GXUnBXzlg0WMxbIl44YMVk/mdhZ1ZtRHK2dXN6Y4S4i3KRuJMgVjFX9Jj+////////Yu1pDWuWce1+VIB3gnKJ5pjfh1WPsVw7TzhP4U+1VQdaIFvdW+lfw2FOYy9l sGZLaO5pm214bfF1M3W5dx95XnnmfTOB44KvhaqJqoo6jquPm5Aykd2XB066" +
 "TsFSA1h1WOxcC3UaXD2BTooKj8WWY5dteyWKz5gIkWJW81Oo//+QF1Q5V4JeJWOobDRwindhfIt/4IhwkEKRVJMQkxiWj3RemsRdB11pZXBnoo2olttjbmdJaRmDxZgXlsCI/m+EZHpb+ E4WcCx1XWYvUcRSNlLiWdNfgWAnYhBlP2V0Zh9mdGjyaBZrY24FcnJ1H3bb" + 
"fL6AVljwiP2Jf4qgipOKy5AdkZKXUpdZZYl6DoEGlrteLWDcYhplpWYUZ5B383pNfE1+PoEKjKyNZI3hjl94qVIHYtljpWRCYpiKLXqDe8CKrJbqfXaCDIdJTtlRSFNDU2Bbo1wCXBZd3WImYkdksGgTa DRsyW1FbRdn029ccU5xfWXLen97rX3a////////fkp/qIF6" +
 "ghuCOYWmim6Mzo31kHiQd5KtkpGVg5uuUk1VhG84cTZRaHmFflWBs3zOVkxYUVyoY6pm/mb9aVpy2XWPdY55DnlWed98l30gfUSGB4o0ljuQYZ8gUOdSdVPMU+JQCVWqWO5ZT3I9W4tcZFMdYONg8 2NcY4NjP2O7//9kzWXpZvld42nNaf1vFXHlTol16Xb4epN8333P" ​​+
 "fZyAYYNJg1iEbIS8hfuIxY1wkAGQbZOXlxyaElDPWJdhjoHThTWNCJAgT8NQdFJHU3Ngb2NJZ19uLI2zkB9P11xejMplz32aU1KIllF2Y8NbWFtrXApkDWdRkFxO1lkaWSpscIpRVT5YFVmlYPBiU2f BgjVpVZZAmcSaKE9TWAZb/oAQXLFeL1+FYCBhS2I0Zv9s8G7e" +
 "gM6Bf4LUiIuMuJAAkC6Wip7bm9tO41PwWSd7LJGNmEyd+W7dcCdTU1VEW4ViWGKeYtNsom/vdCKKF5Q4b8GK/oM4UeeG+FPq////////U+lPRpBUj7BZaoExXf166o+/aNqMN3L4 nEhqPYqwTjlTWFYGV2ZixWOiZeZrTm3hbltwrXfteu97qn27gD2AxobLipWTW1bj" + 
"WMdfPmWtZpZqgGu1dTeKx1Akd+VXMF8bYGVmemxgdfR6Gn9ugfSHGJBFmbN7yXVcevl7UYTE//+QEHnpepKDNlrhd0BOLU7yW5lf4GK9Zjxn8WzohmuId4o7kU6S85nQahdwJnMqgueEV 4yvTgFRRlHLVYtb9V4WXjNegV8UXzVfa1+0YfJjEWaiZx1vbnJSdTp3OoB0" +
 "gTmBeId2ir+K3I2FjfOSmpV3mAKc5VLFY1d29GcVbIhzzYzDk66Wc20lWJxpDmnMj/2TmnXbkBpYWmgCY7Rp+09Dbyxn2I+7hSZ9tJNUaT9vcFdqWPdbLH0scipUCpHjnbROrU9OUF xQdVJDjJ5USFgkW5peHV6VXq1e918fYIxitWM6Y9Bor2xAeId5jnoLfeCCR4oC" +
 "iuaORJAT////////kLiRLZHYnw5s5WRYZOJldW70doR7G5Bpk9FuulTyX7lkpI9Nj+2SRFF4WGtZKVxVXpdt+36PdRyMvI7imFtwuU8da79vsXUwlvtRTlQQWDVYV1msXGBfkmWXZ1xuIXZ7 g9+M7ZAUkP2TTXgleDpSql6mVx9ZdGASUBJRWlGs//9RzVIAVRBYVFhY" +
 "WVdblVz2XYtgvGKVZC1ncWhDaLxo33bXbdhub22bcG9xyF9Tddh5d3tJe1R7UnzWfXFSMIRjhWmF5IoOiwSMRo4PkAOQD5QZlnaYLZOwldhQzVLVVAxYAlwOYadknm0ed7N65YD0hASQU5KFXOCdB 1M/X5dfs22ccnl3Y3m/e+Rr0nLsiq1oA2phUfh6gWk0XEqc9oLr" + 
"W8WRSXAeVnhcb2DHZWZsjIxakEGYE1RRZseSDVlIkKNRhU5NUeqFmYsOcFhjepNLaWKZtH4EdXdTV2lgjt+W42xdToxcPF8Qj+lTAozRgImGeV7/ZeVOc1Fl////////WYJcP5fuTvtZil/Nio 1v4XmweWJb54RxcytxsV50X/Vje2SaccN8mE5DXvxOS1fcVqJgqW/D" +
 "fQ2A/YEzgb+PsomXhqRd9GKKZK2Jh2d3bOJtPnQ2eDRaRn91gq2ZrE/zXsNi3WOSZVdnb3bDckyAzIC6jymRTVANV/lakmiF//9pc3Fkcv2Mt1jyjOCWapAZh3955HfnhClPL1JlU1pizWfPb Mp2fXuUfJWCNoWEj+tm3W8gcgZ+G4OrmcGeplH9e7F4cnu4gId7SGro" +
 „XmGAjHVRdWBRa5Jibox2epGXmupPEH9wYpx7T5WlnOlWelhZhuSWvE80UiRTSlPNU9teBmQsZZFnf2w+bE5ySHKvc+11VH5BgiyF6Yype8SRxnFpmBKY72M9Zml1anbkeNCFQ4buUypTUVQmWYNeh198YL JiSWJ5YqtlkGvUbMx1snaueJF52H3Lf3eApYirirmMu5B/" +
 "l16Y22oLfDhQmVw+X65nh2vYdDV3CX+O///////nztnynoXUzl1i5rtX2aBnYPxgJhfPF/FdWJ7RpA8aGdZ61qbfRB2fossT/VfamoZbDdvAnTieWiIaIpVjHle32PPdcV50oLXky iS8oSchu2cLVTBX2xljG1ccBWMp4zTmDtlT3T2Tg1O2FfgWStaZlvMUaheA16c" + 
"YBZidmV3//9lp2ZubW5yNnsmgVCBmoKZi1yMoIzmjXSWHJZET65kq2tmgh6EYYVqkOhcAWlTmKiEeoVXTw9Sb1+pXkVnDXmPgXmJB4mGbfVfF2JVbLhOz3Jpm5JSBlQ7VnRYs2GkYm 5xGllufIl83n0blvBlh4BeThlPdVF1WEBeY15zXwpnxE4mhT2ViZZbfHOYAVD7" +
 "WMF2VninUiV3pYURe4ZQT1kJckd7x33oj7qP1JBNT79SyVopXwGXrU/dgheS6lcDY1VraXUriNyPFHpCUt9Yk2FVYgpmrmvNfD+D6VAjT/hTBVRGWDFZSVudXPBc710pXpZisWNnZT5luWcL// //////bNVs4XD5eDJ+K4DegrOEDITshwKJEooqjEqQppLSmP2c851s" +
 "Tk9OoVCNUlZXSlmoXj1f2F/ZYj9mtGcbZ9Bo0lGSfSGAqoGoiwCMjIy/kn6WMlQgmCxTF1DVU1xYqGSyZzRyZ3dmekaR5lLDbKFrhlgAXkxZVGcsf/tR4XbG//9kaXjom1Seu1fLWblmJ2eaa8 5U6WnZXlWBnGeVm6pn/pxSaF1Opk/jU8hiuWcrbKuPxE+tfm2ev04H" +
 "YWJugG8rhRNUc2cqm0Vd83uVXKxbxoccbkqE0XoUgQhZmXyNbBF3IFLZWSJxIXJfd9uXJ51haQtaf1oYUaVUDVR9Zg5234/3kpic9Fnqcl1uxVFNaMl9v33sl2KeumR4aiGDAlmeEW19r23Mbd vJ9soAXhJlRMmcontl27mdiUv+ZBVwkYjt8foywVU9gtn0LlYBTAU5f" + 
"UbZZHHI6gDaRzl8ld+JThF95fQSFrIozjo2XVmfzha6UU2EJYQhsuXZS////////iu2POFUvT1FRKlLHU8tbpV59YKBhgmPWZwln2m5nbYxzNnM3dTF5UIjVipiQSpCRkPWWxIeNWRVOiE9ZT g6KiY8/mBBQrV58WZZbuV64Y9pj+mTBZtxpSmnYbQtutnGUdSh6r3+K" +
 "gACESYTJiYGLIY4KkGWWfZkKYX5ikWsy//9sg210f8x//G3Af4WHuoj4Z2WDsZg8lvdtG31hhD2Rak5xU3VdUGsEb+uFzYYtiadSKVQPXGVnTmiodAZ0g3XiiM+I4ZHMluKWeF+Lc4d6y4RO Y6B1ZVKJbUFunHQJdVl4a3ySloZ63J+NT7ZhbmXFhlxOhk6uUNpOIVHM" +
 "W+5lmWiBbbxzH3ZCd616HHzngm+K0pB8kc+WdZgYUpt90VArU5hnl23LcdB0M4HojyqWo5xXnp90YFhBbZl9L5heTuRPNk+LUbdSsV26YBxzsnk8gtOSNJa3lvaXCp6Xn2Jmpmt0UhdSo3 DIiMJeyWBLYZBvI3FJfD599IBv////////hO6QI5MsVEKbb2rTcImMwo3v" +
 "lzJStFpBXspfBGcXaXxplG1qbw9yYnL8e+2AAYB+h0uQzlFtnpN5hICLkzKK1lAtVIyKcWtqjMSBB2DRZ6Cd8k6ZTpicEIprhcGFaGkAbn54l4FV///////////////////////// ///////////////// //////////////////////////////////////////" + 
"////////////////////////////18MThBOFU4qTjFONk48Tj9OQk5WTlhOgk6FjGtOioISXw1Ojk6eTp9OoE6iTrBOs062Ts5OzU7ETsZOwk7XTt5O7U7fTvdPCU9aTzBPW09 dT1dPR092T4hPj0+YT3tPaU9wT5FPb0+GT5ZRGE/UT99Pzk/YT9tP0U/aT9BP5E/l" +
 "UBpQKFAUUCpQJVAFTxxP9lAhUClQLE/+T+9QEVAGUENQR2cDUFVQUFBIUFpQVlBsUHhQgFCaUIVQtFCy////////UMlQylCzUMJQ1lDeUOVQ7VDjUO5Q+VD1UQlRAVECURZRFVEUURpRIVE6UTdRPFE7UT9RQFFSU UxRVFFievhRaVFqUW5RgFGCVthRjFGJUY9RkVGT" +
 "UZVRllGkUaZRolGpUapRq1GzUbFRslGwUbVRvVHFUclR21HghlVR6VHt//9R8FH1Uf5SBFILUhRSDlInUipSLlIzUjlST1JEUktSTFJeUlRSalJ0UmlSc1J/Un1SjVKUUpJScVKIUpGPqI+nUqxSrVK8UrV SwVLNUtdS3lLjUuaY7VLgUvNS9VL4UvlTBlMIdThTDVMQ" +
 "Uw9TFVMaUyNTL1MxUzNTOFNAU0ZTRU4XU0lTTVHWU15TaVNuWRhTe1N3U4JTllOgU6ZTpVOuU7BTtlPDfBKW2VPfZvxx7lPuU+hT7VP6VAFUPVRAVCxULVQ8VC5UNlQpVB1UTlSPVHVUjlRfVHFUd1Rw VJJUe1SAVHZUhFSQVIZUx1SiVLhUpVSsVMRUyFSo////////" + 
"VKtUwlSkVL5UvFTYVOVU5lUPVRRU/VTuVO1U+lTiVTlVQFVjVUxVLlVcVUVVVlVXVThVM1VdVZlVgFSvVYpVn1V7VX5VmFWeVa5VfFWDValVh1WoVdpVxVXfVcRV3FXkVdRWFFX3VhZV/l X9VhtV+VZOVlBx31Y0VjZWMlY4//9Wa1ZkVi9WbFZqVoZWgFaKVqBWlFaP" +
 „VqVWrla2VrRWwla8VsFWw1bAVshWzlbRVtNW11buVvlXAFb/VwRXCVcIVwtXDVcTVxhXFlXHVxxXJlc3VzhXTlc7V0BXT1dpV8BXiFdhV39XiVeTV6BXs1ekV6pXsFfDV8ZX1FfSV9NYClfW V+NYC1gZWB1YclghWGJYS1hwa8BYULg9WHlYhVi5WJ9Yq1i6WN5Yu1i4" +
 "WK5YxVjTWNFY11jZWNhY5VjcWORY31jvWPpY+Vj7WPxY/VkCWQpZEFkbaKZZJVksWS1ZMlk4WT560llVWVBZTllaWVhZYllgWWdZbFlp////////WXhZgVmdT15Pq1mjWbJZxlnoWdxZjV nZWdpaJVofWhFaHFoJWhpaQFpsWklaNVo2WmJaalqaWrxavlrLWsJavVrj" +
 "Wtda5lrpWtZa+lr7WwxbC1sWWzJa0FsqWzZbPltDW0VbQFtRW1VbWltbW2VbaVtwW3NbdVt4ZYhbeluA//9bg1umW7hbw1vHW8lb1FvQW+Rb5lviW95b5VvrW/Bb9lvzXAVcB1w IXA1cE1wgXCJcKFw4XDlcQVxGXE5cU1xQXE9bcVxsXG5OYlx2XHlcjFyRXJRZm1yr" + 
„XLtctly8XLdcxVy + XfJd9V4LXhpeGV4RXhteNl43XkReQ15AXk5eV15UXl9eYl5kXkdedV52XnqevF5/" +
 "XqBewV7CXshe0F7P //////// X4pfiF+RX4dfnl+ZX5hfoF+oX61fvF/WX/tf5F/4X/Ff3WCzX/9gIWBg//9gGWAQ" +
 „YClgDmAxYBtgFWArYCZgD2A6YFpgQWBqYHdgX2BKYEZgTWBjYENgZGBCYGxga2BZYIFgjWDnYINgmmCEYJtglmCXYJJgp2CLYOFguGDgYNNgtF/wYL1gxmC1YNhhTWEVYQZg9mD3YQBg9GD6YQNhIWD 7YPFhDWEOYUdhPmEoYSdhSmE/YTxhLGE0YT1hQmFEYXNhd2FY" +
 "YVlhWmFrYXRhb2FlYXFhX2FdYVNhdWGZYZZhh2GsYZRhmmGKYZFhq2GuYcxhymHJYfdhyGHDYcZhumHLf3lhzWHmYeNh9mH6YfRh/2H9Yfxh/mIAYghiCWINYgxiFGIb////////Yh5iIWIq Yi5iMGIyYjNiQWJOYl5iY2JbYmBiaGJ8YoJiiWJ+YpJik2KWYtRig2KU" + 
"Ytdi0WK7Ys9i/2LGZNRiyGLcYsxiymLCYsdim2LJYwxi7mLxYydjAmMIYu9i9WNQYz5jTWQcY09jlmOOY4Bjq2N2Y6Njj2OJY59jtWNr//9jaWO+Y+ljwGPGY+NjyWPSY/ZjxGQWZDRkBmQ TZCZkNmUdZBdkKGQPZGdkb2R2ZE5lKmSVZJNkpWSpZIhkvGTaZNJkxWTH" +
 "ZLtk2GTCZPFk54IJZOBk4WKsZONk72UsZPZk9GTyZPplAGT9ZRhlHGUFZSRlI2UrZTRlNWU3ZTZlOHVLZUhlVmVVZU1lWGVeZV1lcmV4ZYJlg4uKZZtln2WrZbdlw2XGZcFlxGXMZdJl22XZZeBl 4WXxZ3JmCmYDZftnc2Y1ZjZmNGYcZk9mRGZJZkFmXmZdZmRmZ2Zo" +
 "Zl9mYmZwZoNmiGaOZolmhGaYZp1mwWa5Zslmvma8////////ZsRmuGbWZtpm4GY/ZuZm6WbwZvVm92cPZxZnHmcmZyeXOGcuZz9nNmdBZzhnN2dGZ15nYGdZZ2NnZGeJZ3BnqWd8Z 2pnjGeLZ6ZnoWeFZ7dn72e0Z+xns2fpZ7hn5GfeZ91n4mfuZ7lnzmfGZ+dqnGge" +
 "aEZoKWhAaE1oMmhO//9os2graFloY2h3aH9on2iPaK1olGidaJtog2quaLlodGi1aKBoumkPaI1ofmkBaMppCGjYaSJpJmjhaQxozWjUaOdo1Wk2aRJpBGjXaONpJWj5aOBo72koaSppGmkjaSFoxml5aX dpXGl4aWtpVGl+aW5pOWl0aT1pWWkwaWFpXmldaYFpammy" + 
"aa5p0Gm/acFp02m+ac5b6GnKad1pu2nDaadqLmmRaaBpnGmVabRp3mnoagJqG2n/awpp+WnyaedqBWmxah5p7WoUaetqCmoSasFqI2oTakRqDGpyajZqeGpHamJqWWpmakhqOGoiapBqjWqgaoRqomqj ////////apeGF2q7asNqwmq4arNqrGreatFq32qqatpq6mr7" +
 "awWGFmr6axJrFpsxax9rOGs3dtxrOZjua0drQ2tJa1BrWWtUa1trX2tha3hreWt/a4BrhGuDa41rmGuVa55rpGuqa6trr2uya7Frs2u3a7xrxmvLa9Nr32vsa+tr82vv//+evmwIbBNsFGwbbCRsI2 xebFVsYmxqbIJsjWyabIFsm2x+bGhsc2ySbJBsxGzxbNNsvWzX" +
 „bMVs3WyubLFsvmy6bNts72zzZbOptH4hNbTZtK209bThtGW01bTNtEm0MbWNtk21kbVpteW1ZbY5tlW/kbYVt+W4VbgpttW3HbeZtuG3Gbext3m3Mbeht0m3Fbfpt2W3kbdVt6m3ubi1ub m4ubhlucm5fbj5uI25rbitudm5Nbh9uQ246bk5uJG7/bh1uOG6CbqpumG7J" +
 "brdu0269bq9uxG6ybtRu1W6PbqVuwm6fb0FvEXBMbuxu+G7+bz9u8m8xbu9vMm7M////////bz5vE273b4Zvem94b4FvgG9vb1tv829tb4JvfG9Yb45vkW/Cb2Zvs2+jb6F vpG+5b8Zvqm/fb9Vv7G/Ub9hv8W/ub9twCXALb/pwEXABcA9v/nAbcBpvdHAdcBhwH3Aw" + 
"cD5wMnBRcGNwmXCScK9w8XCscLhws3CucN9wy3Dd//9w2XEJcP1xHHEZcWVxVXGIcWZxYnFMcVZxbHGPcftxhHGVcahxrHHXcblxvnHScclx1HHOceBx7HHncfVx/HH5cf9yDXIQchtyKHItcixy MHIycjtyPHI/ckByRnJLclhydHJ+coJygXKHcpJylnKicqdyuXKy" +
 "csNyxnLEcs5y0nLicuBy4XL5cvdQD3MXcwpzHHMWcx1zNHMvcylzJXM+c05zT57Yc1dzanNoc3BzeHN1c3tzenPIc7NzznO7c8Bz5XPuc950onQFdG90JXP4dDJ0OnRVdD90X3RZdEF0XHRpdHB 0Y3RqdHZ0fnSLdJ50p3TKdM901HPx////////dOB043TndOl07nTy" +
 "dPB08XT4dPd1BHUDdQV1DHUOdQ11FXUTdR51JnUsdTx1RHVNdUp1SXVbdUZ1WnVpdWR1Z3VrdW11eHV2dYZ1h3V0dYp1iXWCdZR1mnWddaV1o3XCdbN1w3W1db11uHW8dbF1zXXKd dJ12XXjdd51/nX///91/HYBdfB1+nXydfN2C3YNdgl2H3YndiB2IXYidiR2NHYw" +
 "djt2R3ZIdkZ2XHZYdmF2YnZodml2anZndmx2cHZydnZ2eHZ8doB2g3aIdot2jnaWdpN2mXaadrB2tHa4drl2unbCds121nbSdt524Xbldud26oYvdvt3CHcHdwR3KXckdx53JXcmdxt3N3 c4d0d3Wndod2t3W3dld393fnd5d453i3eRd6B3nnewd7Z3uXe/d7x3vXe7" + 
"d8d3zXfXd9p33Hfjd+53/HgMeBJ5JnggeSp4RXiOeHR4hnh8eJp4jHijeLV4qniveNF4xnjLeNR4vni8eMV4ynjs////////eOd42nj9ePR5B3kSeRF5GXkseSt5QHlgeVd5X3laeVV5U3l 6eX95inmdeaefS3mqea55s3m5ebp5yXnVeed57HnheeN6CHoNehh6GXog" +
 "eh95gHoxejt6Pno3ekN6V3pJemF6Ynppn516cHp5en16iHqXepV6mHqWeql6yHqw//96tnrFesR6v5CDesd6ynrNes961XrTetl62nrdeuF64nrmeu168HsCew97CnsGezN7GHsZex57NXsoez Z7UHt6ewR7TXsLe0x7RXt1e2V7dHtne3B7cXtse257nXuYe597jXuc" +
 "e5p7i3uSe497XXuZe8t7wXvMe897tHvGe9176XwRfBR75nvlfGB8AHwHfBN783v3fBd8DXv2fCN8J3wqfB98N3wrfD18THxDfFR8T3xAfFB8WHxffGR8VnxlfGx8dXyDfJB8pHytf KJ8q3yhfKh8s3yyfLF8rny5fL18wHzFfMJ82HzSfNx84ps7fO988nz0fPZ8+n0G" +
 "////////fQJ9HH0VfQp9RX1LfS59Mn0/fTV9Rn1zfVZ9Tn1yfWh9bn1PfWN9k32JfVt9j319fZt9un2ufaN9tX3Hfb19q349faJ9r33cfbh9n32wfdh93X3kfd59+33yfeF+ BX4KfiN+IX4SfjF+H34Jfgt+In5GfmZ+O341fjl+Q343//9+Mn46fmd+XX5Wfl5+WX5a" + 
"fnl+an5pfnx+e36DfdV+fY+ufn9+iH6Jfox+kn6QfpN+lH6Wfo5+m36cfzh/On9Ff0x/TX9Of1B/UX9Vf1R/WH9ff2B/aH9pf2d/eH+Cf4Z/g3+If4d/jH+Uf55/nX+af6N/r3+yf 7l/rn +2f7iLcX/Ff8Z/yn/Vf9R/4X/mf+l/83/5mNyaBoAEgAuAEoAYgBmAHIAh" +
 "gCiAP4A7gEqARoBSgFiAWoBfgGKAaIBzgHKAciB2gHmAfYB/gISAhoCFgJuAk4CagK1RkICsgNuA5YDZgN2AxIDagNaBCYDvgPGBG4EpgSOBL4FL////////louBRoE+gVOBUYD8gXGBboFlgWaBdigDgYiBio GAgYKBoIGVgaSBo4FfgZOBqYGwgbWBvoG4gb2BwIHC" +
 "gbqByYHNgdGB2YHYgciB2oHfgeCB54H6gfuB/oIBggKCBYIHggqCDYIQghaCKYIrgjiCM4JAglmCWIJdglqCX4Jk//+CYoJogmqCa4IugnGCd4J4gn6CjYKSgquCn4K7gqyC4YLjgt+C0oL0gvOC+oOTgw OC+4L5gt6DBoLcgwmC2YM1gzSDFoMygzGDQIM5g1CDRYMv" +
 "gyuDF4MYg4WDmoOqg5+DooOWgyODjoOHg4qDfIO1g3ODdYOgg4mDqIP0hBOD64POg/2EA4PYhAuDwYP3hAeD4IPyhA2EIoQgg72EOIUGg/uEbYQqhDyFWOSEhHeEa4SthG6EgorphEaELIRvhHmenYTKhGKE uYS/hJ+E2YTNhLuE2oTQhMGExoTWhKGFIYT/hPSFF4UY" + 
"hSyFH4UVhRSE/IVAhWOFWIVI////////hUGGAoVLhVWFgIWkhYiFkYWKhaiFbYWUhZuF6oWHhZyFd4V+hZCFyYW6hc+FuYXQhdWF3YXlhdyF+YYKhhOGC4X+hfqGBoYihhqGMIY/hk1OVYZUhl+ GZ4ZxhpOGo4aphqqGi4aMhraGr4bEhsaGsIbJiCOGq4bUht6G6Ybs" +
 "//+G34bbhu+HEocGhwiHAIcDhvuHEYcJhw2G+YcKhzSHP4c3hzuHJYcphxqHYIdfh3iHTIdOh3SHV4doh26HWYdTh2OHaogFh6KHn4eCh6+Hy4e9h8CH0JbWh6uHxIezh8eHxoe7h++H8ofgiA+ID Yf+h/aH94gOh9KIEYgWiBWIIoghiDGINog5iCeIO4hEiEKIUohZ" +
 "iF6IYohriIGIfoieiHWIfYi1iHKIgoiXiJKIroiZiKKIjYikiLCIv4ixiMOIxIjUiNiI2YjdiPmJAoj8iPSI6IjyiQSJDIkKiROJQ4keiSWJKokriUGJRIk7iTaJOIlMiR2JYIle///////iWaJZiltiWqJb4l 0iXeJfomDiYiJiomTiZiJoYmpiaaJrImvibKJuom9" +
 "ib+JwInaidyJ3YnnifSJ+IoDihaKEIoMihuKHYolijaKQYpbilKKRopiinyKbYpsimKKhYqCioSKqIqhipGKpYqmipqKo4rEis2KworaiuuK84rn//+K5IrxixSK4IriiveK3orbiwyLB4saiuGLFosQixeLIIszl6uLJosriz 6LKItBi0yLT4tOi0mLVotbi1qLa4tf" + 
„i2yLb4t0i32LgIuMi46LkouTi5aLmYuajDqMQYw/jEiMTIxOjFCMVYxijGyMeIx6jIKMiYyFjIqMjYyOjJSMfIyYYh2MrYyqjL2MsoyzjK6MtozIjMGM5IzjjNqM/Yz6jPuNBI0FjQ qNB40PjQ2NEJ9OjROMzY0UjRaNZ41tjXGNc42BjZmNwo2+jbqNz43ajdaNzI3b" +
 "jcuN6o3rjd+N4438jgiOCY3/jh2OHo4Qjh+OQo41jjCONI5K////////jkeOSY5MjlCOSI5ZjmSOYI4qjmOOVY52jnKOfI6BjoeOhY6EjouOio6TjpGOlI6ZjqqOoY6sjrCOxo6xjr6OxY7 IjsuO247jjvyO+47rjv6PCo8FjxWPEo8ZjxOPHI8fjxuPDI8mjzOPO485" +
 "j0WPQo8+j0yPSY9Gj06PV49c//+PYo9jj2SPnI+fj6OPrY+vj7eP2o/lj+KP6o/vkIeP9JAFj/mP+pARkBWQIZANkB6QFpALkCeQNpA1kDmP+JBPkFCQUZBSkA6QSZA+kFaQWJBekG iQb5B2lqiQcpCCkH2QgZCAkIqQiZCPkKiQr5CxkLWQ4pDkYkiQ25ECkRKRGZEy" +
 „kTCRSpFWkViRY5FlkWmRc5FykYuRiZGCkaKRq5GvkaqRtZG0kbqRwJHBkcmRy5HQkdaR35HhkduR/JH1kfaSHpH/khSSLJIVkhGSXpJXkkWSSZJkkkiSlZI/kkuSUJKckpaSk5KbklqSz5K5kreS6ZMPkvqTR JMu////////kxmTIpMakyOTOpM1kzuTXJNgk3yTbpNW" + 
"k7CTrJOtk5STuZPWk9eT6JPlk9iTw5Pdk9CTyJPklBqUFJQTlAOUB5QQlDaUK5Q1lCGUopRBlFKURJRblGCUYpRelGqSKZRwlHWUd5R9lFqUfJR+lIGUf5WclYeVipWUlZaVmJWZ//+VoJWolaeV rZW8lbuVuZW+lcpv9pXDlc2VzJXVldSV1pXcleGV5ZXiliGWKJYu" +
 "li+WQpZMlk+WS5Z3llyWXpZdll+WZpZylmyWjZaYlpWWl5aqlqeWsZaylrCWtJa2lriWuZbOlsuWyZbNiU2W3JcNltWW+ZcElwaXCJcTlw6XEZcPlxaXGZcklyqXMJc5lz2XPpdEl0aXSJd Cl0mXXJdgl2SXZpdoUtKXa5dxl3mXhZd8l4GXepeGl4uXj5eQl5yXqJem" +
 "l6OXs5e0l8OXxpfIl8uX3Jftn0 + JkumT2ZPplCmUmZRZlQmUuZUZlSmUyZVZmXmZiZpZmtma6ZvJnfmduZ3ZnY" +
 "mdGZ7ZnumfGZ8pn7mfiaAZoPmgWZ4poZmiuaN5pFmkKaQJpD//+aPppVmk2aW5pXml+aYpplmmSaaZprmmqarZqwmryawJrPmtGa05rUmt6a35rimuOa5prvmuua7pr0mvGa95r7mwabGJsamx+b IpsjmyWbJ5somymbKpsumy+bMptEm0ObT5tNm06bUZtYm3Sbk5uD" + 
„M5Gblpu QOdBp0qnSadr50jnR+dRJ0VnRKdQZ0/nT6dRp1I////////nV2dXp1k" +
 „nVGdUJ1ZnXKdiZ2Hnaudb516nZqdpJ2pnbKdxJ3BnbuduJ26ncadz53Cndmd0534nead7Z3vnf2eGp4bnh6edZ55nn2egZ6InouejJ6SnpWekZ6dnqWeqZ64nqqerZdhnsyezp7PntCe1 J7cnt6e3Z7gnuWe6J7v//+e9J72nvee+Z77nvye/Z8Hnwh2t58VnyGfLJ8+" +
 "n0qfUp9Un2OfX59gn2GfZp9nn2yfap93n3Kfdp+Vn5yfoFgvaceQWXRkUdxxmf////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////" +
 "///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" + 
"///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// /" +
 "////////////////////////////////////////////////w==" ;


 privater statischer Short[] UNICODE_TO_QR_KANJI = neuer Short[1 << 16];

 static { // Entpacken Sie die Shift-JIS-Tabelle in eine berechnungsfreundlichere Form Arrays.fill(UNICODE_TO_QR_KANJI, ( short )-1);
 byte[] bytes = Base64.getDecoder().decode(PACKED_QR_KANJI_TO_UNICODE); 
for ( int i = 0; i < bytes.length; i += 2) {
 char c = ( char )(((bytes[i] & 0xFF) << 8) | (bytes[i + 1] & 0xFF));
 if (c == 0xFFFF)
 weiter ;
 behaupten UNICODE_TO_QR_KANJI[c] == -1;
 UNICODE_TO_QR_KANJI[c] = ( kurz )(i / 2);
 }
 }



 /*---- Sonstig ----*/
 
private QrSegmentAdvanced() { } // Nicht instanziierbar
 }

 /* * Schnelle QR-Code-Generatorbibliothek * * Copyright (c) Project Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * * Hiermit wird jeder Person kostenlos die Erlaubnis erteilt, eine Kopie * dieser Software und der zugehörigen Dokumentation zu erhalten Dateien (die „Software“), ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, Ändern, Zusammenführen, Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen von Kopien der Software und zu Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten, * unter den folgenden Bedingungen: * - Der obige Urheberrechtshinweis und dieser Genehmigungshinweis müssen enthalten sein 
* alle Kopien oder wesentlichen Teile der Software.
 * - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt:
 * aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;


 // Speichert die Teile eines QR-Codes, die nur von der Versionsnummer // und nicht von den Daten oder der Fehlerkorrekturstufe oder -maske abhängen. 
letzte Klasse QrTemplate {

 // Verwenden Sie diesen Memoizer, um Instanzen dieser Klasse abzurufen. öffentlicher statischer finaler Memoizer<Integer,QrTemplate> MEMOIZER
 = new Memoizer<>(QrTemplate::new);


 private finale int- Version; // Im Bereich [1, 40]. 
private endgültige int- Größe; // Abgeleitet von version.
 finale int[]-Vorlage; // Länge und Werte hängen von der Version ab. final int[][] masks; // masks.length == 8 und masks[i].length == template.length. final int[] dataOutputBitIndexes; // Länge und Werte hängen von der Version ab.
 // Zeigt Funktionsbausteine ​​an, die keiner Maskierung unterliegen. Wird verworfen, wenn der Konstruktor fertig ist. // Andernfalls ist isFunction.length == template.length, wenn der Konstruktor ausgeführt wird. 
private int[] isFunction;


 // Erstellt eine QR-Code-Vorlage für die angegebene Versionsnummer. private QrTemplate( int ver) {
 if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
 throw new IllegalArgumentException( „Version außerhalb des gültigen Bereichs“ );
 version = ver;
 Größe = Version * 4 + 17;
 template = new int[(size * size + 31) / 32];
 isFunction = new int[template.length];

 drawFunctionPatterns(); // Liest und schreibt Felder 
masks = genericMasks(); // Liest Felder, gibt Array zurück dataOutputBitIndexes = genericZigzagScan(); // Liest Felder, gibt Array zurück isFunction = null ;
 }


 // Liest das Versionsfeld dieses Objekts und zeichnet und markiert alle Funktionsmodule. private void drawFunctionPatterns() {
 // Horizontale und vertikale Zeitmuster zeichnen für ( int i = 0; i < size; i++) {
 darkenFunctionModule(6, i, ~i & 1);
 darkenFunctionModule(i, 6, ~i & 1); 
}

 // 3 Suchmuster zeichnen (alle Ecken außer unten rechts; überschreibt einige Zeitmodule) drawFinderPattern(3, 3);
 drawFinderPattern(size - 4, 3);
 drawFinderPattern(3, size - 4);

 // Zahlreiche Ausrichtungsmuster zeichnen int[] alignPatPos = getAlignmentPatternPositions();
 int numAlign = alignPatPos.length;
 for ( int i = 0; i < numAlign; i++) {
 for ( int j = 0; j < numAlign; j++) {
 // Zeichnen Sie nicht auf die drei Finder-Ecken 
if (!(i == 0 && j == 0 || i == 0 && j == numAlign - 1 || i == numAlign - 1 && j == 0))
 drawAlignmentPattern(alignPatPos[i], alignPatPos[j]);
 }
 }

 // Konfigurationsdaten zeichnen drawDummyFormatBits();
 drawVersion();
 }


 // Zeichnet zwei leere Kopien der Formatbits. private void drawDummyFormatBits() {
 // Erste Kopie zeichnen für ( int i = 0; i <= 5; i++)
 darkenFunctionModule(8, i, 0); 
DarkenFunctionModule(8, 7, 0);
 DarkenFunctionModule(8, 8, 0);
 DarkenFunctionModule(7, 8, 0);
 for ( int i = 9; i < 15; i++)
 darkenFunctionModule(14 - i, 8, 0);

 // Zweite Kopie zeichnen für ( int i = 0; i < 8; i++)
 darkenFunctionModule(size - 1 - i, 8, 0);
 for ( int i = 8; i < 15; i++)
 darkenFunctionModule(8, size - 15 + i, 0);
 darkenFunctionModule(8, size - 8, 1); // Immer dunkel }


 // Zeichnet zwei Kopien der Versionsbits (mit eigenem Fehlerkorrekturcode), 
// basierend auf dem Versionsfeld dieses Objekts, wenn 7 <= Version <= 40. private void drawVersion() {
 if (Version < 7)
 zurückkommen ;

 // Fehlerkorrekturcode berechnen und Bits packen int rem = version; // Version ist uint6, im Bereich [7, 40] für ( int i = 0; i < 12; i++)
 rem = (rem << 1) ^ ((rem >>> 11) * 0x1F25);
 int Bits = Version << 12 | rem; // uint18 
Assert- Bits >>> 18 == 0;

 // Zeichne zwei Kopien für ( int i = 0; i < 18; i++) {
 int bit = QrCode.getBit(bits, i);
 int a = Größe - 11 + i % 3;
 int b = i / 3;
 darkenFunctionModule(a, b, bit);
 darkenFunctionModule(b, a, bit);
 }
 }


 // Zeichnet ein 9*9-Suchmuster einschließlich des Randtrennzeichens, // mit dem Mittelmodul bei (x, y). Module können außerhalb der Grenzen liegen. 
private void drawFinderPattern( int x, int y) {
 for ( int dy = -4; dy <= 4; dy++) {
 for ( int dx = -4; dx <= 4; dx++) {
 int dist = Math.max(Math.abs(dx), Math.abs(dy)); // Tschebyscheff/Unendlichkeitsnorm int xx = x + dx, yy = y + dy; 
if (0 <= xx && xx < Größe && 0 <= yy && yy < Größe)
 darkenFunctionModule(xx, yy, (dist != 2 && dist != 4) ? 1 : 0);
 }
 }
 }


 // Zeichnet ein 5*5-Ausrichtungsmuster mit dem Mittelmodul // bei (x, y). Alle Module müssen innerhalb der Grenzen liegen. private void drawAlignmentPattern( int x, int y) { 
for ( int dy = -2; dy <= 2; dy++) {
 for ( int dx = -2; dx <= 2; dx++)
 darkenFunctionModule(x + dx, y + dy, Math.abs(Math.max(Math.abs(dx), Math.abs(dy)) - 1));
 }
 }


 // Berechnet ein neues Array von Masken und gibt es zurück, basierend auf den verschiedenen Feldern dieses Objekts. private int[][] genericMasks() {
 int[][] result = new int[8][template.length]; 
for ( int mask = 0; mask < result.length; mask++) {
 int[] maskModules = result[mask];
 for ( int y = 0, i = 0; y < size; y++) {
 for ( int x = 0; x < size; x++, i++) {
 boolesche Umkehrung;
 Schalter (Maske) { 
Fall 0: invert = (x + y) % 2 == 0; Pause ;
 Fall 1: invert = y % 2 == 0; Pause ;
 Fall 2: invert = x % 3 == 0; Pause ;
 Fall 3: invert = (x + y) % 3 == 0; Pause ;
 Fall 4: invertieren = (x / 3 + y / 2) % 2 == 0; Pause ; 
Fall 5: invert = x * y % 2 + x * y % 3 == 0; Pause ;
 Fall 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; Pause ;
 Fall 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; Pause ;
 Standard: throw new AssertionError();
 }
 int bit = (invert ? 1 : 0) & ~getModule(isFunction, x, y);
 maskModules[i >>> 5] |= bit << i;
 }
 } 
}
 Ergebnis zurückgeben ;
 }


 // Berechnet ein Array von Bitindizes und gibt es zurück, basierend auf den verschiedenen Feldern dieses Objekts. private int[] genericZigzagScan() {
 int[] result = new int[getNumRawDataModules(version) / 8 * 8];
 int i = 0; // Bitindex in die Daten für ( int right = size - 1; right >= 1; right -= 2) { // Index der rechten Spalte in jedem Spaltenpaar 
if (rechts == 6)
 rechts = 5;
 for ( int vert = 0; vert < size; vert++) { // Vertikaler Zähler für ( int j = 0; j < 2; j++) {
 int x = rechts - j; // Tatsächliche x-Koordinate boolescher Wert nach oben = ((rechts + 1) & 2) == 0;
 int y = nach oben ? Größe - 1 - vert : vert; // Tatsächliche y-Koordinate 
if (getModule(isFunction, x, y) == 0 && i < result.length) {
 Ergebnis[i] = y * Größe + x;
 i++;
 }
 }
 }
 }
 behaupten i == result.length;
 Ergebnis zurückgeben ;
 }


 // Gibt den Wert des Bits an den angegebenen Koordinaten im angegebenen Raster zurück. 
private int getModule(int[] Grid, int x, int y) {
 behaupten 0 <= x && x < size;
 behaupten 0 <= y && y < size;
 int i = y * Größe + x;
 return QrCode.getBit(grid[i >>> 5], i);
 }


 // Markiert das Modul an den angegebenen Koordinaten als Funktionsmodul. // Außerdem wird das Modul entweder dunkel gesetzt oder seine Farbe bleibt unverändert. 
private void darkenFunctionModule( int x, int y, int enable) {
 behaupten 0 <= x && x < size;
 behaupten 0 <= y && y < size;
 Behauptung aktivieren == 0 || aktivieren == 1;
 int i = y * Größe + x;
 template[i >>> 5] |= enable << i;
 isFunction[i >>> 5] |= 1 << i;
 }


 // Gibt eine aufsteigende Liste der Positionen von Ausrichtungsmustern für diese Versionsnummer zurück. 
// Jede Position liegt im Bereich [0,177) und wird sowohl auf der x- als auch auf der y-Achse verwendet. // Dies könnte als Nachschlagetabelle mit 40 Listen variabler Länge mit vorzeichenlosen Bytes implementiert werden. private int[] getAlignmentPatternPositions() {
 if (Version == 1)
 return new int[] { } ;
 sonst {
 int numAlign = version / 7 + 2;
 int step = (version == 32) ? 26: 
(Version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2;
 int[] result = new int[numAlign];
 Ergebnis[0] = 6;
 for ( int i = result.length - 1, pos = size - 7; i >= 1; i--, pos -= step)
 result[i] = pos;
 Ergebnis zurückgeben ;
 }
 }


 // Gibt die Anzahl der Datenbits zurück, die in einem QR-Code der angegebenen Versionsnummer gespeichert werden können, nachdem // alle Funktionsmodule ausgeschlossen wurden. Dies schließt Restbits ein, daher ist es möglicherweise kein Vielfaches von 8. // Das Ergebnis liegt im Bereich [208, 29648]. Dies könnte als Nachschlagetabelle mit 40 Einträgen implementiert werden. 
static int getNumRawDataModules( int ver) {
 if (ver < QrCode.MIN_VERSION || ver > QrCode.MAX_VERSION)
 throw new IllegalArgumentException( „Versionsnummer außerhalb des gültigen Bereichs“ );
 int result = (16 * ver + 128) * ver + 64;
 if (ver >= 2) {
 int numAlign = ver / 7 + 2;
 Ergebnis -= (25 * numAlign - 10) * numAlign - 55;
 if (ver >= 7) 
Ergebnis -= 36;
 }
 Ergebnis zurückgeben ;
 }

 }

 /* * Schnelle QR-Code-Generatorbibliothek * * Copyright (c) Project Nayuki. (MIT-Lizenz) * https://www.nayuki.io/page/fast-qr-code-generator-library * * Hiermit wird jeder Person kostenlos die Erlaubnis erteilt, eine Kopie * dieser Software und der zugehörigen Dokumentation zu erhalten Dateien (die „Software“), ohne Einschränkung mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, Ändern, Zusammenführen, Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen von Kopien der Software und zu Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten, * unter den folgenden Bedingungen: * - Der obige Urheberrechtsvermerk und dieser Genehmigungsvermerk müssen in * allen Kopien oder wesentlichen Teilen der Software enthalten sein. 
* - Die Software wird „wie besehen“ bereitgestellt, ohne ausdrückliche oder ausdrückliche Gewährleistung jeglicher Art
 * stillschweigend, einschließlich, aber nicht beschränkt auf die Garantien der Marktgängigkeit,
 * Eignung für einen bestimmten Zweck und Nichtverletzung. In keinem Fall darf die
 * Autoren oder Urheberrechtsinhaber haften für jegliche Ansprüche, Schäden oder sonstiges
 * Haftung, sei es aus einer vertraglichen, unerlaubten oder sonstigen Handlung, die sich aus Folgendem ergibt:
 * aus oder im Zusammenhang mit der Software oder der Nutzung oder anderen Geschäften in der
 * Software.
 */

 Paket io.nayuki.fastqrcodegen;

 java.util.Arrays importieren ;
 java.util.Objects importieren ;


 // Berechnet Reed-Solomon-Fehlerkorrekturcodewörter für gegebene Datencodewörter. 
letzte Klasse ReedSolomonGenerator {

 // Verwenden Sie diesen Memoizer, um Instanzen dieser Klasse abzurufen. öffentlicher statischer finaler Memoizer<Integer,ReedSolomonGenerator> MEMOIZER
 = new Memoizer<>(ReedSolomonGenerator::new);


 // Eine Tabelle der Größe 256 * Grad, wobei polynomialMultiply[i][j] = multiply(i, Koeffizienten[j]). // 'Koeffizienten' ist das im Konstruktor berechnete temporäre Array. privates Byte[][] polynomialMultiply;

 
// Erstellt ein Reed-Solomon-ECC-Generatorpolynom für den angegebenen Grad. privater ReedSolomonGenerator( int Degree) {
 if (Grad < 1 || Grad > 255)
 throw new IllegalArgumentException( „Grad außerhalb des Bereichs“ );

 // Das Teilerpolynom, dessen Koeffizienten von der höchsten zur niedrigsten Potenz gespeichert werden. // Zum Beispiel wird x^3 + 255x^2 + 8x + 93 als uint8-Array {255, 8, 93} gespeichert. byte[]-Koeffizienten = neues Byte[Grad]; 
Koeffizienten[Grad - 1] = 1; // Beginnen Sie mit dem Monom x^0
 // Berechnen Sie das Produktpolynom (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{Grad-1}), // und löschen Sie es der höchste Monomterm, der immer 1x^Grad beträgt. // Beachten Sie, dass r = 0x02, ein Generatorelement dieses Feldes GF(2^8/0x11D). int root = 1;
 for ( int i = 0; i < Grad; i++) {
 // Multipliziere das aktuelle Produkt mit (x - r^i) für ( int j = 0; j < Koeffizientenlänge; j++) { 
Koeffizienten[j] = ( byte )multiply(coefficients[j] & 0xFF, root);
 if (j + 1 < Koeffizienten.Länge)
 Koeffizienten[j] ^= Koeffizienten[j + 1];
 }
 root = multiply(root, 0x02);
 }

 polynomialMultiply = neues Byte[256][Grad];
 for ( int i = 0; i < polynomialMultiply.length; i++) {
 for ( int j = 0; j < Grad; j++)
 polynomialMultiply[i][j] = ( byte )multiply(i, Koeffizienten[j] & 0xFF); 
}
 }


 // Gibt das Fehlerkorrekturcodewort für das angegebene Datenpolynom und dieses Teilerpolynom zurück. public void getRemainder(byte[] data, int dataOff, int dataLen, byte[] result) {
 Objects.requireNonNull(data);
 Objects.requireNonNull(result);
 int Degree = polynomialMultiply[0].length;
 behaupten result.length == Grad;

 Arrays.fill(result, ( byte )0); 
for ( int i = dataOff, dataEnd = dataOff + dataLen; i < dataEnd; i++) { // Polynomdivision byte[] table = polynomialMultiply[(data[i] ^ result[0]) & 0xFF];
 for ( int j = 0; j < Grad - 1; j++)
 result[j] = ( byte )(result[j + 1] ^ table[j]);
 Ergebnis[Grad - 1] = Tabelle[Grad - 1];
 }
 }


 // Gibt das Produkt der beiden angegebenen Feldelemente modulo GF(2^8/0x11D) zurück. Die Argumente und das Ergebnis 
// sind vorzeichenlose 8-Bit-Ganzzahlen. Dies könnte als Nachschlagetabelle mit 256*256 Einträgen von uint8 implementiert werden. privates statisches int multiply( int x, int y) {
 behaupten x >> 8 == 0 && y >> 8 == 0;
 // Russische Bauernmultiplikation int z = 0;
 for ( int i = 7; i >= 0; i--) {
 z = (z << 1) ^ ((z >>> 7) * 0x11D); 
z ^= ((y >>> i) & 1) * x;
 }
 behaupten z >>> 8 == 0;
 return z;
 }

 }

Contact form