Notifications
Clear all

[Closed] CgTalk Maxscript Challenge 008: "BACK TO BASICS: Bitmap to Planes"

CgTalk Maxscript Challenge 008: “BACK TO BASICS: Bitmap to Planes”

DESCRIPTION: Recreate a bitmap in the viewport using planes. Each plane should represent a pixel. WARNING: Start small! Remember that even a 256×256 bitmap is 65536 pixels! That’s a lot of planes to calculate!

            INTERMEDIATE SCRIPTERS: Think of another way to represent the pixels in the viewport using geometry.

       ADVANCED SCRIPTERS: Automatically render the result.
   
               RULES:  

[ul]
[li]Code from scratch. Try not to use pre-exisitng functions or plugins.[/li][li]Show your script references, if any (eg. Looking at another script to assist you).[/li][li]You are encouraged to ask for help where needed, but try to do it on your own. The maxscript reference is an invaluable resource.[/li][li]Post your final script inside [/li]“`
tags (located on your posting toolbar).
[li]Post all code into THIS thread.[/li][li]Post the max version you coded in, plus any maxscript extensions you used. (Thanks galagast!)[/li][li]Try to finish the challenge in a week. There is no definite time limit. [/li][/ul] NOTES: After much deliberation, I’ve pulled the challenges down a notch. I’ll start making more simplified assignments that can be easily completed in a week. As usual, keep giving feedback to the level of complexity and types of challenges you want.

10 Replies

[color=white]Hey … I am the first one …[/color]
ok … here goes …
[color=white]


rollout[/color] BitmapToPlanesRollout "BitmapToPlanes" width:162 height:106
(
button btn1 "Select Bitmap" pos:[16,14] width:129 height:28
button btn2 "Create Planes" pos:[16,49] width:129 height:28
progressBar pb1 "" pos:[16,87] width:129 height:8
 
global UserBitMap
global Rowcolors = #()
global mapWidth
global mapheight
 
fn CGTalkPlanefn x y c = 
(
B2P = plane width:1 length:1 lengthSegs:1 widthSegs:1 
B2P.name = uniqueName "CGTPlane_" 
B2P.pos = [x,y,0] 
B2P.wirecolor = c 
) 
 
 
fn createPlanesfn = 
( 
cnt = 0 
for i = 1 to mapheight do 
	 ( 
	 for j = 1 to mapWidth do 
		 ( 
			CGTalkPlanefn j (i * -1) Rowcolors[i][j] 
			cnt += 1 
			BitmapToPlanesRollout.pb1.value = cnt*100/(mapWidth*mapheight) 
		 ) 
	 ) 
)
 
 
 
on btn1 pressed do 
( 
UserBitMap = (selectBitmap caption:"Select small if u wanna see it work!!") 
mapWidth = UserBitMap.width 
mapheight = UserBitMap.height 
for i = 0 to (mapheight - 1) do 
	 ( 
	 Rowcolors[(i+1)] = getPixels UserBitMap [0,i] mapWidth 
	 ) 
close UserBitMap 
) 
 
 
on btn2 pressed do 
( 
createPlanesfn() 
) 
 
 
)
 
createdialog BitmapToPlanesRollout

I guess, I should have instanced a plane instead of creating new ones every time…
Will post again with these changes.
I am attaching a jpg alongwith which can be used to see the script in action … you could use any bitmap, but it better be small size – as erilaz had mentioned earlier –
I didn’t actually check the time it takes to build the planes, but it should be betn 3-4 minutes for this image…

  • shibu

[color=white]I’ve modified the code. Now it uses instanced planes. Coded in Max 6[/color]

[color=white]


 
rollout[/color] BitmapToPlanesRollout "BitmapToPlanes" width:162 height:106
(
button btn1 "Select Bitmap" pos:[16,14] width:129 height:28
button btn2 "Create Planes" pos:[16,49] width:129 height:28
progressBar pb1 "" pos:[16,87] width:129 height:8
 
global UserBitMap
global Rowcolors = #()
global mapWidth
global mapheight
global B2P_orig
 
fn CGTalkPlanefn x y c = 
(
B2P = instance B2P_orig
B2P.name = uniqueName "CGTPlane_"
B2P.pos = [x,y,0]
B2P.wirecolor = c 
) 
 
 
fn createPlanesfn = 
( 
cnt = 0 
for i = 1 to mapheight do 
	 ( 
	 for j = 1 to mapWidth do 
		 ( 
			CGTalkPlanefn j (i * -1) Rowcolors[i][j] 
			cnt += 1 
			BitmapToPlanesRollout.pb1.value = cnt*100/(mapWidth*mapheight) 
		 ) 
	 ) 
)
 
 
 
on btn1 pressed do 
( 
UserBitMap = (selectBitmap caption:"Select small if u wanna see it work!!") 
mapWidth = UserBitMap.width 
mapheight = UserBitMap.height 
for i = 0 to (mapheight - 1) do 
	 ( 
	 Rowcolors[(i+1)] = getPixels UserBitMap [0,i] mapWidth 
	 ) 
close UserBitMap 
) 
 
 
on btn2 pressed do 
( 
B2P_orig = plane width:1 length:1 lengthSegs:1 widthSegs:1
createPlanesfn()
delete B2P_orig
) 
 
 
)
 
createdialog BitmapToPlanesRollout

I’m attaching another bitmap for eval purpose.

  • shibu

Hi!

It didn’t seem to work right away, I think you may need to make B2P_orig a global variable… Or at least it worked when I tried that :), apart from that the result looked great!

~Moosley~

ooops yes, forgot to add that line in here while posting.
Thanks

Great work aaaaCHoooo! The progress bar is a nice little touch.

 rdg

Hello,

here is my entry:

(
 	-- -
 	-- CgTalk Maxscript Challenge 008: "BACK TO BASICS: Bitmap to Planes"
 	-- Dipl. Des. Georg Dümlein
 	-- www.preset.de
 	-- -
 	-- this utility converts a bitmap to grayscale and 
 	-- displays the grayscale value by rotating the pixel plane
 	-- -
 	-- 2005-08-30 inital release
 	-- -
 	-- 3ds max 7.0 
 	-- -
 	-- know issues:
 	-- mixed up x an y in a uncomfortable way
  	-- instancing the planes is much more effective ?
 	-- -
 	-- used referneces:
 	-- see below
 	-- - 
 	global rdg_bmp2Plane
 	global theBitmap
 	try(destroyDialog rdg_bmp2Plane)catch()
 	-- -
 	rollout rdg_bmp2Plane "8::rdg" (
 		
 		-- functions
 		fn grayMode_luminosity theInputColor = (
     	    theOutputColor=theInputColor[1].r*0.299+theInputColor[1].g*0.587+theInputColor[1].b*0.114
 			return theOutputColor
 		)
 		fn grayMode_average theInputColor = (
     	    theOutputColor=(theInputColor[1].r+theInputColor[1].g+theInputColor[1].b)/3
 			return theOutputColor
 		)
 		fn calcAngle thePixel = (
 			theAngle=90-90.0/255.0*thePixel
 			return theAngle
 		)
 		fn calcInvAngle thePixel = (
 			theAngle=90.0/255.0*thePixel
 			return theAngle
 		)
 		
 		-- interface
 		button imgSel_btn " select bitmap "
 		button action_btn "process bitmap" enabled:false
 		group "grayscale mode" (
     		radiobuttons    theGrayMode_rdBtn "" labels:#("luminosity", "average")
 		)
 		
 		-- interface: color correction options
 		group "color correction" (
			colorpicker tintColor "tint color" color:(color 255 255 255)
 			checkbox invertBitmap "invert bitmap"
 		)
 		
 		-- progressbar -> could be better 		
 		progressbar bitmapProgress
 		
 		-- events
 		on imgSel_btn pressed do (
 			theBitmap=selectbitmap()
 			if theBitmap != undefined then (
 				action_btn.enabled=true
 			)else(
 				action_btn.enabled=false
 			)
 		)
 		on action_btn pressed do (
 			theBitmapWidth=theBitmap.width
 			theBitmapHeight=theBitmap.height
 			-- set function to convert bitmap to grayscale
 			case theGrayMode_rdBtn.state of (
 				1: grayAction=grayMode_luminosity
 				2: grayAction=grayMode_average
 			)
 			-- set function to calculate the angle -> invert bitmap
 			case invertBitmap.checked of (
 				true: angleCalc=calcInvAngle
 				false: angleCalc=calcAngle
 			)
 			bitmapProgress.value=0
 			pbTotal=theBitmapWidth*theBitmapHeight
 			pWidth=pLength=10
 			-- process the image
 			for x=0 to (theBitmapWidth-1) do (
 				for y=0 to (theBitmapHeight-1) do (
     		    	thePixel=getPixels theBitmap [x,y] 1
 					thePixel=grayAction thePixel
 		 	currentPlane=plane lsegs:1 wsegs:1 width:pWidth length:pLength
 	 		 currentPlane.name="pixel_"+x as String+"-"+y as String
     		    	currentPlane.wireColor=tintColor.color 
     		    	move currentPlane [x*pWidth,-y*pLength,0]
 					theAngle=angleCalc thePixel
     		    	rot_plane=eulerangles theAngle 0 0
 					rotate currentPlane rot_plane
 					
 				)
     		    bitmapProgress.value=100.0/(theBitmapHeight as Float)* (x as Float)
 			)
 			-- garbage collect ...
 			gc()
 			bitmapProgress.value=0
 		)
 
 	)
 	-- start the show
 	createDialog rdg_bmp2Plane 100 210
 	
 	-- refences
 	--  http://forums.cgsociety.org/showthread.php?t=270025&highlight=destroydialog 
 	-- MaxScript Help: Bitmap Values
 	-- grayscale alogorythms:  http://www.puppet.cgtalk.ru/download/shaders_p_e.shtml 
 	-- MaxScript Help: The Return Expression
 	-- MaxScript Help: Case Expression
 	-- MaxScript Help: Radiobuttons
 	-- MaxScript Help: Plane : GeometryClass
 	-- MaxScript Help: Applying Standard Transformations
 	-- MaxScript Help: Colorpicker
 	-- MaxScript Help: ProgressBar
 )
 

** this is v0.2 : theBitmap is now a global …

Georg

your code works great, rdg !! … nice idea.

  • shibu
 rdg

thanke you aaaaCHoooo.

here is a extended version with animation option:

(
	 -- -
	 -- CgTalk Maxscript Challenge 008: "BACK TO BASICS: Bitmap to Planes"
	 -- Dipl. Des. Georg Dümlein
	 -- www.preset.de
	 -- -
	 -- this utility converts a bitmap to grayscale and 
	 -- displays the grayscale value by rotating the pixel plane
	 -- -
	 -- 2005-08-30	inital release
	-- 2005-09-01	animate button added
	--				position store added
	 -- -
	 -- 3ds max 7.0 
	 -- -
	 -- know issues:
	 -- mixed up x an y in a uncomfortable way
	  -- instancing the planes is much more effective ?
	 -- -
	 -- used referneces:
	 -- see below
	 -- - 
	 global rdg_bmp2Plane
	local theIniFile = getDir #plugcfg + "/rdg_tools.ini"
	 global theBitmap
	 try(destroyDialog rdg_bmp2Plane)catch()
	 -- -
	 rollout rdg_bmp2Plane "8::rdg" (
		 
		 -- functions
		 fn grayMode_luminosity theInputColor = (
	 	    theOutputColor=theInputColor[1].r*0.299+theInputColor[1].g*0.587+theInputColor[1].b*0.114
			 return theOutputColor
		 )
		 fn grayMode_average theInputColor = (
	 	    theOutputColor=(theInputColor[1].r+theInputColor[1].g+theInputColor[1].b)/3
			 return theOutputColor
		 )
		 fn calcAngle thePixel = (
			 theAngle=90-90.0/255.0*thePixel
			 return theAngle
		 )
		 fn calcInvAngle thePixel= (
			 theAngle=90.0/255.0*thePixel
			 return theAngle
		 )
		fn rotatePlaneStatic theAngle currentPlane =(
			rot_plane=eulerangles (theAngle) 0 0
			rotate currentPlane rot_plane

		)
		fn rotatePlaneAnim theAngle currentPlane= (
			with animate on(
				at time 0 (
					rot_plane=eulerangles 0 0 0
					rotate currentPlane rot_plane
				)
				at time animationRange.end (
    		    	rot_plane=eulerangles (theAngle) 0 0
					rotate currentPlane rot_plane
				)
			)
		)
		 
		 -- interface
		 button imgSel_btn " select bitmap "
		 button action_btn "process bitmap" enabled:false
		 group "grayscale mode" (
	 		radiobuttons    theGrayMode_rdBtn "" labels:#("luminosity", "average")
		 )
		 
		 -- interface: color correction options
		 group "color correction" (
			colorpicker tintColor "tint color" color:(color 255 255 255)
			 checkbox invertBitmap "invert bitmap"
		 )
		 -- interface: animate 
		group "animation" (
			radiobuttons anim_rdb "" labels:#("on", "off") columns:2 default:2
		)

		 -- progressbar -> could be better 		
		 progressbar bitmapProgress
		 
		 -- events
		 on imgSel_btn pressed do (
			 theBitmap=selectbitmap()
			 if theBitmap != undefined then (
				 action_btn.enabled=true
			 )else(
				 action_btn.enabled=false
			 )
		 )
		 on action_btn pressed do (
			 theBitmapWidth=theBitmap.width
			 theBitmapHeight=theBitmap.height
			 -- set function to convert bitmap to grayscale
			 case theGrayMode_rdBtn.state of (
				 1: grayAction=grayMode_luminosity
				 2: grayAction=grayMode_average
			 )
			 -- set function to calculate the angle -> invert bitmap
			 case invertBitmap.checked of (
				 true: angleCalc=calcInvAngle
				 false: angleCalc=calcAngle
			 )
			case anim_rdb.state of (
				1: rotateFn=rotatePlaneAnim
				2: rotateFn=rotatePlaneStatic
			)
			 bitmapProgress.value=0
			 pbTotal=theBitmapWidth*theBitmapHeight
			 pWidth=pLength=10
			 -- process the image
			 for x=0 to (theBitmapWidth-1) do (
				 for y=0 to (theBitmapHeight-1) do (
	 		    	thePixel=getPixels theBitmap [x,y] 1
	 		    	thePixel=grayAction thePixel
	 			 	currentPlane=plane lsegs:1 wsegs:1 width:pWidth length:pLength
		  			 currentPlane.name="pixel_"+x as String+"-"+y as String
	 		    	currentPlane.wireColor=tintColor.color 
	 		    	move currentPlane [x*pWidth,-y*pLength,0]
					theAngle=angleCalc thePixel
	 		    	rotateFn theAngle currentPlane
				 )
	 		    bitmapProgress.value=100.0/(theBitmapHeight as Float)* (x as Float)
			 )
			 -- garbage collect ...
			 gc()
			 bitmapProgress.value=0
		 )
		on rdg_bmp2Plane moved pos do (
	 		setIniSetting theIniFile "bitmap::hardLight" "Position" (pos as string)
		 )
 
	 )
	-- position loader by Bobo
	 thePos = execute (getIniSetting theIniFile "bitmap::hardLight" "Position")
	 if thePos == OK do thePos = [100,100] 
	 -- start the show
	 createDialog rdg_bmp2Plane 100 250 thePos.x thePos.y

	 
	 -- refences
	 --  http://forums.cgsociety.org/showthread.php?t=270025&highlight=destroydialog 
	 -- MaxScript Help: Bitmap Values
	 -- grayscale alogorythms:  http://www.puppet.cgtalk.ru/download/shaders_p_e.shtml 
	 -- MaxScript Help: The Return Expression
	 -- MaxScript Help: Case Expression
	 -- MaxScript Help: Radiobuttons
	 -- MaxScript Help: Plane : GeometryClass
	 -- MaxScript Help: Applying Standard Transformations
	 -- MaxScript Help: Colorpicker
	 -- MaxScript Help: ProgressBar
	-- cgtalk thread where bobo axplains how to store the dialog position
	-- MaxScript Help: Time Configuration Dialog
 )

Georg.

Great job guys. I’ll hopefully be posting a new challenge next week. Everyone’s gripped in challenge fever at the moment, so these minor challenges get less attention!

Page 1 / 2