[GELÖST] LoadPixmapPNG Bilder maskieren?

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

 

CO2

ehemals "SirMO"

Betreff: [GELÖST] LoadPixmapPNG Bilder maskieren?

BeitragSo, März 11, 2018 23:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich schon wieder Very Happy

Ich beobachte aktuell folgendes Problem: Ich habe ein Bild per SavePixmapPNG() in eine Datei geschrieben. Dieses Bild lade ich bei Programmstart per LoadPixmapPNG() wieder aus der Datei und übergebe das Pixmap-Objekt an LoadImage(). In dem Bild gibt es einen Bereich, der durchsichtig gezeichnet werden soll, dort habe ich die Farbe RGB(255, 0, 255) gemalt. Das Problem ist nun, dass die mit LoadPixmapPNG() geladenen Bilder scheinbar nicht auf die Maskcolor reagieren. Lade ich ein Bild normal mit LoadImage() (Auch PNGs kann ich so laden und diese werden maskiert) und einem festen Pfad ist alles gut, sobald LoadPixmapPNG() aufgerufen wird und aus dem Objekt ein Bild geladen wird, klappt es nicht mehr... Woran könnte das liegen?
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti
  • Zuletzt bearbeitet von CO2 am Mi, März 14, 2018 18:59, insgesamt einmal bearbeitet

Lobby

BeitragMo, März 12, 2018 10:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Wohl daran, dass die Maskierung von LoadImage durchgeführt wird. LoadPixmapPNG kann das vermutlich schon allein deswegen nicht, damit aus einem 24 Bit Bild kein 32 Bit Bild wird.

Wozu brauchst du die Maskierung in der Pixmap? Und vielleicht interessanter: Warum verwendest du nicht gleich den Alpha-Kanal anstatt eine Farbe zum Maskieren? Was Anderes macht LoadImage intern auch nicht Smile
TheoTown - Eine Stadtaufbausimulation für Android
 

CO2

ehemals "SirMO"

BeitragMo, März 12, 2018 19:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Weg ist zugegebenermaßen "wirr": Ich habe ein Spielermodell ursprünglich im BMP-Format gehabt (Deshalb die Maskcolor). Das habe ich zunächst ganz konventionell mit LoadImage geladen und alles war gut. Dann habe ich mir aufgrund von "Datenzusammenführung" gedacht, dass die Information, wo das ImageHandle liegt auch mit zu dem Spielermodell gehört. Ich musste also das BMP umwandeln in eine Datei, in der sowohl Bild- als auch zwei Double-Informationen verhaftet sind. Dies mache ich über einen Converter, welcher das Bild so lädt, wie es ist und mit SavePixmapPNG dann in eine Ausgabedatei schreibt (zusammen mit der Information des Handles). Zum laden lese ich die Datei mit ReadStream aus und lade zunächst eine Pixmap via LoadPixmapPNG(), um anschließend aus der Pixmap das Bild per LoadImage zu laden. Ab diesem Zeitpunkt (oder eventuell schon vorher) greift die Maskcolor dann nicht mehr.
Ich habe das BMP nun in ein PNG umgewandelt und den Alphakanal genutzt, so funktioniert es. Trotzdem würde mich interessieren, warum bei meinem ursprünglichen Vorgehen die Maskcolor nicht greift...
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

Lobby

BeitragMo, März 12, 2018 20:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn ich mich recht erinnere hat LoadImage for dem Uploaden einfach alle Pixel mit der Farbe der Maske auf Transparent gesetzt. Wie hast du denn deine Pixmap gezeichnet?

BMP solltest du am besten nie verwenden, es hat keine mir bekannten Vorteile (selbst einlesen geht mit PNG in der Regel schneller weil weniger Daten von der Platte gelesen werden müssen).
TheoTown - Eine Stadtaufbausimulation für Android
 

CO2

ehemals "SirMO"

BeitragDi, März 13, 2018 18:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe folgendes gemacht:
- Das Bild als .bmp sieht wie folgt aus
user posted image

- Zum Schreiben der Datei BlitzMax: [AUSKLAPPEN]
Local img:TImage = LoadImage("player.bmp")

Local stream:TStream = WriteStream("player.mdl")

WriteDouble(stream, 16)
WriteDouble(stream, 16)

Local pix:TPixmap = LockImage(img)
SavePixmapPNG(pix, stream)
UnlockImage(img)

CloseStream(stream)

End


- Zum laden der Datei BlitzMax: [AUSKLAPPEN]
Graphics(800, 600)
Local FPSLimiter:TTimer = CreateTimer(60)

SetMaskColor(255, 0, 255)

Local model:TStream = ReadStream("player.mdl")
Local hanx:Double = ReadDouble(model)
Local hany:Double = ReadDouble(model)
Local pix:TPixmap = LoadPixmapPNG(model)
CloseStream(model)

Local img:TImage = LoadImage(pix)

SetImageHandle(img, hanx, hany)

Local rot:Double = 0

Repeat
WaitTimer(FPSLimiter)
Cls()

SetRotation(rot)
DrawImage(img, 100, 100)

rot = (rot + 0.5) Mod 360

Flip(0)
Until KeyHit(KEY_ESCAPE)
End


- Das Resultat ist anschließend folgendes:
user posted image

Die Maskcolor habe ich vor dem Laden des Bildes gesetzt, auch die explizite Angabe, dass es sich um ein MASKEDIMAGE handelt, ergibt keinen Unterschied.

Ich habe das Spielermodell (und alle anderen betreffenden Bilder) auf PNG umgestellt, die Nutzung des Alphakanals schafft - wie geschrieben - Abhilfe. BMP ist bei mir irgendwie so drin, wenn ich ein Bild für ein Spiel male, wird das als erstes im BMP-Format gespeichert... Das werde ich dann in Zukunft nicht mehr tun, die Vorteile waren mir gar nicht so klar. Very Happy
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

Lobby

BeitragDi, März 13, 2018 20:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Hab mir mal den zugrunde liegenden Code von LoadImage angesehen (findet man alles bequem auf GitHub). Wenn eine Pixmap angegeben wird, verwendet LoadImage diese einfach als interne Pixmap. Falls ein Dateipfad angegeben wird, lädt er eine Pixmap aus diesem Pfad. Der entscheidende Code für die Maskierung ist dieser hier (eine Methode von TImage, die von TImage.Load aufgerufen wird):
BlitzMax: [AUSKLAPPEN]
Method SetPixmap( index,pixmap:TPixmap )
If (flags & MASKEDIMAGE) And AlphaBitsPerPixel[pixmap.format]=0
pixmap=MaskPixmap( pixmap,mask_r,mask_g,mask_b )
EndIf
pixmaps[index]=pixmap
seqs[index]=0
frames[index]=Null
End Method

Die besagt, dass nur maskiert wird, wenn die Pixmap noch keinen Alpha-Kanal hat. Deine gespeicherte Pixmap hat aber einen Alphakanal, denn das LoadImage aus deinem Code zum Schreiben maskiert bereits eine Farbe aus der Bitmap, und zwar schwarz Twisted Evil (so zumindest lese ich den Code)

Die einfachste Lösung wäre wohl, bereits in deinem schreibenden Programm die MaskColor auf 255,0,255 zu setzen, um dann im lesenden Programm darauf zu verzichten.
TheoTown - Eine Stadtaufbausimulation für Android
 

CO2

ehemals "SirMO"

BeitragMi, März 14, 2018 18:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, wenn ich im schreibenden Programm die Maskcolor entsprechend setze, funktioniert es, auch wenn im lesenden Programm nochmal die Maskcolor gesetzt wird...

Ich "tagge" diesen Thread mal als [GELÖST], die ursprüngliche Frage wurde ja geklärt.

Danke Dir Wink
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

soli

BeitragMo, Apr 01, 2019 23:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist zwar lange her, aber in einem englischen Forum wurde ganz gut erklärt warum das so ist.
Vielleicht nutzt es jemand.

https://www.syntaxbomb.com/index.php?topic=4182.0
Zitat:
SetBlend SOLIDBLEND
before anything you do not want to have transparency

SetBlend MASKBLEND
before anything in which you want pixels either 100% or completely transparent (must have alpha channel, or be loaded with SetMaskColor() first)

SetBlend ALPHABLEND
Before anything with an alpha channel from 0 through 255 determines the amount of transparency. Equivalent to MASKBLEND if the alpha channel contains only 0 or 255.

SetBlend LIGHTBLEND
Will add the pixels of the image to the pixels of the backbuffer, creating a lighting effect

SetBlend SHADEBLEND
Will multiply the pixels with the backbuffer to cause a shading effect.

Note that SetMaskColor() does not work the way you might think it does. BlitzMax does not use mask colors while drawing images, it only uses the alpha channel. SetMaskColor() just tells BlitzMax that while loading any image without an alpha channel, create one and check to see if the pixel color equals the mask color. If it does, then set the image's alpha for that pixel to 0, otherwise set it to 255. This happens at load time, so it will not have any affect on images previously loaded. It also has no affect on images that already have an alpha channel.

So to summarize: The equivalent of DrawBlock is
SetBlend SOLIDBLEND
DrawImage Image,x,y

The equivalent of early blitz DrawImage is
SetBlend ALPHABLEND 'or SetBlend MASKBLEND
DrawImage Image,x,y

Note also that BlitzMax SetMaskColor defaults to 0,0,0. So if your mask color is black, no need to call SetMaskColor first. Also SetBlend ALPHABLEND is default, so if you are loading only images that have an alpha channel already, no need to call that. When you call either of those commands, the state remains the same until you call the command again, so you only need to call them once and not worry about it again until you need to change it.
solitaire

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group