Как добавить эффект водяного знака к изображению в Android?

У меня есть изображение с рамками, и мне нужно добавить эффект водяного знака. Как я могу это сделать?

8 ответов

Решение

Я нашел отличный учебник по обработке изображений Android здесь.

public static Bitmap mark(Bitmap src, String watermark, Point location, Color color, int alpha, int size, boolean underline) {
int w = src.getWidth();
int h = src.getHeight();
Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());

Canvas canvas = new Canvas(result);
canvas.drawBitmap(src, 0, 0, null);

Paint paint = new Paint();
paint.setColor(color);
paint.setAlpha(alpha);
paint.setTextSize(size);
paint.setAntiAlias(true);
paint.setUnderlineText(underline);
canvas.drawText(watermark, location.x, location.y, paint);

return result;
}

Спасибо Питу Хьюстону, который делится таким полезным уроком по базовой обработке изображений.

Для других пользователей, если вы хотите добавить логотип вашего приложения (который находится в вашей папке (ах) для рисования) поверх изображения, используйте следующий метод:

private Bitmap addWaterMark(Bitmap src) {
        int w = src.getWidth();
        int h = src.getHeight();
        Bitmap result = Bitmap.createBitmap(w, h, src.getConfig());
        Canvas canvas = new Canvas(result);
        canvas.drawBitmap(src, 0, 0, null);

        Bitmap waterMark = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.logo);
        canvas.drawBitmap(waterMark, 0, 0, null);

        return result;
    }

Если кто-то все еще ищет это, я нашел идеальный ответ здесь

Он добавляет водяной знак в нижнюю правую часть и масштабирует его в соответствии с исходным изображением, которое было именно тем, что я искал.

/**  
    * Embeds an image watermark over a source image to produce  
    * a watermarked one.  
    * @param watermarkImageFile The image file used as the watermark.  
    * @param sourceImageFile The source image file.  
    * @param destImageFile The output image file.  
    */  
   /**  
    * Adds a watermark on the given image.  
    */  
   public static Bitmap addWatermark(Resources res, Bitmap source) {  
     int w, h;  
     Canvas c;  
     Paint paint;  
     Bitmap bmp, watermark;  
     Matrix matrix;  
     float scale;  
     RectF r;  
     w = source.getWidth();  
     h = source.getHeight();  
     // Create the new bitmap  
     bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);  
     paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);  
     // Copy the original bitmap into the new one  
     c = new Canvas(bmp);  
     c.drawBitmap(source, 0, 0, paint);  
     // Load the watermark  
     watermark = BitmapFactory.decodeResource(res, R.drawable.dell_logo);  
     // Scale the watermark to be approximately 40% of the source image height  
     scale = (float) (((float) h * 0.40) / (float) watermark.getHeight());  
     // Create the matrix  
     matrix = new Matrix();  
     matrix.postScale(scale, scale);  
     // Determine the post-scaled size of the watermark  
     r = new RectF(0, 0, watermark.getWidth(), watermark.getHeight());  
     matrix.mapRect(r);  
     // Move the watermark to the bottom right corner  
     matrix.postTranslate(w - r.width(), h - r.height());  
     // Draw the watermark  
     c.drawBitmap(watermark, matrix, paint);  
     // Free up the bitmap memory  
     watermark.recycle();  
     return bmp;  
   } 

И это хорошо прокомментировано, что является огромным плюсом!

Кажется, вы ищете waterrippleeffect как этот. Оформить заказ с полным исходным кодом. Также проверьте скриншот, как выглядит эффект.

В Котлине:

Примечание. Это только что измененный код приведенных выше ответов.

      private fun mark(src: Bitmap, watermark: String): Bitmap {
        val w = src.width
        val h = src.height
        val result = Bitmap.createBitmap(w, h, src.config)
        val canvas = Canvas(result)
        canvas.drawBitmap(src, 0f, 0f, null)
        val paint = Paint()
        paint.color = Color.RED
        paint.textSize = 10f
        paint.isAntiAlias = true
        paint.isUnderlineText = true
        canvas.drawText(watermark, 20f, 25f, paint)
        return result
    }

val imageBitmap = mark(yourBitmap, "Your Text")
binding.meetProofImageView.setImageBitmap(imageBitmap)

Вы можете использовать AndroidWM, чтобы добавить водяной знак в ваше изображение, даже с невидимыми водяными знаками:

добавить зависимость:

dependencies {
  ...
  implementation 'com.huangyz0918:androidwm:0.2.3'
  ...
}

и код Java:

 WatermarkText watermarkText = new WatermarkText(“Hello World”)
                    .setPositionX(0.5) 
                    .setPositionY(0.5) 
                    .setTextAlpha(100) 
                    .setTextColor(Color.WHITE) 
                    .setTextFont(R.font.champagne) 
                    .setTextShadow(0.1f, 5, 5, Color.BLUE); 

 WatermarkBuilder.create(this, backgroundBitmap) 
                    .loadWatermarkText(watermarkText) 
                    .getWatermark() 
                    .setToImageView(backgroundView); 

Вы можете легко добавить водяной знак типа изображения или текстовый водяной знак, как этот, и размер библиотеки будет меньше 30 КБ.

Я попробовал несколько библиотек, упомянутых в других сообщениях, например эту , но, к сожалению, она отсутствует и недоступна для загрузки. Итак, я последовал ответу AndroidLearner выше, но после небольшой настройки кода для тех из вас, у кого возникли проблемы с вращением водяного знака, и какие значения действительны для различных методовclass, чтобы текст отображался повернутым под углом (как это делают большинство водяных знаков компании), вы можете использовать приведенный ниже код.
Обратите внимание, что,и- это ширина и высота экрана соответственно, которые вы можете легко рассчитать, существует множество способов, которые вы можете найти только в stackoverflow.

      public static Bitmap waterMarkBitmap(Bitmap src, String watermark) {
    int w = src.getWidth();
    int h = src.getHeight();
    Bitmap mutableBitmap = Utils.getMutableBitmap(src);
    Bitmap result = Bitmap.createBitmap(w, h, mutableBitmap.getConfig());

    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(src, 0f, 0f, null);

    Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setTextSize(92f);
    paint.setAntiAlias(true);
    paint.setAlpha(70);  // accepts value between 0 to 255, 0 means 100% transparent, 255 means 100% opaque.
    paint.setUnderlineText(false);
    canvas.rotate(45, w / 10f, h / 4f);
    canvas.drawText(watermark, w / 10f, h / 4f, paint);
    canvas.rotate(-45, w / 10f, h / 4f);

    return result;
}

Он поворачивает текстовый водяной знак на 45 градусов и помещает его в центр растрового изображения.

Также обратите внимание, что если вы не можете получить водяной знак, возможно, растровое изображение, которое вы используете в качестве источника, является неизменным. Для этого наихудшего сценария вы можете использовать приведенный ниже метод для создания изменяемого растрового изображения из неизменного.

      public static Bitmap getMutableBitmap(Bitmap immutableBitmap) {
    if (immutableBitmap.isMutable()) {
        return immutableBitmap;
    }

    Bitmap workingBitmap = Bitmap.createBitmap(immutableBitmap);
    return workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
}

Я нашел выше метод внутри здесь . Я протестировал оба метода в своем приложении, и он отлично работает после того, как я добавил вышеуказанные настройки. Попробуйте и дайте мне знать, если это работает или нет.

Использовать framelayout. поместите два просмотра изображений внутри рамки кадра и укажите положение водяного знака.

Другие вопросы по тегам