最近做音视频项目中的色度抠图功能,用吸管进行当前帧取色,然后进行强度和阴影调节进行取色,具体效果可查看剪映的色度抠图功能。
这篇文章就讲述了如何对视频当前帧的某个位置进行取色。
首先需要获取视频对应的当前帧:
/**
* 获取当前帧对应的Bitmap
*
* @param clip 媒体片段对象
* @param position 当前位置
* @return
*/
private Bitmap getCurrentBitmap(MediaClip clip, long position) {
File file = new File(clip.getFilePath());
if (!file.exists()) return null;
if (clip.isVideo()) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(file.getAbsolutePath());
return retriever.getFrameAtTime(position, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
} else {
return BitmapFactory.decodeFile(file.getAbsolutePath());
}
}
然后从获取到的Bitmap上取触摸位置的颜色:
/**
* 从Bitmap指定点获取颜色
*
* @param bitmap 源图
* @param wRatio 水平方向位置在整个帧图位置上的比例
* @param hRatio 垂直方向位置在整个帧图位置上的比例
* @return
*/
public int getColorFromBitmap(Bitmap bitmap, float wRatio, float hRatio) {
if (bitmap == null || bitmap.isRecycled()) {
return 0;
}
Rect sampleRect = new Rect();
final int sampleWidth = 10;
final int sampleHeight = 10;
sampleRect.left = (int) (bitmap.getWidth() * wRatio);
if (sampleRect.left < sampleWidth / 2) {
sampleRect.left = 0;
} else if (sampleRect.left + sampleWidth > bitmap.getWidth()) {
sampleRect.left = bitmap.getWidth() - sampleWidth;
} else {
sampleRect.left = sampleRect.left - sampleWidth / 2;
}
sampleRect.top = (int) (bitmap.getHeight() * hRatio);
if (sampleRect.top < sampleHeight / 2) {
sampleRect.top = 0;
} else if (sampleRect.top + sampleHeight > bitmap.getHeight()) {
sampleRect.top = bitmap.getHeight() - sampleHeight;
} else {
sampleRect.top = sampleRect.top - sampleHeight / 2;
}
sampleRect.right = sampleRect.left + sampleWidth;
sampleRect.bottom = sampleRect.top + sampleHeight;
int[] pixels = new int[sampleWidth * sampleHeight];
bitmap.getPixels(pixels, 0, sampleWidth, sampleRect.left, sampleRect.top, sampleWidth, sampleHeight);
float a = 0;
float r = 0;
float g = 0;
float b = 0;
for (int px : pixels) {
a = a + Color.alpha(px);
r = r + Color.red(px);
g = g + Color.green(px);
b = b + Color.blue(px);
}
a = 1;
r = r / pixels.length / 256;
g = g / pixels.length / 256;
b = b / pixels.length / 256;
return Color.argb(a, r, g, b);
}
主要方法:public void getPixels(@ColorInt int[] pixels, int offset, int stride,
int x, int y, int width, int height)
引申方法:public void copyPixelsToBuffer(Buffer dst)
感谢大家的支持,如有错误请指正,如需转载请标明原文出处!