Как найти относительный размер текста - PullRequest
0 голосов
/ 23 марта 2019

Я пытаюсь нарисовать текст на изображениях разных размеров. Изображение отображается в ImageView, а затем рисуется в Canvas. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '*' * '* * * * * * *, Хотя ImageView сохраняет исходную высоту и ширину изображения, но в *1004* изображение выглядит намного меньше, поэтому очень неудобно выбирать подходящий размер текста для Canvas, поскольку ImageView дает ложное восприятие о том, как текст будет отображаться на изображении.

Чтобы столкнуться с этой проблемой, я решил использовать кросс-умножение, чтобы найти подходящий размер текста для текста на Canvas, который, как предполагается, появляется на Canvas, как и на ImageView. Вот моя попытка:

textSize = topTextView.getTextSize();
imageViewArea = ((img.getWidth()) * (img.getHeight()));
canvasArea = ((canvas.getWidth()) * (canvas.getHeight()));
x = (((textSize)/(imageViewArea)) * (canvasArea));

Первая строка получает размер текста, который появляется на ImageView. 2-я и 3-я строки вычисляют площадь ImageView и Canvas. Третья строка в основном собирает все вместе и (в идеале) выводит значение с плавающей запятой, которое должно быть размером текста, нарисованного на Canvas.

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

Мое предположение таково: перекрестное умножение - не тот путь.

Есть предложения?

public Bitmap createMeme(ImageView img){
        BitmapDrawable bitmapDrawable = ((BitmapDrawable) img.getDrawable());
        Bitmap bitmap = bitmapDrawable.getBitmap();
        Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

        String topText = topTextView.getText().toString();
        String bottomText = bottomTextView.getText().toString();

        topText = topText.toUpperCase();
        bottomText = bottomText.toUpperCase();

        Canvas canvas = new Canvas(mutableBitmap);

        TextPaint topFillPaint = new TextPaint();
        TextPaint bottomFillPaint = new TextPaint();

        TextPaint topStrokePaint = new TextPaint();
        TextPaint bottomStrokePaint = new TextPaint();

        Typeface typeface = getResources().getFont(R.font.impact);

        textSize = topTextView.getTextSize();
        imageViewArea = ((img.getWidth()) * (img.getHeight()));
        canvasArea = ((canvas.getWidth()) * (canvas.getHeight()));
        val = textSize * sqrt(canvasArea / imageViewArea);
        x = (float)val;

        topFillPaint.setColor(Color.WHITE);
        topFillPaint.setTextSize(x);
        topFillPaint.setTypeface(typeface);

        topStrokePaint.setStyle(Paint.Style.STROKE);
        topStrokePaint.setStrokeWidth(4);
        topStrokePaint.setTextSize(x);
        topStrokePaint.setColor(Color.BLACK);
        topStrokePaint.setTypeface(typeface);

        bottomFillPaint.setColor(Color.WHITE);
        bottomFillPaint.setTextSize(x);
        bottomFillPaint.setTypeface(typeface);

        bottomStrokePaint.setStyle(Paint.Style.STROKE);
        bottomStrokePaint.setStrokeWidth(4);
        bottomStrokePaint.setColor(Color.BLACK);
        bottomStrokePaint.setTextSize(x);
        bottomStrokePaint.setTypeface(typeface);

        StaticLayout topFillLayout = new StaticLayout(topText, topFillPaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
                0.8f, 0.0f, false);
        StaticLayout topStrokeLayout = new StaticLayout(topText, topStrokePaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
                0.8f, 0.0f, false);
        StaticLayout bottomFillLayout = new StaticLayout(bottomText, bottomFillPaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
                0.8f, 0.0f, false);
        StaticLayout bottomStrokeLayout = new StaticLayout(bottomText, bottomStrokePaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
                0.8f, 0.0f, false);


        topFillLayout.draw(canvas);

        topStrokeLayout.draw(canvas);

        canvas.translate(0, canvas.getHeight() - 50);
        bottomFillLayout.draw(canvas);

        bottomStrokeLayout.draw(canvas);

        return mutableBitmap;
    }

OUTPUT

Итак, я загрузил 4 изображения с разными размерами, чтобы увидеть размер текста для каждого из них. Вот мои выводы:

  1. 274 x 184 topTextSize: 0, bottomTextSize: 0
  2. 3704 x 2469 topTextSize: 237,58, bottomTextSize: 237,58
  3. 640 x 480 topTextSize: 0, bottomTextSize: 0
  4. 2560 x 1920 topTextSize: 168, bottomTextSize: 168

Для 2 и 4, только верхний текст отображается на растровом изображении

Например, вот значения для изображения с размерами 274 x 184:

textSize = 168
imageViewArea = 1728000
canvasArea = 50416
x = 0

1 Ответ

1 голос
/ 24 марта 2019

Соотношение, которое вы вычисляете, является отношением площадей, а не соотношением длин.Если вы масштабируете изображение на 2 вдоль каждой стороны, вы получите соотношение площадей 4 (или 1/4, в зависимости от направления, которое вы рассматриваете).Размер шрифта должен быть длиной, поэтому вы должны использовать соотношение длины.

Если вы знаете, что масштабирование равномерное (высота масштабируется равным ширине), просто рассчитайте коэффициенты на основе ширины или высоты (не районы).Если это не так, вам потребуется метод визуализации текста, который может растянуть шрифт в одном направлении.Если вы хотите использовать какой-то средний размер шрифта, который сохраняет соотношение площади, просто используйте x = textSize * sqrt(canvasArea / imageViewArea).

Не по теме комментарий: в вашем фрагменте кода много лишних скобок.Лично я считаю, что это затрудняет чтение кода.Поэтому я бы посоветовал убрать лишние скобки (если они не используются намеренно для передачи определенного значения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...