how to crop an image

BlitzMax Forums/BlitzMax Beginners Area/how to crop an image

hub(Posted 2010) [#1]
Hi !
i need some help to have idea how to crop a png image. Imagine that i've a classic 2d sprite on the image at the center. I need to crop the image to delete the transparent pixels arround the sprite ! (into a pixmap)

In fact i've coded a program to automatically make an anim strip from image files. Now i need to center automatically the sprite on each imagestrip frame (before).

Thanks to post algo or sample.

(Here my code, sorry i use french into it)
' Assemble des images pour faire une imagestrip

Strict

Global seed
SeedRnd MilliSecs()
seed=RndSeed()

Global Largeur
Global Hauteur

Global Dossier:String
Global DebutNomFichier:String
Global NomFichierSortie:String = "image_strip_finale_" + Rand (0, 5000) + ".png"

Notify "Le programme débute..."

Dossier:String = RequestDir:String("Veuillez indiquer le dossier ou se trouve les images")

If Dossier:String = "" Then
	Notify "Ne trouve pas le dossier, traitement annulé"
	End
End If

DebutNomFichier = RequestFile("Sélectionnez le premier fichier à traiter", "Image Files:png;")
If DebutNomFichier = "" Then
	Notify "Fichier non renseigné, traitement annulé"
	End
Else
	DebutNomFichier = Left (DebutNomFichier, Len (DebutNomFichier) - 7)
	Notify "base fichier = '" + DebutNomFichier + "'"
End If

Global Nombre_fichiers = 16
Global hImage:TImage[Nombre_fichiers+1]

' préchargement des fichiers

For Local i = 1 To Nombre_fichiers
	
	Local Nomfic:String
	
	If i <= 9 Then
		Nomfic = DebutNomFichier$ + "00" + String(i) + ".png"
	Else
		Nomfic = DebutNomFichier$ + "0" + String(i) + ".png"
	End If
	hImage[i] = LoadImage (NomFic:String, DYNAMICIMAGE)
	Largeur = ImageWidth (hImage[i])
	Hauteur = ImageHeight (hImage[i])
	If hImage[i] = Null Then
		Notify "Erreur ne trouve pas le fichier '" + Nomfic:String + "' !"
		End
	End If
Next

Local ImageSortie:TPixmap = CreatePixmap (Largeur * Nombre_fichiers, Hauteur, PF_BGRA8888)

Local decalx = 0
Local a
Local pixmap:TPixmap

Notify "Traitement commence avec largeur = " + Largeur + ", hauteur = " + Hauteur + "."

ImageSortie.ClearPixels(0)

For Local i = 1 To Nombre_fichiers 
	pixmap = LockImage:TPixmap(hImage[i], 0, True, True)
	For Local y = 0 To Hauteur - 1
		For Local x = 0 To Largeur - 1
			a = ReadPixel (pixmap, x, y)
			WritePixel (ImageSortie, x + decalx, y, a)
		Next
	Next
    UnlockImage(hImage[i], 0)
	decalx = decalx + Largeur
Next

SavePixmapPNG(ImageSortie, Dossier:String + "/" + NomFichierSortie:String)
Notify "Traitement terminé, fichier : " + Dossier:String + "/" + NomFichierSortie:String + " écrit."


Last edited 2010


Jesse(Posted 2010) [#2]
Sorry Hub, I am not sure I understand exactly what you are trying to do.
Are you trying to figure out how to put images in the center of a frame or are you trying to remove the the transparent color from an image while incorporating it to the frames image? Or both?

Do all of the images have alpha for transparency?


Are all of your images PF_BGRA8888 format?

finally are you trying to cut out an image from another image to paste into the frames image?


hub(Posted 2010) [#3]
Thanks for your help Jesse. Finally i've written this code and it works well !

' Assemble des images pour faire une imagestrip

Strict

Global seed
SeedRnd MilliSecs()
seed=RndSeed()

Global Largeur
Global Hauteur

Global Dossier:String
Global DebutNomFichier:String
Global NomFichierSortie:String = "image_strip_finale_" + Rand (0, 5000) + ".png"

Notify "Le programme débute..."

Dossier:String = RequestDir:String("Veuillez indiquer le dossier ou se trouve les images")

If Dossier:String = "" Then
	Notify "Ne trouve pas le dossier, traitement annulé"
	End
End If

DebutNomFichier = RequestFile("Sélectionnez le premier fichier à traiter", "Image Files:png;")
If DebutNomFichier = "" Then
	Notify "Fichier non renseigné, traitement annulé"
	End
Else
	DebutNomFichier = Left (DebutNomFichier, Len (DebutNomFichier) - 7)
	Notify "base fichier = '" + DebutNomFichier + "'"
End If

Global Nombre_fichiers = 16
Global hImage:TImage[Nombre_fichiers+1]

' préchargement des fichiers

For Local i = 1 To Nombre_fichiers
	
	Local Nomfic:String
	
	If i <= 9 Then
		Nomfic = DebutNomFichier$ + "00" + String(i) + ".png"
	Else
		Nomfic = DebutNomFichier$ + "0" + String(i) + ".png"
	End If
	hImage[i] = LoadImage (NomFic:String, DYNAMICIMAGE)
	Largeur = ImageWidth (hImage[i])
	Hauteur = ImageHeight (hImage[i])
	If hImage[i] = Null Then
		Notify "Erreur ne trouve pas le fichier '" + Nomfic:String + "' !"
		End
	End If
Next

Local ImageSortie:TPixmap = CreatePixmap (Largeur * Nombre_fichiers, Hauteur, PF_BGRA8888)

Local decalx = 0
Local a
Local pixmap:TPixmap

Notify "Traitement commence avec largeur = " + Largeur + ", hauteur = " + Hauteur + "."

ImageSortie.ClearPixels(0)

' algo crop

For Local i = 1 To Nombre_fichiers 

	Local nx1 : Int
	Local ny1 : Int
	Local nx2 : Int
	Local ny2 : Int
	
	pixmap = LockImage:TPixmap(hImage[i], 0, True, True)
	
	' crop haut
	
	Local Compteur
	
	ny1 = 0
	For Local y=0 To Hauteur - 1
		compteur = 0
		For Local x=0 To Largeur - 1
			a = ReadPixel (pixmap, x, y)
			If a = 0 Then
				Compteur = Compteur + 1
			End If
		Next
		If Compteur = Largeur Then
			ny1 = ny1 + 1
		Else
			Exit
		End If
	Next
	
	' crop bas
	ny2 = Hauteur - 1
	For Local y = Hauteur-1 To 0 Step - 1
		compteur = 0
		For Local x=0 To Largeur-1
			a = ReadPixel (pixmap, x, y)
			If a = 0 Then
				Compteur = Compteur + 1
			End If
		Next
		If Compteur = Largeur Then
			ny2 = ny2 - 1
		Else 
			Exit
		End If
	Next
	
	' crop gauche	
		
	nx1 = 0
	For Local x=0 To Largeur - 1
		compteur = 0
		For Local y=0 To Hauteur - 1
			a = ReadPixel (pixmap, x, y)
			If a = 0 Then
				Compteur = Compteur + 1
			End If
		Next
		If Compteur = Hauteur Then
			nx1 = nx1 + 1
		Else
			Exit
		End If
	Next

	' crop droite
		
	nx2 = Largeur - 1
	For Local x = Largeur-1 To 0  Step - 1
		compteur = 0
		For Local y=0 To Hauteur - 1
			a = ReadPixel (pixmap, x, y)
			If a = 0 Then
				Compteur = Compteur + 1
			End If
		Next
		If Compteur = Hauteur Then
			nx2 = nx2 - 1
		Else
			Exit
		End If
	Next
	
	Print "Crop : x1=" + nx1 + ",y1=" + ny1 + ",x2=" + nx2 + ",y2=" + ny2
	
	' calcule l'écart
	
	Local posx = (Largeur - (nx2-nx1)) / 2
	Local posy = (Hauteur - (ny2-ny1)) / 2
	
	Print "PosX=" + posX + ",PosY=" + PosY
	
	pixmap = LockImage:TPixmap(hImage[i], 0, True, True)
	
	Local incx
	Local incy
	
	incx = PosX + decalX
	incy = PosY

	For Local y = ny1 To ny2 
		incx = PosX + decalX
		For Local x = nx1 To nx2 
			a = ReadPixel (pixmap, x, y)
			'Print "incx=" + incx + ",incy=" + incy			
			WritePixel (ImageSortie, incx, incy, a)
			incx = incx + 1
		Next
		incy = incy + 1
	Next
    UnlockImage(hImage[i], 0)
	decalx = decalx + Largeur

Rem
	pixmap = LockImage:TPixmap(hImage[i], 0, True, True)
	For Local y = 0 To Hauteur - 1
		For Local x = 0 To Largeur - 1
			a = ReadPixel (pixmap, x, y)
			WritePixel (ImageSortie, x + decalx, y, a)
		Next
	Next
    UnlockImage(hImage[i], 0)
	decalx = decalx + Largeur
End Rem

Next

SavePixmapPNG(ImageSortie, Dossier:String + "/" + NomFichierSortie:String)
Notify "Traitement terminé, fichier : " + Dossier:String + "/" + NomFichierSortie:String + " écrit."




GfK(Posted 2010) [#4]
Are you not aware of PixmapWindow()?


hub(Posted 2010) [#5]
Thanks Gfk. In fact this code detect the transparent pixels arround the sprite. As the sprite could be not centered inside the first image, i center it into the new imagestrip frame. It's not optimized code, but works for my needs.

i use lightwave to produce 3d to 2d sprite. i animate them into lightwave. When i render the animation, ligthwave produce many png files (each file is for an animation frame). It's difficult for me to center the sprite inside lightwave.

Before this code i've used photoshop and copy paste !