Seite 1 von 1

png grayscale 16 bit

Verfasst: Freitag 6. März 2020, 18:12
von Isajah
Hallo,

ich habe für ein PC Spiel einen Karten-Editor geschrieben, mit dem man eine heightmap erstellen und alle Masken generieren kann, die das Spiel braucht um eine Karte lesen zu können. das Programm an sich funktioniert schon recht gut.

Das Problem ist die Anforderung an die heightmap: Sie muss eine 16bit Grayscale (ohne alphakanal) PNG Datei sein muss (sollte).

ich habe schon einiges probiert:
matplotlib/pyplot verwende ich um previews anzuzeigen, aber pyplot speichert auch grayscale as 24bit png
Pillow:

Code: Alles auswählen

 
heightmap.astype(numpy.uint16)  
image = Image.fromarray(heightmap, mode='I;16') # genauso 'I'
image.save(os.path.join(map_folder,heightmap_file_name))
schmeißt mir zwar ein 16 bit Bild aus, aber das sieht nach einer Matrix aus schwarzen und weißen punkten aus und nicht wie die Karte, die rauskommen soll

imread mit 'I' liest dagegen karten von anderen ohne Probleme

bei

Code: Alles auswählen

cv2.imwrite(os.path.join(map_folder,heightmap_file_name),heightmap)
kommt auch nix sinnvolles heraus


die numpy arrays sind 1024x1024 mit Werten im Bereich von 0...65535 (also das bestätigen auch die print(heightmap.min(),heightmap.max()) Befehle die ich vor und hinter den entsprechenden Anweisungen gepackt habe.

Ich teste auf einer virtuellen Ubuntu Maschine (falls das von Relevanz ist).

Re: png grayscale 16 bit

Verfasst: Freitag 6. März 2020, 19:00
von __deets__

Re: png grayscale 16 bit

Verfasst: Freitag 6. März 2020, 22:31
von Isajah
Ja danke, da hatte ich auch schon reingeschaut, und mich an den Beispiele orientiert, aber immer einen Datatype Fehler bekommen.

da in der doc von pypng steht, dass es für list ausgelegt ist und für numpy nur so lala funktioniert, habe ich das np.array in eine Liste explizit als int geschrieben und die List dann mit pypng geschrieben :

Code: Alles auswählen

to_img = []
    for i in range(0,1024):
        to_img.append([])
        for j in range(0,1024):
           to_img[i].append(int(heightmap[i][j]))

imgWriter = png.Writer(1024, 1024, greyscale=True, alpha=False, bitdepth=16)
file_buffer = open(os.path.join(map_folder,heightmap_file_name), "wb")
imgWriter.write(file_buffer,to_img)

Re: png grayscale 16 bit

Verfasst: Samstag 7. März 2020, 00:24
von __blackjack__
@Isajah: Das ist falsch eingerückt, und was soll man dazu sagen wenn man nicht weiss was Du da machst und welche Fehlermeldung das nun genau ist. Was ist denn `heightmap`? Was enthält das? Warum wandelst Du das in Listen um? Und warum so umständlich? Wie kommst Du darauf das das für Numpy Arrays nur so lala funktioniert? Der entsprechende Teil wo das gemacht wird liest sich für mich so dass 2D-Arrays sich nicht von verschachtelten Listen unterscheiden: Ist halt eine Sequenz von Sequenzen mit Zahlen. Es gibt eine Notiz zu einem bestimmten Problem, wo aber auch die Lösung zu dem Problem drin steht.

`file_buffer` ist ein komischer Name für ein Dateiobjekt. Dateien sollte man wo möglich mit der ``with``-Anweisung zusammen öffnen.

Wie `to_img` erzeugt wird ist echt ”unpythonisch”. Das wäre eigentlich folgender Einzeiler:

Code: Alles auswählen

to_img = [[int(value) for value in row] for row in heightmap]
Und wenn `heightmap` ein Numpy-Array ist (und 16-Bit-Int-Werte enthält) geht das *noch* einfacher:

Code: Alles auswählen

to_img = heightmap.tolist()
Was bedeutet die Abkürzung `to` im `to_img`-Namen?

Re: png grayscale 16 bit

Verfasst: Samstag 7. März 2020, 13:16
von Sirius3
Und auch falls heightmap den falschen Typ hat, ließe sich das einfacher konvertieren:

Code: Alles auswählen

with open(os.path.join(map_folder, heightmap_file_name), "wb") as output:
    image_writer = png.Writer(1024, 1024, greyscale=True, alpha=False, bitdepth=16)
    image_writer.write(output, heightmap.astype('u2'))