From 73004fe84d41e35136ea814cc0cf1008f96f01f0 Mon Sep 17 00:00:00 2001 From: xiaowusky Date: Mon, 15 May 2023 16:08:37 +0800 Subject: [PATCH] =?UTF-8?q?desc:java=E4=BB=A3=E7=A0=81=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B0=B4=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/easydarwin/push/MediaStream.java | 4 + .../java/org/easydarwin/sw/TxtOverlay.java | 47 ++++++++--- .../java/org/easydarwin/util/YUVUtils.java | 73 ++++++++++++++++++ .../main/res/drawable-hdpi/float_button.png | Bin 0 -> 7663 bytes 4 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 library/src/main/java/org/easydarwin/util/YUVUtils.java create mode 100644 library/src/main/res/drawable-hdpi/float_button.png diff --git a/library/src/main/java/org/easydarwin/push/MediaStream.java b/library/src/main/java/org/easydarwin/push/MediaStream.java index 59a5a93..ef9a3dd 100644 --- a/library/src/main/java/org/easydarwin/push/MediaStream.java +++ b/library/src/main/java/org/easydarwin/push/MediaStream.java @@ -404,6 +404,9 @@ public class MediaStream extends Service implements LifecycleObserver { public void onPreviewFrame2(byte[] data, Object camera) { if (camera instanceof Camera) { + if (PreferenceManager.getDefaultSharedPreferences(mApplicationContext).getBoolean("key_enable_video_overlay", true)) { + overlay.javaOverlay(data, "EasyPusher"); + } if (mDgree == 0) { Camera.CameraInfo camInfo = new Camera.CameraInfo(); Camera.getCameraInfo(mCameraId, camInfo); @@ -425,6 +428,7 @@ public class MediaStream extends Service implements LifecycleObserver { if (PreferenceManager.getDefaultSharedPreferences(mApplicationContext).getBoolean("key_enable_video_overlay", true)) { String txt;// = String.format("drawtext=fontfile=" + mApplicationContext.getFileStreamPath("SIMYOU.ttf") + ": text='%s%s':x=(w-text_w)/2:y=H-60 :fontcolor=white :box=1:boxcolor=0x00000000@0.3", "EasyPusher", new SimpleDateFormat("yyyy-MM-ddHHmmss").format(new Date())); txt = "EasyPusher " + new SimpleDateFormat("yy-MM-dd HH:mm:ss SSS").format(new Date()); + overlay.javaOverlay(data, txt); overlay.overlay(data, txt); } mVC.onVideo(data, NV21); diff --git a/library/src/main/java/org/easydarwin/sw/TxtOverlay.java b/library/src/main/java/org/easydarwin/sw/TxtOverlay.java index bac0708..39cb5ce 100644 --- a/library/src/main/java/org/easydarwin/sw/TxtOverlay.java +++ b/library/src/main/java/org/easydarwin/sw/TxtOverlay.java @@ -1,8 +1,13 @@ package org.easydarwin.sw; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.text.TextUtils; +import org.easydarwin.easypusher.R; +import org.easydarwin.util.YUVUtils; + import java.io.File; /** @@ -17,32 +22,54 @@ public class TxtOverlay { private final Context context; - public TxtOverlay(Context context){ + int startY = 100;//水印Y轴的位置 + int startX = 100;//水印X轴的位置 + Bitmap bmp; + byte[] mark; + + public TxtOverlay(Context context) { this.context = context; + //从drawble中获取水印图片 + Bitmap bmp1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.float_button); + //缩小图片 + bmp = YUVUtils.scaleImage(bmp1, 40, 40); + //转YUV + mark = YUVUtils.getYUVByBitmap(bmp); } + private long ctx; - public void init(int width, int height,String fonts) { - if (TextUtils.isEmpty(fonts)){ + public void init(int width, int height, String fonts) { + if (TextUtils.isEmpty(fonts)) { throw new IllegalArgumentException("the font file must be valid!"); } - if (!new File(fonts).exists()){ + if (!new File(fonts).exists()) { throw new IllegalArgumentException("the font file must be exists!"); } - ctx = txtOverlayInit(width, height,fonts); + ctx = txtOverlayInit(width, height, fonts); } public void overlay(byte[] data, String txt) { -// txt = "drawtext=fontfile="+context.getFileStreamPath("SIMYOU.ttf")+": text='EasyPusher 2017':x=(w-text_w)/2:y=H-60 :fontcolor=white :box=1:boxcolor=0x00000000@0.3"; -// txt = "movie=/sdcard/qrcode.png [logo];[in][logo] " -// + "overlay=" + 0 + ":" + 0 -// + " [out]"; -// if (ctx == 0) throw new RuntimeException("init should be called at first!"); if (ctx == 0) return; txtOverlay(ctx, data, txt); } + public void javaOverlay(byte[] data, + String txt) { + if (ctx == 0) return; + int j = 0; + for (int i = startY; i < bmp.getHeight() + startY; i++) { + for (int c = 0; c < bmp.getWidth(); c++) { + //去掉PNG水印的黑边 + if (mark[j * bmp.getWidth() + c] != 0x10 && mark[j * bmp.getWidth() + c] != 0x80 && mark[j * bmp.getWidth() + c] != 0xeb) { + System.arraycopy(mark, j * bmp.getWidth() + c, data, startX + i * 1280 + c, 1); + } + } + j++; + } + } + public void release() { if (ctx == 0) return; txtOverlayRelease(ctx); diff --git a/library/src/main/java/org/easydarwin/util/YUVUtils.java b/library/src/main/java/org/easydarwin/util/YUVUtils.java new file mode 100644 index 0000000..a1695ef --- /dev/null +++ b/library/src/main/java/org/easydarwin/util/YUVUtils.java @@ -0,0 +1,73 @@ +package org.easydarwin.util; + +import android.graphics.Bitmap; +import android.graphics.Matrix; + +public class YUVUtils { + //缩小图片到制定长宽 + public static Bitmap scaleImage(Bitmap bm, int newWidth, int newHeight) { + if (bm == null) { + return null; + } + int width = bm.getWidth(); + int height = bm.getHeight(); + float scaleWidth = ((float) newWidth) / width; + float scaleHeight = ((float) newHeight) / height; + Matrix matrix = new Matrix(); + matrix.postScale(scaleWidth, scaleHeight); + Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, + true); + if (bm != null & !bm.isRecycled()) { + bm.recycle(); + bm = null; + } + return newbm; + } + + //图片转YUV + public static byte[] getYUVByBitmap(Bitmap bitmap) { + if (bitmap == null) { + return null; + } + int width = bitmap.getWidth(); + int height = bitmap.getHeight(); + + int size = width * height; + + int pixels[] = new int[size]; + bitmap.getPixels(pixels, 0, width, 0, 0, width, height); + byte[] data = rgb2YCbCr420(pixels, width, height); + + return data; + } + + public static byte[] rgb2YCbCr420(int[] pixels, int width, int height) { + int len = width * height; + //yuv格式数组大小,y亮度占len长度,u,v各占len/4长度。 + byte[] yuv = new byte[len * 3 / 2]; + int y, u, v; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + //屏蔽ARGB的透明度值 + int rgb = pixels[i * width + j] & 0x00FFFFFF; + //像素的颜色顺序为bgr,移位运算。 + int r = rgb & 0xFF; + int g = (rgb >> 8) & 0xFF; + int b = (rgb >> 16) & 0xFF; + //套用公式 + y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; + u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; + v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128; + + y = y < 16 ? 16 : (y > 255 ? 255 : y); + u = u < 0 ? 0 : (u > 255 ? 255 : u); + v = v < 0 ? 0 : (v > 255 ? 255 : v); + //赋值 + yuv[i * width + j] = (byte) y; + yuv[len + (i >> 1) * width + (j & ~1) + 0] = (byte) u; + yuv[len + +(i >> 1) * width + (j & ~1) + 1] = (byte) v; + } + } + return yuv; + } +} diff --git a/library/src/main/res/drawable-hdpi/float_button.png b/library/src/main/res/drawable-hdpi/float_button.png new file mode 100644 index 0000000000000000000000000000000000000000..0f43fa2abbe379e6c901d6d4f8b059d23ae1f972 GIT binary patch literal 7663 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 z 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 literal 0 HcmV?d00001