モザイク(ブロック)
基本的にはモザイク処理ですが、モザイク範囲の左上部分の明度を少し高くしてモザイク範囲の右下部分の明度を少し低くする事でブロック(縦横サイズを違うものにすればレンガ)調みたいな画像に加工できます。。。コードが長くてスミマセン。手抜きです。_| ̄|○
private Bitmap effectPixelizationBlock( Bitmap bitmap, int blockFlg ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int i, j, ii, jj; int sizeWidth = 20; int sizeHeight = 10; int sizeMargin = 1; boolean flg = false; if( blockFlg == 1 ){ // 横にずらす for( i = 0; i < height; i += sizeHeight ){ j = 0; if( flg == true ){ j -= sizeWidth / 2; flg = false; } else { flg = true; } for( ; j < width; j += sizeWidth ){ int r, rr, g, gg , b, bb, counts; r = rr = g = gg = b = bb = counts = 0; for( ii = i; ii < ( i + sizeHeight ); ++ii ){ for( jj = j; jj < ( j + sizeWidth ); ++jj ){ if( ii < 0 || height <= ii || jj < 0 || width <= jj ){ continue; } int bitmapColor = pixels[( jj + ii * width )]; rr = Color.red( bitmapColor ); gg = Color.green( bitmapColor ); bb = Color.blue( bitmapColor ); r += rr; g += gg; b += bb; counts++; } } rr = r / counts; gg = g / counts; bb = b / counts; // hsv[0] is Hue [0.0f .. 360.0f] // hsv[1] is Saturation [0.0f...1.0f] // hsv[2] is Value [0.0f...1.0.0f] float[] hsvHighlight = new float[3]; Color.RGBToHSV( rr, gg, bb, hsvHighlight ); hsvHighlight[2] += 0.15f; if( 1 < hsvHighlight[2] ){ hsvHighlight[2] = 1.0f; } float[] hsvShadow = new float[3]; Color.RGBToHSV( rr, gg, bb, hsvShadow ); hsvShadow[2] -= 0.15f; if( hsvShadow[2] < 0 ){ hsvShadow[2] = 0.0f; } int colorHighlight = Color.HSVToColor( hsvHighlight ); int colorShadow = Color.HSVToColor( hsvShadow ); for( ii = i; ii < ( i + sizeHeight ); ++ii ){ for( jj = j; jj < ( j + sizeWidth ); ++jj ){ if( ii < 0 || height <= ii || jj < 0 || width <= jj ){ continue; } int iii = ii - i; int jjj = jj - j; if( ( iii < ( sizeHeight - sizeMargin ) && jjj < sizeMargin ) || ( iii < sizeMargin && jjj < ( sizeWidth - sizeMargin ) ) ){ pixels[( jj + ii * width )] = colorHighlight; } else if( ( ( sizeHeight - sizeMargin ) <= iii && jjj < sizeWidth ) || ( 0 <= iii && ( sizeWidth - sizeMargin ) <= jjj ) ){ pixels[( jj + ii * width )] = colorShadow; } else { pixels[( jj + ii * width )] = Color.rgb( rr, gg, bb ); } } } } } } else if( blockFlg == 2 ){ // 縦にずらす for( i = 0; i < width; i += sizeWidth ){ j = 0; if( flg == true ){ j -= sizeHeight / 2; flg = false; } else { flg = true; } for( ; j < height; j += sizeHeight ){ int r, rr, g, gg , b, bb, counts; r = rr = g = gg = b = bb = counts = 0; for( ii = i; ii < ( i + sizeWidth ); ++ii ){ for( jj = j; jj < ( j + sizeHeight ); ++jj ){ if( ii < 0 || width <= ii || jj < 0 || height <= jj ){ continue; } int bitmapColor = pixels[( ii + jj * width )]; rr = Color.red( bitmapColor ); gg = Color.green( bitmapColor ); bb = Color.blue( bitmapColor ); r += rr; g += gg; b += bb; counts++; } } rr = r / counts; gg = g / counts; bb = b / counts; // hsv[0] is Hue [0.0f .. 360.0f] // hsv[1] is Saturation [0.0f...1.0f] // hsv[2] is Value [0.0f...1.0.0f] float[] hsvHighlight = new float[3]; Color.RGBToHSV( rr, gg, bb, hsvHighlight ); hsvHighlight[2] += 0.15f; if( 1 < hsvHighlight[2] ){ hsvHighlight[2] = 1.0f; } float[] hsvShadow = new float[3]; Color.RGBToHSV( rr, gg, bb, hsvShadow ); hsvShadow[2] -= 0.15f; if( hsvShadow[2] < 0 ){ hsvShadow[2] = 0.0f; } int colorHighlight = Color.HSVToColor( hsvHighlight ); int colorShadow = Color.HSVToColor( hsvShadow ); for( ii = i; ii < ( i + sizeWidth ); ++ii ){ for( jj = j; jj < ( j + sizeHeight ); ++jj ){ if( ii < 0 || width <= ii || jj < 0 || height <= jj ){ continue; } int iii = ii - i; int jjj = jj - j; if( ( iii < ( sizeWidth - sizeMargin ) && jjj < sizeMargin ) || ( iii < sizeMargin && jjj < ( sizeHeight - sizeMargin ) ) ){ pixels[( ii + jj * width )] = colorHighlight; } else if( ( ( sizeWidth - sizeMargin ) <= iii && jjj < sizeHeight ) || ( 0 <= iii && ( sizeHeight - sizeMargin ) <= jjj ) ){ pixels[( ii + jj * width )] = colorShadow; } else { pixels[( ii + jj * width )] = Color.rgb( rr, gg, bb ); } } } } } } else { // ずらさない for( i = 0; i < width; i += sizeWidth ){ for( j = 0; j < height; j += sizeHeight ){ int r, rr, g, gg , b, bb, counts; r = rr = g = gg = b = bb = counts = 0; for( ii = i; ii < ( i + sizeWidth ); ++ii ){ for( jj = j; jj < ( j + sizeHeight ); ++jj ){ if( ii < 0 || width <= ii || jj < 0 || height <= jj ){ continue; } int bitmapColor = pixels[( ii + jj * width )]; rr = Color.red( bitmapColor ); gg = Color.green( bitmapColor ); bb = Color.blue( bitmapColor ); r += rr; g += gg; b += bb; counts++; } } rr = r / counts; gg = g / counts; bb = b / counts; // hsv[0] is Hue [0.0f .. 360.0f] // hsv[1] is Saturation [0.0f...1.0f] // hsv[2] is Value [0.0f...1.0.0f] float[] hsvHighlight = new float[3]; Color.RGBToHSV( rr, gg, bb, hsvHighlight ); hsvHighlight[2] += 0.15f; if( 1 < hsvHighlight[2] ){ hsvHighlight[2] = 1.0f; } float[] hsvShadow = new float[3]; Color.RGBToHSV( rr, gg, bb, hsvShadow ); hsvShadow[2] -= 0.15f; if( hsvShadow[2] < 0 ){ hsvShadow[2] = 0.0f; } int colorHighlight = Color.HSVToColor( hsvHighlight ); int colorShadow = Color.HSVToColor( hsvShadow ); for( ii = i; ii < ( i + sizeWidth ); ++ii ){ for( jj = j; jj < ( j + sizeHeight ); ++jj ){ if( ii < 0 || width <= ii || jj < 0 || height <= jj ){ continue; } int iii = ii - i; int jjj = jj - j; if( ( iii < ( sizeWidth - sizeMargin ) && jjj < sizeMargin ) || ( iii < sizeMargin && jjj < ( sizeHeight - sizeMargin ) ) ){ pixels[( ii + jj * width )] = colorHighlight; } else if( ( ( sizeWidth - sizeMargin ) <= iii && jjj < sizeHeight ) || ( 0 <= iii && ( sizeHeight - sizeMargin ) <= jjj ) ){ pixels[( ii + jj * width )] = colorShadow; } else { pixels[( ii + jj * width )] = Color.rgb( rr, gg, bb ); } } } } } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }
オリジナル:
モザイク(ブロック・縦ずれ)(違いは詳細で見てください):
モザイク(ブロック・横ずれ)(違いは詳細で見てください):
モザイク(ブロック・ずれ無)(違いは詳細で見てください):
モザイク(陰影)
基本的にはモザイク処理ですが、モザイク範囲の端部分に線を引いてデコボコ感やタイル感を強調しています。
private Bitmap effectPixelizationShadow( Bitmap bitmap, int margin ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int i, j, ii, jj; int size = 10; for( i = 0; i < width; i += size ){ for( j = 0; j < height; j += size ){ int r, rr, g, gg , b, bb, counts; r = rr = g = gg = b = bb = counts = 0; for( ii = 0; ii < size; ++ii ){ for( jj = 0; jj < size; ++jj ){ if( ( i + ii ) < 0 || width <= ( i + ii ) || ( j + jj ) < 0 || height <= ( j + jj ) ){ continue; } int bitmapColor = pixels[( ( i + ii ) + ( j + jj ) * width )]; rr = Color.red( bitmapColor ); gg = Color.green( bitmapColor ); bb = Color.blue( bitmapColor ); r += rr; g += gg; b += bb; counts++; } } rr = r / counts; gg = g / counts; bb = b / counts; for( ii = 0; ii < size; ++ii ){ for( jj = 0; jj < size; ++jj ){ if( ( i + ii ) < 0 || width <= ( i + ii ) || ( j + jj ) < 0 || height <= ( j + jj ) ){ continue; } if( ( margin <= jj && ( ii + 1 ) == size ) || ( margin <= ii && ( jj + 1 ) == size ) ){ pixels[( ( i + ii ) + ( j + jj ) * width )] = Color.rgb( 0, 0, 0 ); } else { pixels[( ( i + ii ) + ( j + jj ) * width )] = Color.rgb( rr, gg, bb ); } } } } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }
オリジナル:
モザイク(陰影・全部)(違いは詳細で見てください):
モザイク(陰影・一部)(違いは詳細で見てください):
モザイク
モザイク処理。なんだかドキドキします。
こでは全体を処理しているけど、対象がピックアップできたら該当部分だけモザイク処理をする事もできそう(目だけモザイクが入るとか)。
private Bitmap effectPixelization( Bitmap bitmap ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int i, j, ii, jj; int size = 10; for( i = 0; i < width; i += size ){ for( j = 0; j < height; j += size ){ int r, rr, g, gg , b, bb, counts; r = rr = g = gg = b = bb = counts = 0; for( ii = 0; ii < size; ++ii ){ for( jj = 0; jj < size; ++jj ){ if( ( i + ii ) < 0 || width <= ( i + ii ) || ( j + jj ) < 0 || height <= ( j + jj ) ){ continue; } int bitmapColor = pixels[( ( i + ii ) + ( j + jj ) * width )]; rr = Color.red( bitmapColor ); gg = Color.green( bitmapColor ); bb = Color.blue( bitmapColor ); r += rr; g += gg; b += bb; counts++; } } rr = r / counts; gg = g / counts; bb = b / counts; for( ii = 0; ii < size; ++ii ){ for( jj = 0; jj < size; ++jj ){ if( ( i + ii ) < 0 || width <= ( i + ii ) || ( j + jj ) < 0 || height <= ( j + jj ) ){ continue; } pixels[( ( i + ii ) + ( j + jj ) * width )] = Color.rgb( rr, gg, bb ); } } } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }
すりガラス
すりガラス越しに見ているような画像に加工。
private Bitmap effectDiffuse( Bitmap bitmap ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int radius = 10; Random random = new Random( ); for( int YY = 0; YY < width; ++YY ){ for( int XX = 0; XX < height; ++XX ){ int bitmapColor = pixels[( YY + XX * width )]; int rr = Color.red( bitmapColor ); int gg = Color.green( bitmapColor ); int bb = Color.blue( bitmapColor ); int Y = random.nextInt( radius * 2 ) - radius; int X = random.nextInt( radius * 2 ) - radius; if( ( Y + YY ) < 0 || width <= ( Y + YY ) || ( X + XX ) < 0 || height <= ( X + XX ) ){ continue; } pixels[( ( Y + YY ) + ( X + XX ) * width )] = Color.rgb( rr, gg, bb ); } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }
モーションブラー
動きながら撮影しているような画像に加工する事らしい。
ここでは全体を処理しているけど、対象がピックアップできたら該当部分だけモーションブラー処理をする事もできそう(超高速移動とか)。
private Bitmap effectMotionBlur( Bitmap bitmap ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int i, j; int size = 10, pos; for( i = 0; i < width; ++i ){ for( j = 0; j < height; ++j ){ int r, rr, g, gg , b, bb, counts; r = rr = g = gg = b = bb = counts = 0; for( pos = -size; pos <= size; pos++ ){ if( ( j + pos ) < 0 || height <= ( j + pos ) || ( i + pos ) < 0 || width <= ( i + pos ) ){ continue; } int bitmapColor = pixels[( ( i + pos ) + ( j + pos ) * width )]; rr = Color.red( bitmapColor ); gg = Color.green( bitmapColor ); bb = Color.blue( bitmapColor ); r += rr; g += gg; b += bb; counts++; } rr = r / counts; gg = g / counts; bb = b / counts; pixels[( i + j * width )] = Color.rgb( rr, gg, bb ); } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }
ぼかし
トイカメラ風の画像を加工する工程の中で既に出てきていますが(サンプル画像はコントラスト等を調整しているので)ぼかし処理だけを入れた場合の画像。
private Bitmap effectShadeing( Bitmap bitmap, int range ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int i, j, ii, jj; int pixel = 3; for( i = 0; i < width; ++i ){ for( j = 0; j < height; ++j ){ int r, g, b; float sumR, sumG, sumB; sumR = 0.0f; sumG = 0.0f; sumB = 0.0f; for( ii = -pixel; ii <= pixel; ii++ ){ for( jj = -pixel; jj <= pixel; jj++ ){ if( ( i + ii ) < 0 || width <= ( i + ii ) || ( j + jj ) < 0 || height <= ( j + jj ) ){ continue; } int bitmapColor = pixels[( ( i + ii ) + ( j + jj ) * width )]; r = Color.red( bitmapColor ); g = Color.green( bitmapColor ); b = Color.blue( bitmapColor ); sumR += (float)r; sumG += (float)g; sumB += (float)b; } } int rr, gg, bb; rr = (int)( sumR / Math.pow( ( 1 + ( 2 * pixel ) ), 2 ) ); gg = (int)( sumG / Math.pow( ( 1 + ( 2 * pixel ) ), 2 ) ); bb = (int)( sumB / Math.pow( ( 1 + ( 2 * pixel ) ), 2 ) ); if( range <= 0 || !( i < ( ( width / 2 ) + range ) && ( ( width / 2 ) - range ) < i && j < ( ( height / 2 ) + range ) && ( ( height / 2 ) - range ) < j ) ){ pixels[( i + j * width )] = Color.rgb( rr, gg, bb ); } } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }
ノイズ除去
縦横斜め前後の情報を取得。で、ソートした後に真ん中の値を採用。。。という事らしい。
private Bitmap effectMedianFilter( Bitmap bitmap ){ if( bitmap == null ){ bitmap = BitmapFactory.decodeResource( getResources( ), R.drawable.original ).copy( Bitmap.Config.ARGB_8888, true ); } if( bitmap == null ){ return bitmap; } if( bitmap.isMutable( ) != true ){ bitmap = bitmap.copy( Bitmap.Config.ARGB_8888, true ); } int height = bitmap.getHeight( ); int width = bitmap.getWidth( ); int[] pixels = new int[( width * height )]; bitmap.getPixels( pixels, 0, width, 0, 0, width, height ); int maxFiter = 9; int fiterCount = 0; int[] filter = new int[maxFiter]; for( int YY = 0; YY < width; ++YY ){ for( int XX = 0; XX < height; ++XX ){ fiterCount = 0; for( int X = fiterCount = 0; X < maxFiter; ++X ){ filter[X] = 2147483647; } for( int Y = -1; Y <= 1; ++Y ){ for( int X = -1; X <= 1; ++X ){ if( ( Y + YY ) < 0 || width <= ( Y + YY ) || ( X + XX ) < 0 || height <= ( X + XX ) ){ continue; } filter[fiterCount] = pixels[( ( Y + YY ) + ( X + XX ) * width )]; ++fiterCount; } } if( fiterCount > 0 ){ Arrays.sort( filter ); int bitmapColor = filter[( fiterCount / 2 )]; int rr = Color.red( bitmapColor ); int gg = Color.green( bitmapColor ); int bb = Color.blue( bitmapColor ); pixels[( YY + XX * width )] = Color.rgb( rr, gg, bb ); } } } bitmap.setPixels( pixels, 0, width, 0, 0, width, height ); return bitmap; }