ResampleImage

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

Lunatix

Betreff: ResampleImage

BeitragMo, Apr 16, 2007 23:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi.

Ich habe angefangen, eine Funktion zu machen, die ein Bild vergrössern/kleinern kann. Zum einarbeiten wollte ich erstmal "Pixel Resize" machen, welches, wie ich dachte, nicht so schwer ist. Ists auch nicht, solange das bild die hälte des originales gross ist. (Zum vergrössern wollte ich später kommen, wenn ich verkleinern kann, also nicht so wichtig)

Problem dabei : da 512 die hälfte von 1024 ist, muss ich hier nur alle 2 pixel 2pixel auslassen. Bloß - wie lasse ich nun bei anderen grössen 1.4 pixel aus... ?

Mein Ansatz :
Code: [AUSKLAPPEN]
   Framework brl.max2d
   Import brl.glmax2d
   Import brl.pngloader
   Import brl.jpgloader
   Import brl.retro
   Import brl.basic


   Graphics 1024,768,0
   SetClsColor 255,255,255
   Local image:TImage = LoadImage("grassland.png")      
         
      Rem
      Hier beliebiges bild einsetzen,
      ich hatte hier 1024x768 sowie > 2500x1900 (foto)
      End Rem
      
   DrawImage image,0,0
   Flip
   Cls
   WaitKey
   Print "resampling"
   image = ResampleImage(image,image.width/2,image.height/2,0)
   Print "ready"

   Repeat
      DrawImage image,0,0
      Flip
      Cls
   Until KeyHit(KEY_ESCAPE)
   End

   Function ResampleImage:TImage(image:TImage,width:Float,height:Float,sampling:Int=0)
      
      If image.width = width And image.height = height Return image
      
      Local nImage:TImage = TImage.Create(width,height,1,MASKEDIMAGE|DYNAMICIMAGE,255,0,0)
      
      nImage.seqs[0]=0
      nImage.Frames[0]=Null
      nImage.Pixmaps[0] = CreatePixmap(width,height,PF_RGBA8888)
      'Hier ist dazu zu sagen, dies ist wie LockImage, nur mit eigener Pixmap
      
      Select sampling
      
         Case 0
            
            Local xFactor:Float = Float(image.width)/Float((image.width-width))
            Local yFactor:Float = Float(Image.height)/Float((Image.height-height))
            
            If xFactor-Int(xFactor) > 0.5
               xFactor = Ceil(xFactor)
            Else
               xFactor = Floor(xFactor)
            EndIf
            If yFactor-Int(yFactor) > 0.5
               yFactor = Ceil(yFactor)
            Else
               yFactor = Floor(yFactor)
            EndIf          
                                              
            For Local x:Float = 0 To Image.width-1    
               'Print x
               If xpos<=xFactor Or x=0
                  
                  For Local y:Float = 0 To Image.height-1
                     If ypos<=yFactor Or y=0
                        If nx < nImage.width And ny < nImage.height
                           nImage.pixmaps[0].WritePixel nx,ny,image.pixmaps[0].ReadPixel(x,y)
                        EndIf
                        ny:+1
                        ypos:+1
                     Else
                        ypos=0
                     EndIf
                  Next
                  ny=0
                  nx:+1
               Else
                  xpos=0
               EndIf
               xpos:+1
            Next
            
            Return nImage
            
      End Select
      
   End Function


Ich hoffe, er ist wenigstens zum Teil richtig... Wink
Ceil und Floor müssen allerdings wahrscheinlich raus, bloß bin ich dann immernoch bei 1.4 oder anderen Pixeln... steh grad so ein bisschen auf dem Schlauch ... Sad
[size=9]Pro|gram|mier|er: Ein Organismus, der Koffein in Software umwandelt.
Geben Sie eine beliebige 11-stellige Primzahl ein, um fortzusetzen...
 

Dreamora

BeitragMo, Apr 16, 2007 23:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Garnicht

Solange du da nicht mit Filtern und damit im Klartext mit Matrizen arbeitest, wirst du nirgends hin kommen.

"Auslassen" ist keine Lösung, das ist ein Hack der in speziellen Fällen funktioniert.
Aber was wenn 800x600 auf 320x290 resampled werden sollen?
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Lunatix

BeitragMo, Apr 16, 2007 23:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh ok, dann hab ich wohl komplett falch angefangen. Werd ich mir das mit den Matrizen mal anschauen... naja man kann ja nicht alles wissen Wink

Edit: Naja, also nun weiss ich (hoffe ich doch) das eine Matrix Pitch,Yaw,Roll und die Skalierung speichert. Nur irgendwie beginnt meine Suche wohl ziehmlich im Nirgendwo, ich find einfach keinen Ansatz... könntest du mir eventuell einen geben oder so etwas in der Art ?
[size=9]Pro|gram|mier|er: Ein Organismus, der Koffein in Software umwandelt.
Geben Sie eine beliebige 11-stellige Primzahl ein, um fortzusetzen...

TheShadow

Moderator

BeitragDi, Apr 17, 2007 20:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
"Auslassen" ist keine Lösung, das ist ein Hack der in speziellen Fällen funktioniert.


ist kein Hack - diese Methode nennt sich "nearest neighbor" - und ist Qualitativ eher die schlechteste Wahl...

der 2. einfachste und 2. schnellste Algorithmus ist "bilineares filtering" - lässt sich auch ohne matrizen errechnen

der beste ist glaube ich lanczos - zur vereinfachung/beschleunigung wird hier mit matrizen gerechnet...
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2
 

Dreamora

BeitragDi, Apr 17, 2007 20:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Inwiefern ist Billinear etwas anders als eine Matrixoperation?
Alles was Pixel um sich herum miteinbezieht ist eine Matrixoperation ...
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Lunatix

BeitragDi, Apr 17, 2007 22:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Mh ok - Bilinear Filtering. So wie ich das nun gelesen habe, ist das so, das aus Vier Pixeln einer berechnet wird... wenn wir ein Quad. von 1-4 haben, würden 1 & 2 verrechnet und der Wert dann mit den unteren - genau hab ichs noch nciht verstanden aber naja. Bloss - wenn ich jetz nur 100 Pixel vom gesamtbild wegnehmen muss, wie entscheide ich dann, welche Pixel a) wegmüssen und b) geglättet werden müssen?
[size=9]Pro|gram|mier|er: Ein Organismus, der Koffein in Software umwandelt.
Geben Sie eine beliebige 11-stellige Primzahl ein, um fortzusetzen...

maximilian

BeitragMi, Apr 18, 2007 15:33
Antworten mit Zitat
Benutzer-Profile anzeigen
/edit: Habs noch mal ein bisschen optimiert.

Code: [AUSKLAPPEN]
Graphics 640, 480, 16, 2
SetBuffer BackBuffer()


Local scale# = 1
Local img = LoadImage("texture.bmp")

IMAGE_WIDTH = ImageWidth(img)-1
IMAGE_HEIGHT = ImageHeight(img)-1

bnk_img = CreateBank(ImageWidth(img)*ImageHeight(img)*4)
bnk_pitch = ImageWidth(img)

For y = 0 To IMAGE_HEIGHT
 For x = 0 To IMAGE_WIDTH
   PokeInt(bnk_img, (y*ImageWidth(img)+x)*4, ReadPixel(x, y, ImageBuffer(img)))
 Next
Next


While Not KeyHit(1)

 LockBuffer BackBuffer()

 dx# = 1/scale#
 dy# = 1/scale#

 w = Floor(IMAGE_WIDTH*scale#-1)
 h = Floor(IMAGE_HEIGHT*scale#-1)

 py# = 0
 For y = 0 To h
  px# = 0

  y1 = Floor(py)
  fractY# = py# - y1
  y2 = (y1 + 1) And IMAGE_HEIGHT

  For x = 0 To w

    x1 = Floor(px)
    fractX# = px# - x1
    x2 = (x1 + 1) And IMAGE_WIDTH

    col = PeekInt(bnk_img, (x1+y1*bnk_pitch) Shl 2)
    Weight# = (1 - fractX#)*(1 - fractY#)
    ar = (col Shr 16) And $FF: ag = (col Shr 8) And $FF: ab = (col) And $FF
    r = ar*Weight#: g = ag*Weight#: b = ab*Weight#

    col = PeekInt(bnk_img, (x1+y2*bnk_pitch) Shl 2)
    Weight# = (1 - fractX#)*fractY#
    ar = (col Shr 16) And $FF: ag = (col Shr 8) And $FF: ab = (col) And $FF
    r = r + ar*Weight#: g = g + ag*Weight#: b = b + ab*Weight#

    col = PeekInt(bnk_img, (x2+y1*bnk_pitch) Shl 2)
    Weight# = fractX#*(1 - fractY#)
    ar = (col Shr 16) And $FF: ag = (col Shr 8) And $FF: ab = (col) And $FF
    r = r + ar*Weight#: g = g + ag*Weight#: b = b + ab*Weight#

    col = PeekInt(bnk_img, (x2+y2*bnk_pitch) Shl 2)
    Weight# = fractX#*fractY#
    ar = (col Shr 16) And $FF: ag = (col Shr 8) And $FF: ab = (col) And $FF
    r = r + ar*Weight#: g = g + ag*Weight#: b = b + ab*Weight#

    WritePixelFast x, y, (r Shl 16) + (g Shl 8) + b

    px# = px# + dx#
  Next
  py# = py# + dy#
 Next

 UnlockBuffer BackBuffer()

 If KeyDown(201) Then scale# = scale# + 0.05
 If KeyDown(209) Then scale# = scale# - 0.05

 Flip
 Cls

Wend

End


Bild-Auf, Bild-Ab zum zoomen. Lässt sich sicherlich noch gut optimieren (evtl. Fixed point, k.A. obs auf heutigen Prozis noch was bringt), und wird mit BMax sowieso schneller laufen.

PS: Hab auch noch ne Fassung für ARM Asm/NDS als fertige universelle Funktion. Smile
Variety is the spice of life. One day ignore people, next day annoy them.
  • Zuletzt bearbeitet von maximilian am Do, Apr 19, 2007 14:00, insgesamt einmal bearbeitet

TheShadow

Moderator

BeitragMi, Apr 18, 2007 18:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Inwiefern ist Billinear etwas anders als eine Matrixoperation?
Alles was Pixel um sich herum miteinbezieht ist eine Matrixoperation ...


eigentlich nicht - ich meine Matrizen aus mathematischer Sicht...


@LordChaos

hat du dir das selbst zusammengestrickt? weil ich meine bilinear hatte etwas andere formeln...
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2

maximilian

BeitragDo, Apr 19, 2007 13:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Kommt daher: http://www.gamedev.net/referen...cle810.asp

Also das Resultat sieht zumindest verdammt bilinear aus. Smile
Variety is the spice of life. One day ignore people, next day annoy them.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group