Qr-Code-Bitmap als Datei speichern

  • Antworten:7
  • Bentwortet
Gerhard
  • Forum-Beiträge: 36

02.11.2020, 21:22:19 via Website

Hallo zusammen,

ich schreibe eine App, die Qr-Codes erzeugt und auf dem Display anzeigt, sowie auch den zugehörigen Web-Service, der die Daten dazu verwaltet. Anzeigen eines Qr-Codes auf einem Handy und diesen mit einem anderen Handy einscannen, funktioniert schon.

Jetzt ist der Wunsch, einen erzeugten Qr-Code auch per Mail schicken zu können. Ich müsste also den Qr-Code, der als Bitmap in der App vorhanden ist, als shared File (JPG oder PNG) speichern, dann kann der User seine Mail-App öffnen und eine Mail mit dieser Datei als Attachment schreiben. Ich habe verschiedene Versuche geschrieben:

FileOutputStream fOut = new FileOutputStream(saveFile);
qrcodeBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
... oder CompressFormat.PNG oder anderer Quality-Wert ...

oder:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
qrcodeBitmap.compress(Bitmap.CompressFormat.JPG, 85, bos);
byte[] bitmapdata = bos.toByteArray();
fos.write(bitmapdata);

Das Ergebnis ist immer, daß eine Datei geschrieben wird, und da ist bei Bitmap.CompressFormat.JPG auch ein Qr-Code-Bild drin; bei PNG ist es nur komplett schwarz oder weiß, je nach Hintergrundfarbe des Layouts, in dem das Bild eingebettet ist.

Bei JPG gelingt es allerdings der serverseitigen Qr-Code-Methode nicht, Qr-Code zu erkennen. Ich habe im Web-Portal eine Upload-Methode, die eine JPG- oder PNG-Datei auf den Server hochlädt; dieser analysiert mit Google Zxing das Bild und ermittelt den enthaltenen Inhalt. Das klappt mit einer PNG-Datei, die ich auf andere Weise erstellt habe, aber trotz etlicher Versuche nicht bei JPG.

Wie kriege ich es hin, die Bitmap in eine lesbare PNG-Datei zu schreiben? Oder wenn ihr eine Idee habt, wie ich Zxing überrede, eine Qr-Code-Datei im JPG-Format zu akzeptieren, wäre das natürlich auch willkommen.

Im voraus vielen Dank
Gerhard

Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.558

03.11.2020, 16:55:52 via Website

Warum gehst du eigentlich den Umweg über das Imageview?
Du hast doch bestimmt irgentwo in deinem Code ein Bitmap oder auch Canvas wo du den QR Code erstellst und auch dann dem Imageview übergibst.
Dann speicher es doch gleich da in eine Datei.

Am besten du erstellst gleich ein Bitmap mit Alpha Kanal und zeichnest auch darauf deinen QR Code. Dann solltest du es auch als PNG speichern können.

Oder du Wandelst das Bitmap in eines mit Alpha Kanal um. „Bitmap.setConfig(...)“ dabei darf die Bitmap aber nicht in der Anzeige sein.

Oder neues Bitmat duch kopieren.
Bitmap bitmapAlpha = qrCodeBitmap.copy( Bitmap.Config.ARGB_8888, false );
false wenn die Pixel beim kopieren nicht geändert werden sollen.

Oder du kopierst in einer Schleife die Pixel selber in das neue Bitmap mit Alpha Kanal.

bei PNG ist es nur komplett schwarz oder weiß, je nach Hintergrundfarbe des Layouts, in dem das Bild eingebettet ist.

Wo in was ist das eingebettet? Benutze das Bitmap oder das Canvas in das du gezeichnet hast nicht eine View der du das Bild schon gegeben hast . Aus der du das Bild wider holen auslesen willst.

— geändert am 03.11.2020, 20:16:06

Hilfreich?
Gerhardswa00
Kommentieren
swa00
  • Forum-Beiträge: 3.707

02.11.2020, 21:30:06 via Website

Hallo Gerhard,

Wie kriege ich es hin, die Bitmap in eine lesbare PNG-Datei zu schreiben?

du musst da schon den Zwischenweg mit einem temporären Alpha Bitmap gehen und canvas verwenden.
Ein JPG besitzt keinen Alpha Kanal.

Bsp
Bitmap mBitmapOut = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mBitmapOut);

... hier dann im Canvas rendern

mBitmapOut .compress(Bitmap.CompressFormat.PNG, 100, outStream);

— geändert am 02.11.2020, 23:19:12

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
Kommentieren
Rafael K.
  • Forum-Beiträge: 2.359

02.11.2020, 21:54:13 via Website

Hier stand Blödsinn :-D

— geändert am 02.11.2020, 21:55:35

Crystal Math - Numbers On Speed -- Verkaufswert Rechner -- Trader Radar - Insider Trade News

Hilfreich?
Kommentieren
Gerhard
  • Forum-Beiträge: 36

03.11.2020, 15:35:02 via Website

Hallo Stefan,

das Gefühl sagt mir, daß dies die Lösung ist, ich habe es nur noch nicht verstanden.

Mit createBitmap und new Canvas erstelle ich, zusätzlich zu den schon vorhandenen und in der App sichtbaren Objekten zwei neue Objekte, die ich der GUI nicht sichtbar werden, richtig? Oder meintest du mit mBitmapOut meine vorhandene Bitmap, die das QrCode-Bild enthält?

Und "im Canvas rendern" heißt imageView.draw (canvas), oder?

Und empfiehlst du JPG oder PNG?

Ich habe folgendes probiert:
Bitmap mBitmapOut = Bitmap.createBitmap(qrcodeBitmap.getWidth(), qrcodeBitmap.getHeight(), Bitmap.Config.ARGB_8888); // neu erzeugtes Objekt
Canvas canvas = new Canvas(mBitmapOut); // neu erzeugtes Objekt

    ImageView qrCodeImageView = findViewById(R.id.qrCodeImageView); // schon vorhandene View, die das QrCode-Bild enthält
    qrCodeImageView.draw(canvas);

    mBitmapOut.compress(Bitmap.CompressFormat.JPEG, 100, outStream);

Mit CompressFormat.JPEG wird eine JPG-Datei mit dem sichtbaren QrCode erzeugt; allerdings habe ich dabei das Problem wie zuvor mit JPG-Dateien, daß der WebService den QrCode nicht identifizieren kann. Ich habe dieselbe Konstruktion auch mit CompressFormat.PNG versucht. Ergebnis ist eine PNG-Datei mit komplett weißem Bild; mit GIMP betrachtet sieht man: es sind weiße Pixel auf transparentem Hintergrund, obwohl der Hintergrund der ImageView schwarz ist.

Wie kriege ich denn den Hintergrund in der erzeugten PNG-Datei schwarz?

Viele grüße
Gerhard

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.558

03.11.2020, 16:08:13 via Website

Hallo
Für mich bedeutet

qrCodeImageView.draw(canvas);

das du dem imageview ein canvas zum rendern gibst und nicht das du das schon im imageview vorhandene bild canvas haben willst.

Du übergibst da dein neues leeres Canvas an das Imageview. Du willst es, aber eigentlich andersrum haben.

— geändert am 03.11.2020, 18:23:52

Hilfreich?
Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.558

03.11.2020, 16:55:52 via Website

Warum gehst du eigentlich den Umweg über das Imageview?
Du hast doch bestimmt irgentwo in deinem Code ein Bitmap oder auch Canvas wo du den QR Code erstellst und auch dann dem Imageview übergibst.
Dann speicher es doch gleich da in eine Datei.

Am besten du erstellst gleich ein Bitmap mit Alpha Kanal und zeichnest auch darauf deinen QR Code. Dann solltest du es auch als PNG speichern können.

Oder du Wandelst das Bitmap in eines mit Alpha Kanal um. „Bitmap.setConfig(...)“ dabei darf die Bitmap aber nicht in der Anzeige sein.

Oder neues Bitmat duch kopieren.
Bitmap bitmapAlpha = qrCodeBitmap.copy( Bitmap.Config.ARGB_8888, false );
false wenn die Pixel beim kopieren nicht geändert werden sollen.

Oder du kopierst in einer Schleife die Pixel selber in das neue Bitmap mit Alpha Kanal.

bei PNG ist es nur komplett schwarz oder weiß, je nach Hintergrundfarbe des Layouts, in dem das Bild eingebettet ist.

Wo in was ist das eingebettet? Benutze das Bitmap oder das Canvas in das du gezeichnet hast nicht eine View der du das Bild schon gegeben hast . Aus der du das Bild wider holen auslesen willst.

— geändert am 03.11.2020, 20:16:06

Hilfreich?
Gerhardswa00
Kommentieren
swa00
  • Forum-Beiträge: 3.707

03.11.2020, 20:58:03 via Website

Hallo Gehrad,

es tut mir ja leid , aber ich habe das Gefühl, du weisst gar nicht den Unterschied zu Alpha und non
Alpha. Wenn du grundsätzlich auf allen Plattformen eine PNG weiter verarbeiten kannst , dann brauchst du ein ALphaChannel Image-Dateiformat. NIEMALS JPG !!!

Du benötigst also einen transparenten Hintergrund und zeichnest darauf mit Canvas NUR den QR-Inhalt ( schwarze) stellen - du kannst nicht einfach ein Image aus den Resourcen nehmen und draufklatschen.

In Canvas zeichnest du also die schwarzen Flächen des QR-Codes - die Lücken bleiben frei und
dann nur als PNG speichern , sonst werden die Lücken wieder mit einer zufälligen Farbe gefüllt.

Du erhälst quasi ein Mehr-Layer Image.

Das Ganze hat NICHTS mit der GUI zu tun , das ist ein Puffer-basierendes Rendering.

Du kannst allerhöchstens mal probieren ein Bitmap aus einer PNG-Resource zu erstellen
(Oder Vektor) und diese dann wiederum als Bitmap auf den Canvas zu rendern.
Aber wie gesagt : niemals über den Weg -> qrCodeImageView.draw(canvas);

Eigentlich hat Jokel schon alles dazu erklärt .

— geändert am 03.11.2020, 21:10:40

Liebe Grüße - Stefan
[ App - Entwicklung ]

Hilfreich?
GerhardPascal P.
Kommentieren
Gerhard
  • Forum-Beiträge: 36

05.11.2020, 17:19:15 via Website

Hallo Jokel, hallo Stefan,

nach etlichen Versuchen habe ich es hinbekommen. Das Verwirrende war, daß Zxing (zumindest in meiner App) WEISSE Punkte auf transparenten Hintergrund schreibt, wie man in GIMP sieht. Das ist in der GUI sehr willommen, da die App eine Farbgestaltung mit mittel- bis dunkelgrüner Hintergrundfarbe hat, da entsteht ein Qrcode-Bild grün auf weiß (oder exakt: weiß auf grün), das sieht richtig schick aus.

Die verschiedenen aufgeführten Varianten haben alle ein PNG mit weißen Punkten auf transparentem Hintergrund geschrieben; wenn der User sich das anschaut, sieht er ein weißes Bild. Meine Lösung ist, Pixel für Pixel auslesen und invertiert in die Datei schreiben.

Vielen Dank und viele Grüße
Gerhard

Hilfreich?
Kommentieren