root/as3/SeamCarving/src/org/libspark/display/SeamCarving.as

リビジョン 132, 5.3 kB (コミッタ: yossy, コミット時期: 2 年 前)

Moved.

Line 
1 /**
2 * An implementation of seam carving.
3 * Algorithm by Shai Avidan, Ariel Shamir
4 * Seam Carving for Content-Aware Image Resizing
5 * ACM SIGGRAPH 2007
6 * http://www.faculty.idc.ac.il/arik/
7 *
8 * ネタです。
9 * shrinkWidth に非常に時間がかかります。
10 * 適当実装なので高速化しようとしたんですが、
11 * すでにやられてしまったようです。
12 * http://www.quasimondo.com/archives/000652.php
13 *
14 * @author rch850
15 */
16
17 package org.libspark.display {
18         import flash.display.BitmapData;
19
20         public class SeamCarving {
21                 /**
22                 * Shrinks the width of bitmap.
23                 * ビットマップの幅を縮めます。
24                 * @param        bitmap
25                 */
26                 static public function shrinkWidth(bitmap:BitmapData):void {
27                         var energy:BitmapData = createEnergy(bitmap);
28                         var energySum:BitmapData = createEnergySum(energy);
29                        
30                         var xo:int;
31                         var emin:int = int.MAX_VALUE;
32                         var w:int = energySum.width;
33                         var h:int = energySum.height;
34                        
35                         bitmap.lock();
36                        
37                         // Find the x coordinate of bottom of the seam.
38                         (function():void{
39                                 for (var x:int = 0; x < w; ++x) {
40                                         var e:int = energySum.getPixel(x, h - 1);
41                                         if (e < emin) {
42                                                 emin = e;
43                                                 xo = x;
44                                         }
45                                 }
46                         })();
47                        
48                         // Shrink bottom line.
49                         (function():void{
50                                 for (var x:int = xo; x < w - 1; ++x) {
51                                         bitmap.setPixel(x, h - 1, bitmap.getPixel(x + 1, h - 1));
52                                 }
53                                 bitmap.setPixel(w - 1, h - 1, 0);
54                         })();
55                        
56                         var DX:Array = [-1, 0, 1];
57                        
58                         // Shrink each lines from bottom to top.
59                         (function():void{
60                                 var x:int, y:int;
61                                
62                                 for (y = h - 2; y >= 0; --y) {
63                                         emin = int.MAX_VALUE;
64                                         var xoo:int = xo;
65                                         for (var i:int = 0; i < 3; ++i) {
66                                                 x = xoo + DX[i];
67                                                 if (x < 0 || w - 1 < x) {
68                                                         continue;
69                                                 }
70                                                
71                                                 var e:int = energySum.getPixel(x, y);
72                                                 if (e < emin) {
73                                                         emin = e;
74                                                         xo = x;
75                                                 }
76                                         }
77                                        
78                                         for (x = xo; x < w - 1; ++x) {
79                                                 bitmap.setPixel(x, y, bitmap.getPixel(x + 1, y));
80                                         }
81                                         bitmap.setPixel(w - 1, y, 0);
82                                 }
83                         })();
84                        
85                         bitmap.unlock();
86                 }
87                
88                 /**
89                 * Returns Bitmap which describes an energy distribution of bitmap.
90                 * bitmap のエネルギー分布を表す Bitmap を返します。
91                 * @param        bitmap
92                 * @return       Bitmap which describes an energy distribution of bitmap.
93                 */
94                 static public function createEnergy(bitmap:BitmapData):BitmapData {
95                         var width:int = bitmap.width;
96                         var height:int = bitmap.height;
97                         var energy:BitmapData = new BitmapData(width, height);
98                        
99                         energy.lock();
100                         for (var y:int = 0; y < height; ++y) {
101                                 for (var x:int = 0; x < width; ++x) {
102                                         energy.setPixel(x, y, getEnergy(bitmap, x, y));
103                                 }
104                         }
105                         energy.unlock();
106                        
107                         return energy;
108                 }
109                
110                 /**
111                 * Returns an energy value at position (x, y) of bitmap.
112                 * bitmap 上の座標 (x, y) が持つエネルギーを返します。
113                 * @param        bitmap
114                 * @param        x
115                 * @param        y
116                 * @return
117                 */
118                 static public function getEnergy(bitmap:BitmapData, x:int, y:int):int {
119                         // Black is a special case.
120                         if (bitmap.getPixel(x, y) == 0) {
121                                 return 100000;
122                         }
123                        
124                         var DX:Array = [-1,  0,  1,  0];
125                         var DY:Array = [ 0, -1,  0,  1];
126                         var w:int = bitmap.width;
127                         var h:int = bitmap.height;
128                         var sum:int = 0;
129                         var num:int = 0;
130                         var center:int = getBrightness(bitmap.getPixel(x, y));
131                        
132                         for (var i:int = 0; i < 4; ++i) {
133                                 var u:int = x + DX[i];
134                                 var v:int = y + DY[i];
135                                 if (u < 0 || w - 1 < u || v < 0 || h - 1 < v) {
136                                         continue;
137                                 }
138                                 var neighbor:int = getBrightness(bitmap.getPixel(u, v));
139                                 sum += int(Math.abs(center - neighbor));
140                                 ++num;
141                         }
142                         if (num > 0) {
143                                 sum /= num;
144                         }
145                         return sum;
146                 }
147                
148                 /**
149                 * Returns a brightness value computed from rgb argument.
150                 * RGB 値から明るさを算出して返します。
151                 * @param        rgb
152                 * @return       brightness of rgb value.
153                 */
154                 static public function getBrightness(rgb:int):int {
155                         var r:int = (rgb >> 16) & 0xFF;
156                         var g:int = (rgb >> 8) & 0xFF;
157                         var b:int = rgb & 0xFF;
158                         return int(0.299 * r + 0.587 * g + 0.114 * b);
159                 }
160                
161                 /**
162                 * Returns Bitmap which describes summations of energies.
163                 * @param        energy
164                 * @return
165                 */
166                 static public function createEnergySum(energy:BitmapData):BitmapData {
167                         var w:int = energy.width;
168                         var h:int = energy.height;
169                         var sum:BitmapData = new BitmapData(w, h);
170                        
171                         sum.lock();
172                         for (var y:int = 0; y < h; ++y) {
173                                 for (var x:int = 0; x < w; ++x) {
174                                         sum.setPixel(x, y, getEnergySum(sum, energy, x, y));
175                                 }
176                         }
177                         sum.unlock();
178                        
179                         return sum;
180                 }
181                
182                 /**
183                 * Returns summation of energies at (x, y).
184                 * @param        sum
185                 * @param        energy
186                 * @param        x
187                 * @param        y
188                 * @return       Summation of energies.
189                 */
190                 static public function getEnergySum(sum:BitmapData, energy:BitmapData, x:int, y:int):int {
191                         if (y == 0) {
192                                 return energy.getPixel(x, y);
193                         }
194                        
195                         var DX:Array = [-1, 0, 1];
196                         var w:int = energy.width;
197                         var emin:int = 1000;
198                        
199                         for (var i:int = 0; i < 3; ++i) {
200                                 var u:int = x + DX[i];
201                                 var v:int = y - 1;
202                                 if (u < 0 || w - 1 < u) {
203                                         continue;
204                                 }
205                                
206                                 var e:int = sum.getPixel(u, v);
207                                 if (e < emin) {
208                                         emin = e;
209                                 }
210                         }
211                        
212                         return emin + energy.getPixel(x, y);
213                 }
214         }
215        
216 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。