/Visual Studio 2008/CSSL3WriteableBitmap/ReadMe.html

# · HTML · 353 lines · 348 code · 5 blank · 0 comment · 0 complexity · b57b8dc8a41e56145cf435c2851dda8c MD5 · raw file

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta content="zh-cn" http-equiv="Content-Language" />
  5. <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
  6. <title>Working with Silverlight Writeab</title>
  7. <style type="text/css">
  8. h1 {
  9. color: #FF0000;
  10. }
  11. h2 {
  12. color: #3399FF;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <h1>Working with Silverlight WriteableBitmap</h1>
  18. <h2>Introduction</h2>
  19. <p>WriteableBitmap is a new feature in Silverlight 3. It allows you to work with
  20. raw pixel data of a bitmap image. This enables a lot of useful scenarios.
  21. However, due to the limitation in the security sandbox (for example, unable to
  22. write unsafe code that uses pointers), you may need to write more code compared
  23. to a similar desktop application.</p>
  24. <p>This sample contains 3 sub samples which demonstrate some common tasks when
  25. working with WriteableBitmap:</p>
  26. <ul>
  27. <li>The gun shoot sample. It allows you to select two images of different
  28. size, scales them to the same resolution, and puts one on top of the other.
  29. When you click the top image to fire some bullets, a gun mark will be
  30. created, and you&#39;ll be able to see through the bottom image. This sample
  31. demonstrates how to scale a source image to a specific resolution (800 * 600
  32. in this case), as well as how to modify individual pixels.</li>
  33. <li>The fill color sample. It implements a common feature in painting
  34. programmers: Fill an area with a solid color. It demonstrates how to apply
  35. common algorithms to Silverlight WriteableBitmap, as well as how to avoid
  36. stack overflow in very deep recursive methods by simulating the way CLR
  37. invokes methods.</li>
  38. <li>The screenshot sample. It demonstrates another feature of
  39. WriteableBitmap: Create bitmap screenshots from either bitmap or non-bitmap
  40. elements. It allows you to save the result to a bmp file. It also
  41. demonstrates the limitation of the screenshot feature.</li>
  42. </ul>
  43. <p>To work with WriteableBitmap in any advanced scenarios, solid foundation of
  44. computer graphics is required. You should at least understand how bitmap is
  45. stored in memory, the essential concepts related to pixels and colors, and how
  46. to work with bitwise shift operations to improve performance.</p>
  47. <h2>Important: When to use WriteableBitmap, and when not</h2>
  48. <p>Traditionally, it may be attempted to use some CPU based solutions similar to
  49. WriteableBitmap whenever you need to modify a pixel on the screen. However,
  50. these days we have much better GPU based solutions. For example: The mighty
  51. shader effect. Keep in mind that when using WriteableBitmap, all jobs are
  52. performed on the CPU, and if you need to do the job on each pixel, you will have
  53. to do them pixel by pixel. Even if you create multiple threads, you can process
  54. at least 4 pixels at one time on a quad-core CPU. GPU, on the other hand, can
  55. process all pixels in parallel, no matter how many pixels the scenario contains.
  56. Also, in most scenarios, it is much easier to write HLSL compared to a CPU based
  57. algorithm, because you can think with a single pixel rather than find where the
  58. pixel is, get its color in an integer value, extract the ARGB information using
  59. bitwise shift operations, and so on. So it is recommended to use shader effect
  60. whenever possible.</p>
  61. <p>However, shader effects do have limitations:</p>
  62. <ul>
  63. <li>Silverlight 3 supports pixel shader only. No vertex shader and geometry
  64. shader. Without geometry shader, you cannot create GPU primitives
  65. dynamically in your HLSL program.</li>
  66. <li>Silverlight 3 supports shader 2.0 only (while Direct 3D 11 supports
  67. shader 5.0). There&#39;re a lot of limitations in shader 2.0 due to the
  68. limitation of GPU at that time. For example, up to 64 arithmetic instructions may be given in a HLSL program, limited numbers of GPU
  69. registries can be used, and so on. Keep in mind GPU does not support loop.
  70. So when compiling HLSL, all loops will be expanded. That will introduce more
  71. arithmetic instructions than you may expect. Silverlight needs to support
  72. low end GPUs (in contrast to Direct 3D). That&#39;s why shader 2.0 is chosen.</li>
  73. <li>Some features are just difficult to be written in shader effect. For
  74. example, one pixel&#39;s processing relies on another pixel&#39;s result. Shader
  75. effects are usually used to perform the same operation to all pixels. Of
  76. course, you can pass different parameters to achieve different results.
  77. Think of a swirl effect. All pixels are performed using the same algorithm,
  78. just the angle parameter is different. So shader effect can be used.
  79. However, if you want to fill an area with a solid color, or maybe even
  80. gradient, it can be very difficult to do with shader effect.</li>
  81. </ul>
  82. <p>So use WriteableBitmap when:</p>
  83. <ul>
  84. <li>Your algorithm is too complex for a shader 2.0 program.</li>
  85. <li>You have to support extremely low end computers where even shader 2.0 is
  86. not supported (in this case, CPU&#39;s SSE instructions set will be used if you
  87. choose shader effect, whose performance is not ideal).</li>
  88. <li>In your algorithm, one pixel&#39;s processing relies on another pixel&#39;s
  89. result.</li>
  90. </ul>
  91. <h2>Difference between Silverlight and WPF&#39;s WriteableBitmap</h2>
  92. <p>While this sample targets Silverlight, you may want to port it to WPF. You
  93. must be aware of some key differences between Silverlight and WPF&#39;s
  94. WriteableBitmap:</p>
  95. <ul>
  96. <li>Silverlight doesn&#39;t allow you to write unsafe code that uses pointers,
  97. while you will have to write unsafe code when working with WPF
  98. WriteableBitmap.</li>
  99. <li>Silverlight exposes a Pixels property whose type is int[], while WPF
  100. exposes a BackBuffer property which is a pointer (convert it to a byte*) to
  101. the pixels&#39; data.</li>
  102. <li>In Silverlight, since the pixel&#39;s color is of type int, you will have to
  103. use bitwise shift operations to extract ARGB information (you can use other
  104. solutions, but they&#39;re slow). In WPF, you can control the pointer to point
  105. to whatever position you like. For example, point to A, and then to R with
  106. pointer++.</li>
  107. <li>Silverlight&#39;s WriteableBitmap supports Pbgra32 format only, so the back
  108. buffer stride is always pixel width * 4. WPF supports a lot of formats. So
  109. you need to get the back buffer stride from the BackBufferStride property.</li>
  110. <li>In WPF, you need to wrap the write operation in a Lock and Unlock pair,
  111. while in Silverlight this is not required.</li>
  112. <li>WPF allows you to use PLINQ to work with multi-core CPUs without
  113. worrying about threads, while in Silverlight you have to implement your own
  114. if you want to take advantage of multi-core CPUs.</li>
  115. </ul>
  116. <p>So, if you want to convert the following Silverlight code (extracted from the
  117. fill color sample) to WPF,</p>
  118. <p align="left" class="MsoNormal">
  119. <span lang="EN-US" style="font-size:9.0pt;font-family:
  120. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  121. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  122. </span><span style="color:green">//Start from the clicked point.<o:p></o:p></span></span></p>
  123. <p align="left" class="MsoNormal">
  124. <span lang="EN-US" style="font-size:9.0pt;font-family:
  125. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  126. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  127. </span><span style="color:#2B91AF">Point</span> clickedPoint =
  128. e.GetPosition(img);<o:p></o:p></span></p>
  129. <p align="left" class="MsoNormal">
  130. <span lang="EN-US" style="font-size:9.0pt;font-family:
  131. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  132. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  133. </span><span style="color:green">//The position of the clicked point in the
  134. pixel array.<o:p></o:p></span></span></p>
  135. <p align="left" class="MsoNormal">
  136. <span lang="EN-US" style="font-size:9.0pt;font-family:
  137. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  138. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  139. </span><span style="color:blue">int</span> clickedColorPosition = bmp.PixelWidth
  140. * (<span style="color:blue">int</span>)clickedPoint.Y + (<span style="color:blue">int</span>)clickedPoint.X;<o:p></o:p></span></p>
  141. <p align="left" class="MsoNormal">
  142. <span lang="EN-US" style="font-size:9.0pt;font-family:
  143. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  144. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  145. </span><span style="color:green">//The color of the clicked point.<o:p></o:p></span></span></p>
  146. <p align="left" class="MsoNormal">
  147. <span lang="EN-US" style="font-size:9.0pt;font-family:
  148. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  149. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  150. </span><span style="color:blue">int</span> clickedColor =
  151. bmp.Pixels[clickedColorPosition];<o:p></o:p></span></p>
  152. <p>you will need to write:</p>
  153. <p align="left" class="MsoNormal">
  154. <span lang="EN-US" style="font-size:9.0pt;font-family:
  155. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  156. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  157. </span>bmp.Lock();<o:p></o:p></span></p>
  158. <p align="left" class="MsoNormal">
  159. <span lang="EN-US" style="font-size:9.0pt;font-family:
  160. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  161. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  162. </span><span style="color:green">//</span></span><span style="color:green"><span style="font-size:9.0pt;font-family:
  163. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  164. mso-font-kerning:0pt;mso-no-proof:yes">The start position in the back buffer.</span></span></p>
  165. <p align="left" class="MsoNormal">
  166. <span lang="EN-US" style="font-size:9.0pt;font-family:
  167. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  168. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  169. </span><span style="color:blue">byte</span>* start = (<span style="color:blue">byte</span>*)bmp.BackBuffer.ToPointer();<o:p></o:p></span></p>
  170. <p align="left" class="MsoNormal">
  171. <span lang="EN-US" style="font-size:9.0pt;font-family:
  172. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  173. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  174. </span><span style="color:green">//<span lang="EN-US" style="font-size: 9.0pt; font-family: 新宋体; mso-hansi-font-family: &quot;Times New Roman&quot;; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-font-kerning: 0pt; mso-no-proof: yes"><span style="color: green">Start
  175. from the clicked point.<o:p></o:p></span></span></span></span></p>
  176. <p align="left" class="MsoNormal">
  177. <span lang="EN-US" style="font-size:9.0pt;font-family:
  178. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  179. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  180. </span><span style="color:#2B91AF">Point</span> c</span><span style="font-size:9.0pt;font-family:
  181. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  182. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  183. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  184. mso-font-kerning:0pt;mso-no-proof:yes">Point = e.GetPosition(img);<o:p></o:p></span></p>
  185. <p align="left" class="MsoNormal">
  186. <span lang="EN-US" style="font-size:9.0pt;font-family:
  187. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  188. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  189. </span><span style="color:green">//</span></span><span style="color:green"><span style="font-size:9.0pt;font-family:
  190. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  191. mso-font-kerning:0pt;mso-no-proof:yes">Get how many bytes a pixel occupies.</span></span></p>
  192. <p align="left" class="MsoNormal">
  193. <span lang="EN-US" style="font-size:9.0pt;font-family:
  194. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  195. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  196. </span><span style="color:blue">int</span> bytesPerPixel = bmp.BackBufferStride
  197. / bmp.PixelWidth;<o:p></o:p></span></p>
  198. <p align="left" class="MsoNormal">
  199. <span lang="EN-US" style="font-size:9.0pt;font-family:
  200. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  201. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  202. </span><span style="color:green">//</span></span><span lang="EN-US" style="font-size: 9.0pt; font-family: 新宋体; mso-hansi-font-family: &quot;Times New Roman&quot;; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-font-kerning: 0pt; mso-no-proof: yes"><span style="color: green">The
  203. position of the clicked point in the pixel array.<o:p></o:p></span></span></p>
  204. <p align="left" class="MsoNormal">
  205. <span lang="EN-US" style="font-size:9.0pt;font-family:
  206. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  207. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  208. </span><span style="color:blue">byte</span>* c</span><span style="font-size:9.0pt;font-family:
  209. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  210. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  211. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  212. mso-font-kerning:0pt;mso-no-proof:yes">Color</span><span style="font-size:9.0pt;font-family:
  213. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  214. mso-font-kerning:0pt;mso-no-proof:yes">Position</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  215. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  216. mso-font-kerning:0pt;mso-no-proof:yes"> = start + (<span style="color:blue">int</span>)c</span><span style="font-size:9.0pt;font-family:
  217. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  218. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  219. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  220. mso-font-kerning:0pt;mso-no-proof:yes">Point.X
  221. * bytesPerPixel + bmp.BackBufferStride * (<span style="color:blue">int</span>)c</span><span style="font-size:9.0pt;font-family:
  222. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  223. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  224. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  225. mso-font-kerning:0pt;mso-no-proof:yes">Point.Y;<o:p></o:p></span></p>
  226. <p align="left" class="MsoNormal">
  227. <span lang="EN-US" style="font-size:9.0pt;font-family:
  228. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  229. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  230. </span><span style="color:green">//<span lang="EN-US" style="font-size: 9.0pt; font-family: 新宋体; mso-hansi-font-family: &quot;Times New Roman&quot;; mso-bidi-font-family: &quot;Times New Roman&quot;; mso-font-kerning: 0pt; mso-no-proof: yes"><span style="color: green">The
  231. color of the clicked point.<o:p></o:p></span></span></span></span></p>
  232. <p align="left" class="MsoNormal">
  233. <span lang="EN-US" style="font-size:9.0pt;font-family:
  234. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  235. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  236. </span><span style="color:blue">byte</span>[] c</span><span style="font-size:9.0pt;font-family:
  237. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  238. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  239. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  240. mso-font-kerning:0pt;mso-no-proof:yes">Color =
  241. <span style="color:blue">new</span> <span style="color:blue">byte</span>[bytesPerPixel];<o:p></o:p></span></p>
  242. <p align="left" class="MsoNormal">
  243. <span lang="EN-US" style="font-size:9.0pt;font-family:
  244. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  245. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  246. </span><span style="color:blue">for</span> (<span style="color:blue">int</span>
  247. i = 0; i &lt; bytesPerPixel; i++)<o:p></o:p></span></p>
  248. <p align="left" class="MsoNormal">
  249. <span lang="EN-US" style="font-size:9.0pt;font-family:
  250. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  251. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  252. </span>{<o:p></o:p></span></p>
  253. <p align="left" class="MsoNormal">
  254. <span lang="EN-US" style="font-size:9.0pt;font-family:
  255. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  256. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:4">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  257. </span>c</span><span style="font-size:9.0pt;font-family:
  258. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  259. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  260. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  261. mso-font-kerning:0pt;mso-no-proof:yes">Color[i] = c</span><span style="font-size:9.0pt;font-family:
  262. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  263. mso-font-kerning:0pt;mso-no-proof:yes">licked</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  264. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  265. mso-font-kerning:0pt;mso-no-proof:yes">Color</span><span style="font-size:9.0pt;font-family:
  266. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  267. mso-font-kerning:0pt;mso-no-proof:yes">Position</span><span lang="EN-US" style="font-size:9.0pt;font-family:
  268. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  269. mso-font-kerning:0pt;mso-no-proof:yes">[i];<o:p></o:p></span></p>
  270. <p align="left" class="MsoNormal">
  271. <span lang="EN-US" style="font-size:9.0pt;font-family:
  272. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  273. mso-font-kerning:0pt;mso-no-proof:yes"><span style="mso-tab-count:3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
  274. </span>}</span><o:p></o:p><br/><o:p>//Other operations.</o:p>
  275. <span style="font-size:9.0pt;font-family:
  276. 新宋体;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
  277. mso-font-kerning:0pt;mso-no-proof:yes">
  278. <br/><o:p>bmp.Unlock();</o:p></span>
  279. <p>&nbsp;</p>
  280. <p>In the future, we may also write WPF WriteableBitmap samples.</p>
  281. <h2>Walkthrough of each sample</h2>
  282. <h3>Gun shoot</h3>
  283. <p>When you select 2 bitmap images, 2 WriteableBitmaps will be created and
  284. stored in memory. Since the images&#39; size may be different, we need to convert
  285. them to the same resolution. This is done by calculate a ratio and then
  286. multiplies each pixel&#39;s position with the ratio. For example, if we need to
  287. convert a 1600*1200 image to 800*600, we simply multiplies each pixel&#39;s position
  288. with 0.5</p>
  289. <p>After the WriteableBitmaps are created, we set the source of the Image
  290. Control to the top one, and the source images are no longer needed.</p>
  291. <p>When you click on the image, the program calculates a circle whose radius is
  292. 50. It also calculates the rectangle bound of the circle so we don&#39;t need to
  293. walkthrough all pixels. Then for each pixel in the bound, if it is in the
  294. radius, we paint the pixel with the color in the bottom image at the same
  295. position. So you will be able to see through the bottom image at this pixel. We
  296. also draw a gun mark at the edge of the circle. This demonstrates how to extract
  297. the ARGB values, and how to modify them.</p>
  298. <p>Finally, do not forget you must once again set the Image Control&#39;s Source
  299. property to the WriteableBitmap, or it won&#39;t be updated.</p>
  300. <h3>Fill color</h3>
  301. <p>This samples implements a very simple version of edge detection algorithm:
  302. The growth method. It starts from the clicked point. If the clicked point&#39;s
  303. color is the same as the filling color, then terminates the algorithm. Otherwise
  304. extract the left, right, top, and bottom pixels (grow to the 4 pixels). If the
  305. color is different from the clicked pixel, then we need to fill this pixel with
  306. the filling color. And then we grow the graph to the left, right, top, and
  307. bottom pixels of the new pixel.</p>
  308. <p>If you have a very large area to be filled, you may soon get into stack
  309. overflow due to a very deep recursive. To avoid this, we can try to put the
  310. recursive body inside a normal loop, and manually simulate the way CLR invokes a
  311. method. To do so, first we need a stack. The number of elements inside the stack
  312. represents the number of the method needs to be invoked. The data inside the
  313. stack is the method&#39;s parameter. Now whenever we need to invoke the recursive
  314. method, we instead populates a parameter data, and push it to the stack. When
  315. the recursive body is executed, we pop the stack to get the parameter of this
  316. recursion. Once there&#39;s no data in the stack, it means the recursive method has
  317. finally completed, so we can exit the loop.</p>
  318. <p>If you want to provide your own image for this sample, please choose images
  319. with large areas that can be filled. Also be aware of anti-aliased images. The
  320. sample&#39;s implementation of the algorithm is simple, and do not take
  321. anti-aliasing into account. For example, it may be difficult to see the
  322. difference between 0xfffffffe and 0xffffffff, but the algorithm thinks the two
  323. pixels have different color.</p>
  324. <h3>Screenshot</h3>
  325. <p>In this sample, you will see two rectangles. The above one is a vector
  326. graphic that is wrapped in a Canvas, and the below one is a bitmap that is
  327. captured from the above rectangle from time to time. It is very easy to use the
  328. screenshot feature of WriteableBitmap. Just provide a UIElement and its
  329. transform to the constructor. However, as demonstrated in this sample, there&#39;re
  330. some limitations.</p>
  331. <p>Supported features:</p>
  332. <ul>
  333. <li>The current value in the animation.</li>
  334. <li>RenderTransform.</li>
  335. <li>Shader Effects.</li>
  336. </ul>
  337. <p>Unsupported features:</p>
  338. <ul>
  339. <li>Projection.</li>
  340. <li>Non-UIElement, such as html elements.</li>
  341. </ul>
  342. <p>So be aware if you want to use WriteableBitmap to capture screenshots because
  343. projection will be lost.</p>
  344. <p>This sample also implements a bmp encoder to allow you to save the result to
  345. a bmp file. Silverlight doesn&#39;t ship the various bitmap encoders out of box. So
  346. you will have to implement your own if you need.</p>
  347. </body>
  348. </html>