pixmap.monkey2 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. Namespace std.graphics
  2. #rem monkeydoc Pixmaps allow you to store and manipulate rectangular blocks of pixel data.
  3. A pixmap contains a block of memory used to store a rectangular array of pixels.
  4. #end
  5. Class Pixmap
  6. #rem monkeydoc @hidden
  7. #end
  8. Field OnDiscarded:Void()
  9. #rem monkeydoc Creates a new pixmap.
  10. @param width The width of the pixmap in pixels.
  11. @param height The height of the pixmap in pixels.
  12. @param format The pixmap format.
  13. @param data A pointer to the pixmap data.
  14. @param pitch The pitch of the data.
  15. #end
  16. Method New( width:Int,height:Int,format:PixelFormat=PixelFormat.RGBA32 )
  17. Local depth:=PixelFormatDepth( format )
  18. Local pitch:=width*depth
  19. Local data:=Cast<UByte Ptr>( libc.malloc( pitch*height ) )
  20. _width=width
  21. _height=height
  22. _format=format
  23. _depth=depth
  24. _data=data
  25. _pitch=pitch
  26. OnDiscarded=Lambda()
  27. libc.free( data )
  28. End
  29. End
  30. Method New( width:Int,height:Int,format:PixelFormat,data:UByte Ptr,pitch:Int )
  31. Local depth:=PixelFormatDepth( format )
  32. _width=width
  33. _height=height
  34. _format=format
  35. _depth=depth
  36. _data=data
  37. _pitch=pitch
  38. End
  39. #rem monkeydoc Releases the memory used by a pixmap.
  40. Memory is only released if the pixmap was created using New, Copy, Convert or Load.
  41. If the pixmap represents a 'window' into another pixmap (ie: it was created using Window) then memory is not released.
  42. Discarding a pixmap also sets its width, height, pitch and depth to 0.
  43. #end
  44. Method Discard()
  45. If Not _data Return
  46. _width=0
  47. _height=0
  48. _pitch=0
  49. _depth=0
  50. _data=Null
  51. OnDiscarded()
  52. End
  53. #rem monkeydoc The pixmap width.
  54. #end
  55. Property Width:Int()
  56. Return _width
  57. End
  58. #rem monkeydoc The pixmap height.
  59. #end
  60. Property Height:Int()
  61. Return _height
  62. End
  63. #rem monkeydoc The pixmap format.
  64. #end
  65. Property Format:PixelFormat()
  66. Return _format
  67. End
  68. #rem monkeydoc The pixmap depth.
  69. The number of bytes per pixel.
  70. #end
  71. Property Depth:Int()
  72. Return _depth
  73. End
  74. #rem monkeydoc True if pixmap format includes alpha.
  75. #end
  76. Property HasAlpha:Bool()
  77. Select _format
  78. Case PixelFormat.A8,PixelFormat.IA16,PixelFormat.RGBA32
  79. Return True
  80. End
  81. Return False
  82. End
  83. #rem monkeydoc The raw pixmap data.
  84. #end
  85. Property Data:UByte Ptr()
  86. Return _data
  87. End
  88. #rem monkeydoc The pixmap pitch.
  89. This is the number of bytes between one row of pixels in the pixmap and the next.
  90. #end
  91. Property Pitch:Int()
  92. Return _pitch
  93. End
  94. #rem monkeydoc Gets a pointer to a pixel in the pixmap.
  95. @param x the x coordinate of the pixel.
  96. @param y the y coordinate of the pixel.
  97. @return the address of the pixel at `x`, `y`.
  98. #end
  99. Method PixelPtr:UByte Ptr( x:Int,y:Int )
  100. Return _data + y*_pitch + x*_depth
  101. End
  102. #rem monkeydoc Sets a pixel to a color.
  103. Sets the pixel at `x`, `y` to `pixel`.
  104. In debug builds, a runtime error will occur if the pixel coordinates lie outside of the pixmap area.
  105. @param x The x coordinate of the pixel.
  106. @param y The y coordinate of the pixel.
  107. @param color The color to set the pixel to.
  108. #end
  109. Method SetPixel( x:Int,y:Int,color:Color )
  110. DebugAssert( x>=0 And y>=0 And x<_width And y<_height )
  111. Local p:=PixelPtr( x,y )
  112. Select _format
  113. Case Format.A8
  114. p[0]=color.a * 255
  115. Case Format.I8
  116. p[0]=color.r * 255
  117. Case Format.IA16
  118. p[0]=color.r * 255
  119. p[1]=color.a * 255
  120. Case Format.RGB24
  121. p[0]=color.r * 255
  122. p[1]=color.g * 255
  123. p[2]=color.b * 255
  124. Case Format.RGBA32
  125. p[0]=color.r * 255
  126. p[1]=color.g * 255
  127. p[2]=color.b * 255
  128. p[3]=color.a * 255
  129. Default
  130. Assert( False )
  131. End
  132. End
  133. #rem monkeydoc Gets the color of a pixel.
  134. Gets the pixel at `x`, `y` and returns it in ARGB format.
  135. In debug builds, a runtime error will occur if the pixel coordinates lie outside of the pixmap area.
  136. @param x The x coordinate of the pixel.
  137. @param y The y coordinate of the pixel.
  138. @return The color of the pixel at `x`, `y`.
  139. #end
  140. Method GetPixel:Color( x:Int,y:Int )
  141. DebugAssert( x>=0 And y>=0 And x<_width And y<_height )
  142. Local p:=PixelPtr( x,y )
  143. Select _format
  144. Case Format.A8
  145. Return New Color( 0,0,0,p[0]/255.0 )
  146. Case Format.I8
  147. Local i:=p[0]/255.0
  148. Return New Color( i,i,i,1 )
  149. Case Format.IA16
  150. Local i:=p[0]/255.0
  151. Return New Color( i,i,i,p[1]/255.0 )
  152. Case Format.RGB24
  153. Return New Color( p[0]/255.0,p[1]/255.0,p[2]/255.0,1 )
  154. Case Format.RGBA32
  155. Return New Color( p[0]/255.0,p[1]/255.0,p[2]/255.0,p[3]/255.0 )
  156. Default
  157. Assert( False )
  158. End
  159. Return Color.None
  160. End
  161. #rem monkeydoc Sets a pixel to an ARGB color.
  162. Sets the pixel at `x`, `y` to `pixel`.
  163. In debug builds, a runtime error will occur if the pixel coordinates lie outside of the pixmap area.
  164. @param x The x coordinate of the pixel.
  165. @param y The y coordinate of the pixel.
  166. @param color The pixel to set in ARGB format.
  167. #end
  168. Method SetPixelARGB( x:Int,y:Int,color:UInt )
  169. DebugAssert( x>=0 And y>=0 And x<_width And y<_height )
  170. Local p:=PixelPtr( x,y )
  171. Select _format
  172. Case Format.A8
  173. p[0]=color Shr 24
  174. Case Format.I8
  175. p[0]=color Shr 16
  176. Case Format.IA16
  177. p[0]=color Shr 24
  178. p[1]=color Shr 16
  179. Case Format.RGB24
  180. p[0]=color Shr 16
  181. p[1]=color Shr 8
  182. p[2]=color
  183. Case Format.RGBA32
  184. p[0]=color Shr 16
  185. p[1]=color Shr 8
  186. p[2]=color
  187. p[3]=color Shr 24
  188. Default
  189. Assert( False )
  190. End
  191. End
  192. #rem monkeydoc Gets the ARGB color of a pixel.
  193. Get the pixel at `x`, `y` and returns it in ARGB format.
  194. @param x the x coordinate of the pixel.
  195. @param y the y coordinate of the pixel.
  196. @return the pixel at `x`, `y` in ARGB format.
  197. #end
  198. Method GetPixelARGB:UInt( x:Int,y:Int )
  199. DebugAssert( x>=0 And y>=0 And x<_width And y<_height )
  200. Local p:=PixelPtr( x,y )
  201. Select _format
  202. Case Format.A8
  203. Return p[0] Shl 24
  204. Case Format.I8
  205. Local i:=p[0]
  206. Return UByte($ff) Shl 24 | i Shl 16 | i Shl 8 | i
  207. Case Format.IA16
  208. Local i:=p[1]
  209. Return p[0] Shl 24 | i Shl 16 | i Shl 8 | i
  210. Case Format.RGB24
  211. Return UByte($ff) Shl 24 | p[0] Shl 16 | p[1] Shl 8 | p[2]
  212. Case Format.RGBA32
  213. Return p[3] Shl 24 | p[0] Shl 16 | p[1] Shl 8 | p[2]
  214. Default
  215. Assert( False )
  216. End
  217. Return 0
  218. End
  219. 'Optimize!
  220. '
  221. #rem monkeydoc Clears the pixmap to a given color.
  222. @param color The color to clear the pixmap to.
  223. #end
  224. Method Clear( color:Color )
  225. For Local y:=0 Until _height
  226. For Local x:=0 Until _width
  227. SetPixel( x,y,color )
  228. Next
  229. Next
  230. End
  231. #rem monkeydoc Clears the pixmap to an ARGB color.
  232. @param color ARGB color to clear the pixmap to.
  233. #end
  234. Method ClearARGB( color:UInt )
  235. For Local y:=0 Until _height
  236. For Local x:=0 Until _width
  237. SetPixelARGB( x,y,color )
  238. Next
  239. next
  240. End
  241. #rem monkeydoc Paste a pixmap to the pixmap.
  242. In debug builds, a runtime error will occur if the operation would write to pixels outside of the pixmap.
  243. Note: No alpha blending is performed - pixels in the pixmap are simply overwritten.
  244. @param pixmap The pixmap to paste.
  245. @param x The x coordinate.
  246. @param y The y coordinate.
  247. #end
  248. Method Paste( pixmap:Pixmap,x:Int,y:Int )
  249. DebugAssert( x>=0 And x+pixmap._width<=_width And y>=0 And y+pixmap._height<=_height )
  250. For Local ty:=0 Until pixmap._height
  251. For Local tx:=0 Until pixmap._width
  252. SetPixel( x+tx,y+ty,pixmap.GetPixel( tx,ty ) )
  253. Next
  254. Next
  255. End
  256. 'Optimize!
  257. '
  258. #rem monkeydoc Creates a copy of the pixmap.
  259. @return A new pixmap.
  260. #end
  261. Method Copy:Pixmap()
  262. Return Convert( _format )
  263. End
  264. 'Optimize!
  265. '
  266. #rem monkeydoc Converts the pixmap to a different format.
  267. @param format The pixel format to convert the pixmap to.
  268. @return A new pixmap.
  269. #end
  270. Method Convert:Pixmap( format:PixelFormat )
  271. Local t:=New Pixmap( _width,_height,format )
  272. For Local y:=0 Until _height
  273. For Local x:=0 Until _width
  274. t.SetPixel( x,y,GetPixel( x,y ) )
  275. Next
  276. Next
  277. Return t
  278. End
  279. 'Optimize!
  280. '
  281. #rem monkeydoc Premultiply pixmap r,g,b components by alpha.
  282. #end
  283. Method PremultiplyAlpha()
  284. Select _format
  285. Case PixelFormat.IA16,PixelFormat.RGBA32
  286. For Local y:=0 Until _height
  287. For Local x:=0 Until _width
  288. Local color:=GetPixel( x,y )
  289. color.r*=color.a
  290. color.g*=color.a
  291. color.b*=color.a
  292. SetPixel( x,y,color )
  293. Next
  294. Next
  295. End
  296. End
  297. #rem monkeydoc Flips the pixmap on the Y axis.
  298. #end
  299. Method FlipY()
  300. Local sz:=Width*Depth
  301. Local tmp:=New UByte[sz]
  302. For Local y:=0 Until Height/2
  303. Local p1:=PixelPtr( 0,y )
  304. Local p2:=PixelPtr( 0,Height-1-y )
  305. libc.memcpy( tmp.Data,p1,sz )
  306. libc.memcpy( p1,p2,sz )
  307. libc.memcpy( p2,tmp.Data,sz )
  308. Next
  309. End
  310. #rem monkeydoc Returns a rectangular window into the pixmap.
  311. In debug builds, a runtime error will occur if the rectangle lies outside of the pixmap area.
  312. @param x The x coordinate of the top left of the rectangle.
  313. @param y The y coordinate of the top left of the rectangle.
  314. @param width The width of the rectangle.
  315. @param height The height of the rectangle.
  316. #end
  317. Method Window:Pixmap( x:Int,y:Int,width:Int,height:Int )
  318. DebugAssert( x>=0 And y>=0 And width>=0 And height>=0 And x+width<=_width And y+height<=_height )
  319. Return New Pixmap( width,height,_format,PixelPtr( x,y ),_pitch )
  320. End
  321. #rem monkeydoc Saves the pixmap to a file.
  322. The only save format currently suppoted is PNG.
  323. #End
  324. Method Save:Bool( path:String )
  325. Return SavePixmap( Self,path )
  326. End
  327. #rem monkeydoc Loads a pixmap from a file.
  328. @param path The file path.
  329. @param format The format to load the pixmap in.
  330. @return Null if the file could not be opened, or contained invalid image data.
  331. #end
  332. Function Load:Pixmap( path:String,format:PixelFormat=PixelFormat.Unknown )
  333. Return LoadPixmap( path,format )
  334. End
  335. Private
  336. Field _width:Int
  337. Field _height:Int
  338. Field _format:PixelFormat
  339. Field _depth:Int
  340. Field _data:UByte Ptr
  341. Field _pitch:Int
  342. End