Aktuelle Zeit: 16.08.2018 02:00

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 17 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: Sprite als tga speichern
BeitragVerfasst: 13.06.2018 21:53 
Offline

Registriert: 08.03.2009 16:08
Guten Tag,

ich arbeite an einem kleinen Grafikprogramm. Das soll nicht Gimp ersetzen, sondern dient nur einem einzigen Zweck, für den es nichts gibt. Als "Pinsel" verwende ich ein Sprite, weil man das rotieren kann. Weil ich es nicht anders hinbekommen habe, benutze ich für das Bild, das bemalt werden soll, auch ein Sprite. Das mit dem Pinsel und dem Malen klappt auch wunderbar.

Problem ist nur: Sprites kann man nicht als tga speichern (Ist das Absicht oder ein Versehen?) sondern nur als bmp,jpg, jpeg2000 (nie gehört) und png:

SaveSprite(#Sprite, DateiName$ [, ImagePlugin [, Flags]])
#PB_ImagePlugin_BMP : Speichert das Bild als BMP. (Standard-Format)
#PB_ImagePlugin_JPEG : Speichert das Bild als JPEG (der Befehl UseJPEGImageEncoder() muss verwendet werden)
#PB_ImagePlugin_JPEG2000 : Speichert das Bild als JPEG2000 (der Befehl UseJPEG2000ImageEncoder() muss verwendet werden)
#PB_ImagePlugin_PNG : Speichert das Bild als PNG (der Befehl UsePNGImageEncoder() muss verwendet werden)

Ich habe es einfach mal "SaveSprite(#Sprite, DateiName$#PB_ImagePlugin_TGA)" versucht, geht aber nicht.

Ich brauche es aber unbeding als tga. Dass ich das mit Gimp umwandeln könnte, ist klar, aber wie sieht das denn aus ...

Ich dachte mir nun, das Sprite liegt ja im Speicher, also lese ich den einfach aus. 24 bit, also 3 * 3 byte über die Bildgröße 1600 * 1600 macht 3 * 1600 * 1600. Die byte-Reihenfolge kriege ich schon hin, wenn die nicht stimmen sollte. Den tga-Header kopiere ich einfach aus einer anderen tga im selben Format (18 Byte, hat schon 10.000 mal geklappt). Von Speicher verstehe ich aber leider überhaupt nichts.

Die Speicheraddresse des Spites, kriegt man ja, habe ich hier gelesen, mit drawingbuffer() heraus. Also habe ich geschrieben:

Code:

;Kopieren des tga-Headers
file1 = ReadFile(#PB_Any,"kopier.tga")
file2 = CreateFile(#PB_Any,"sprite.tga")
For x = 1 To 18
  a = ReadAsciiCharacter(file1)
  WriteAsciiCharacter(file2,a)
Next

; jetzt geht's los

StartDrawing(SpriteOutput(spriteBig))
*Buffer = DrawingBuffer()
StopDrawing()
For x = 1 To 1600 * 1600 * 3
  a = PeekA(*buffer)
  *buffer = *buffer + 8
  WriteAsciiCharacter(file2,a)
Next


Klappt natürlich nicht und gibt einen Speicherfehler. Wie geht's richtig?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 13.06.2018 22:01 
Offline
Benutzeravatar

Registriert: 01.04.2007 20:18
TGA Bildformat

Bei Wikipedia ist eine Formatbeschreibung vorhanden. Allerdings, wenn ich diese Beschreibung lese, frage ich mich, warum es tga sein muss...
Png scheint da doch mehr zu bieten...

_________________
PureBasic 5.46 LTS / 5.62 (Windows x86/x64) | Windows10 Pro x64 | Z370 Extreme4 | i7 8770k | 32GB RAM | iChill GeForce GTX 980 X4 Ultra | HAF XF Evo​​


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 14.06.2018 18:58 
Offline

Registriert: 08.03.2009 16:08
Tga muss es sein, das nur das Format dann weiterverarbeitet werden kann. Warum ich den Header nicht selber mache? Mir ist es zu lästig, da 18 Bytes zu definieren und auch noch die Art und Größe des Bildes zu berücksichtigen. Kopieren geht leichter. Wenn ich verstünde, wie das mit "DATA" funktioniert, wäre es vielleicht anderes, tue ich aber nicht.

Das Programm ist eigentlich fertig und läuft prächtig, nur das Speichern geht halt nicht.

Habe bei der Gelegenheit übrigens festgestellt, dass PB kein Greyscale-TGA kann (Indexed colour habe ich nicht ausprobiert). Ist sicherlich nicht wichtig, sollte aber vielleicht erwähnt werden, ich war schon etwas enttäuscht.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 15.06.2018 22:49 
Offline

Registriert: 08.03.2009 16:08
Ich habe es inzwischen hinbekommen:
Code:
StartDrawing(SpriteOutput(spriteBig))
 adresse = DrawingBuffer()
 StopDrawing()
 *adresse = adresse
 
 For x = 1 To 1600 * 1600
  rot  = PeekA(*adresse)
  *adresse + 1
  gruen = PeekA(*adresse)
  *adresse + 1
  blau = PeekA(*adresse)
  *adresse + 1
  *adresse + 1 ; <= PB benutzt vier Byte/Pixel und nicht drei
  WriteAsciiCharacter(file1,rot)
  WriteAsciiCharacter(file1,gruen)
  WriteAsciiCharacter(file1,blau)
Next


Allerdings steht das Bild auf dem Kopf, da die y-Achse im Original von unten nach oben läuft. Die Zeilen vom Ende nach vorne auszulesen, habe ich dann nicht mehr geschafft ;-) Als Ersatz lade ich nach dem Speichern erneut und speichere nochmal. Es ist die Funktionalität, die zählt ;-)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 15.06.2018 22:51 
Offline

Registriert: 10.06.2011 17:23
Hi, ich bin zwar nicht der PB-Crack aber da ich auch schon viel Hilfe in den Foren gefunden habe werfe ich mal mein Wissen in die Runde!

Das 'SaveSprite()' nicht als TGA speichern kann hat einen einfach Grund, es gibt kein 'UseTGAImageEncoder()', ist wohl einfach zu alt und zu ineffizient.

Aber dein Ansatz ging schon einmal in die richtige Richtung:
Den Header eines anderen TGA-Files aus Bequemlichkeit (es sind ja nur 12 Werte) ist unguenstig... das Problem daran ist das du erstmal nicht weisst welches Format der Drawingbuffer hat und dieser nicht mit dem urspruenglichen Image identisch sein muss, dafuer gibt es 'DrawingBufferPixelFormat()'.
Bei mir gibt diese Funktion den Wert '#PB_PixelFormat_32Bits_BGR' zurueck und der entsprechende funktionierende Code (32bit uncompressed RGB Image) schaut dann so aus:

Code:
StartDrawing(SpriteOutput(spriteBig))

*Buffer = DrawingBuffer()
file2 = CreateFile(#PB_Any, "sprite.tga", 0)

WriteByte(file2, 0) ; no id field
WriteByte(file2, 0) ; no color map
WriteByte(file2, 2) ; uncompressed true-color image
WriteWord(file2, 0) ; first colour Map entry in palette
WriteWord(file2, 0) ; number of colours in palette
WriteByte(file2, 0) ; number of bits per palette entry 15,16,24,32
WriteWord(file2, 0) ; x-origin
WriteWord(file2, 0) ; y-origin
WriteWord(file2, SpriteWidth(spriteBig)) ; width
WriteWord(file2, SpriteHeight(spriteBig)) ; height
WriteByte(file2, 32) ; bits per pixel
WriteByte(file2, %00100000) ; image descriptor bits ( descriptor: 00vhaaaa / h horizontal flip / v vertical flip / a alpha bits)

For y = 0 To SpriteHeight(spriteBig)-1
  For x = 0 To SpriteWidth(spriteBig)-1
   
    wert0.b = PeekB(*buffer + (y*SpriteWidth(spriteBig)*4)+(x*4+0)) ; blue
    wert1.b = PeekB(*buffer + (y*SpriteWidth(spriteBig)*4)+(x*4+1)) ; green
    wert2.b = PeekB(*buffer + (y*SpriteWidth(spriteBig)*4)+(x*4+2)) ; red
    wert3.b = PeekB(*buffer + (y*SpriteWidth(spriteBig)*4)+(x*4+3)) ; | $ff ; alpha <- wenn 24bit TGA geladen wurde!
   
    WriteByte(file2, wert0)
    WriteByte(file2, wert1)
    WriteByte(file2, wert2)
    WriteByte(file2, wert3)
   
  Next
Next

CloseFile(file2)

StopDrawing()

Das ist jetzt der Code fuer meinen Rechner, da ist alles 'hart verdrahtet', um flexibel zu sein muessten alle Rueckgabewerte von 'DrawingBufferPixelFormat()' entsprechend behandelt werden.

Weiterhin scheint die Farbreihenfolge im RGB-Mode eines TGA Files NICHT R-G-B zu sein sondern B-G-R (24Bit) bzw. B-G-R-A (32bit). Das Pixelformat in deinem DrawingBuffer scheint also ebenfalls '#PB_PixelFormat_32Bits_BGR' zu sein, daher liest du 4 Bytes (statt der erwarteten 3) und schreibst sie zufaelligerweise auch in der richtigen Reihenfolge, das kann auf anderen Rechnern aber schief gehen.

Code:
 TGA Legend:
 x - unsed bit
 A - alpha channel bit
 R - red channel bit
 G - green channel bit
 B - blue channel bit
 
15-bit pixel depth
 color value: xRRRRRGG GGGBBBBB
 byte[0] = GGGBBBBB;
 byte[1] = xRRRRRGG;
 
16-bit pixel depth
 color value: ARRRRRGG GGGBBBBB
 byte[0] = GGGBBBBB;
 byte[1] = ARRRRRGG;
 
24-bit pixel depth
 color value: RRRRRRRR GGGGGGGG BBBBBBBB
 byte[0] = BBBBBBBB;
 byte[1] = GGGGGGGG;
 byte[2] = RRRRRRRR;
 
32-bit pixel depth
 color value: AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
 byte[0] = BBBBBBBB;
 byte[1] = GGGGGGGG;
 byte[2] = RRRRRRRR;
 byte[3] = AAAAAAAA;


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 16.06.2018 14:04 
Offline

Registriert: 08.03.2009 16:08
Vielen Dank! Ich werde das anpassen und verwenden. Alleine das doppelte Speichern hat mich schon genervt, so ein Notbehelf ist ja nicht gerade schön.

Zufällig war die Farbreihenfolge nicht, das war Versuche und Irrtum :-) Warum sie dann stimmte, war mir allerdings nicht klar. Hardwareabhängigkeit ist natürlich ganz schlecht, schon deshalb muss da etwas richtiges stehen. Hast mir sehr geholfen, ich werde mich aber wohl kaum revanchieren können ...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 16.06.2018 15:43 
Offline
Benutzeravatar

Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg
Syntacks_Error hat geschrieben:
...Das soll nicht Gimp ersetzen, sondern dient nur einem einzigen Zweck, für den es nichts gibt.

Hallo Syntacks Error, hast Du Dir mal "Pro Motion" von Cosmigo angesehen?
https://www.cosmigo.com/

Evtl. kennst Du ja von früher vom Amiga das Grafikprogramm "DeluxePaint". Das Pro Motion ist quasi DeluxePaint im Godmode. Das kann genau das was Du suchst. Es gibt auch eine eingeschränkte Free-Version, die trotzdem schon recht umfangreich ist.

Gruß Kurzer

_________________
"Never run a changing system!"
PB 5.62, OS: Windows 7 Pro x64, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Ich bin Baujahr 1968, also aktuell 50.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 16.06.2018 19:05 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
Hier ein TGA - Loader den ich mal angefangen habe :)
Unterstützt bisher nur unkomprimierte 24 & 32 Bit TGAs.

TGA:: Load() gibt ein PureBasic BMP (24 bzw. 32 Bit) ImageHandle zurück.

Hier das Module:
Code:
;TGA loader by Mijikai (wip)

DeclareModule TGA
  Declare.i Load(*Buffer,File.s = #Null$);as bitmap (internal 24 or 32 bits)
  Declare.i SaveAsBMP(Image.i,File.s)
  Declare.i Free(Image.i)
EndDeclareModule

Module TGA
 
  Structure TGA_STRUCT
    ImageLengthId.a
    ColorMapType.a
    DataCodeType.a
    ColorMapOrigin.w
    ColorMapLength.w
    ColorBits.a
    OriginX.w
    OriginY.w
    Width.w
    Height.w
    BitsPerPixel.a
    ImageDescriptor.a
  EndStructure
 
  Procedure.i Load(*Buffer,File.s = #Null$)
    Protected *TGA.TGA_STRUCT
    Protected FileHandle.i
    Protected *ImageData
    Protected PixelSize.i
    Protected ImageBlob.i
    Protected ImageOffset.i
    Protected ImageSize.i
    Protected Image.i
    Protected PixelIndex.i
    Protected PixelOffset.i
    Protected *DrawingBuffer
    *TGA = AllocateMemory(SizeOf(TGA_STRUCT))
    If *TGA
      If *Buffer
        ;\\ load from memory / not implemented
      Else
        FileHandle = OpenFile(#PB_Any,File) 
        If FileHandle
          If ReadData(FileHandle,*TGA,SizeOf(TGA_STRUCT)) = SizeOf(TGA_STRUCT)
            If *TGA\Width > 0 And *TGA\Height > 0
              If *TGA\BitsPerPixel = 24 Or *TGA\BitsPerPixel = 32
                If *TGA\DataCodeType = 2 ;Or *TGA\DataCodeType = 10
                  PixelSize = *TGA\BitsPerPixel / 8
                  ImageSize = (*TGA\Width * *TGA\Height) * PixelSize
                  ImageBlob = *TGA\ImageLengthId + *TGA\ColorMapLength
                  ImageOffset = SizeOf(TGA_STRUCT) + ImageBlob
                  If Lof(FileHandle) - SizeOf(TGA_STRUCT) = ImageSize + ImageBlob
                    FileSeek(FileHandle,ImageOffset)
                    *ImageData = ReAllocateMemory(*TGA,Lof(FileHandle))
                    If *ImageData
                      *TGA = *ImageData
                      If ReadData(FileHandle,*TGA + ImageOffset,ImageSize) = ImageSize
                        If *TGA\DataCodeType = 2;uncompressed
                          Image = CreateImage(#PB_Any,*TGA\Width,*TGA\Height,*TGA\BitsPerPixel)
                          If Image
                            If StartDrawing(ImageOutput(Image))
                              *DrawingBuffer = DrawingBuffer()
                              For PixelIndex = 0 To (*TGA\Width * *TGA\Height) - 1
                                PixelOffset = ImageOffset + (PixelIndex * PixelSize)
                                CopyMemory(*TGA + PixelOffset,*DrawingBuffer + (PixelIndex * PixelSize),PixelSize)
                              Next
                              StopDrawing()           
                            Else
                              FreeImage(Image)
                              Image = #Null
                            EndIf 
                          EndIf
                        ElseIf *TGA\DataCodeType = 10;compressed
                          ;\\ not implemented
                        EndIf
                      EndIf
                    EndIf
                  EndIf
                EndIf
              EndIf
            EndIf
          EndIf 
          CloseFile(FileHandle)
        EndIf
      EndIf
      FreeMemory(*TGA)
    EndIf
    ProcedureReturn Image
  EndProcedure
 
  Procedure.i SaveAsBMP(Image.i,File.s)
    If IsImage(Image)
      ProcedureReturn SaveImage(Image,File)
    EndIf
  EndProcedure
 
  Procedure.i Free(Image.i)
    If IsImage(Image)
      FreeImage(Image)
    EndIf
  EndProcedure
 
EndModule

;Example:
Global Image.i

Image = TGA::Load(#Null,"test.tga")
Debug Image
Debug TGA::SaveAsBMP(Image,"test_tga_bmp.bmp")
TGA::Free(Image)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 18.06.2018 22:45 
Offline

Registriert: 08.03.2009 16:08
Das ist ja gewaltig, da muss ich erst einmal verstehen, wie das funktioniert. Aber ich habe noch ein anderes klitzekleines Problem: Ich habe nicht nur ein Sprite ("spriteBig") dass als Malgrund dient, sondern auch noch ein paar andere kleine Sprites. Die sind in einer Liste gespeichert. Die will ich nun auf das spriteBig malen, das dann ja abgespeichert wird. Das sieht im Prinzip etwa so aus:

Code:
EnableExplicit

UsePNGImageDecoder()
InitSprite()
InitKeyboard()
Define window.i,screenwindow,spriteBig, spriteNr,x,y,painted
Global NewList spriteList.i()

window = OpenWindow(#PB_Any, 200,200,800,800,"Test")
screenwindow = OpenWindowedScreen(WindowID(window),0,0,800,800)

Procedure createspriteBig()
 Define spriteBig,x,y,
 spriteBig = CreateSprite(#PB_Any,800,800)
 StartDrawing(SpriteOutput(spriteBig))
 FillArea(0,0,-1,$FFCC66)
 StopDrawing()
 ProcedureReturn spriteBig
EndProcedure

Procedure createSprites()
 Define spriteNr,x,y
 For x = 1 To 20
  spriteNr =  CreateSprite(#PB_Any,15,15)
  RotateSprite(spriteNr,x*18,#PB_Absolute)
  AddElement(spriteList())
  spriteList() = spriteNr
 Next 
EndProcedure

spriteBig = createspriteBig()
createSprites()

Repeat
  DisplaySprite(spriteBig,0,0)
  If painted = 0 ;               bis eine Taste gedrückt und gemalt wird
   ForEach spriteList()
    x + 1 : y + 1
    DisplaySprite(spriteList(), x*35,y*35)
   Next
   x = 0 : y = 0
   FlipBuffers()
   ClearScreen(RGB(0, 0, 0))
  EndIf

 ExamineKeyboard()
 If KeyboardInkey() ;    Dann sollen die 20 kleinen Sprites auf das spritBig gemalt werden
  StartDrawing(SpriteOutput(spriteBig))
  DrawingMode(#PB_2DDrawing_Default )
  ForEach spriteList();
   x + 1 : y + 1
   DrawImage(SpriteID(spriteList()),x*35,y*35)
   ;Box(x*35,y*35,15,15,0)
  Next
  StopDrawing()
  MessageRequester("Bild speichern und schließen?","",#PB_MessageRequester_YesNo)
  If #PB_MessageRequester_Yes
   SaveSprite(spriteBig,"sprite.png") ; spriteBig wird gespeichert, ich nehme hier mal png :-)
   End ;           Ende
  EndIf
 EndIf
 Until WaitWindowEvent() =  #PB_Event_CloseWindow


Bitte nach dem Start also einmal eine Taste drücken, sonst tut sich nichts.

Das bigSprite wird auch gespeichert, aber von den kleinen Sprites ist nicht zu sehen. Malt drawimage() nicht auf Sprites oder was ist hier falsch? Die Boxen werden schon gemalt, da fehlt aber die Roatation.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Sprite als tga speichern
BeitragVerfasst: 19.06.2018 12:09 
Offline
Benutzeravatar

Registriert: 06.07.2017 12:24
Bin grad auf der Arbeit, kann also nix testen, aber ich das verstehe, möchtest du "in ein Sprite" andere Bilddaten hineinmalen. Das ist prinzipiell kein Problem, allerdings müßten eben andere Bilddaten als Image vorliegen. Wenn du ein Sprite darstellst mit DisplaySprite (oder DisplayTransparentSprite), wird das IMMER direkt auf den Bildschirm ausgegeben; du kannst keine Sprites in andere Bildpuffer hineinzeichnen.
"Image <> Sprite", das hat auch bei mir etwas gedauert, bis ich das verstanden habe. :)

_________________
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 17 Beiträge ]  Gehe zu Seite 1, 2  Nächste

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  
cron

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye