Проблема с растровым изображением аннотации изображения Android

#android #image #kotlin #canvas #bitmap

#Android #изображение #kotlin #холст #растровое изображение

Вопрос:

Я создаю базовую медиа-библиотеку, и одной из функций является аннотация изображения. Я получаю медиафайл из системы хранения Android, а затем преобразую его в растровое изображение. Затем я создаю холст из растрового изображения и использую функцию DrawLine класса canvas, чтобы разрешить базовую аннотацию. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что холст и изображение имеют разный размер, поэтому линии нарисованы в неправильном месте.

Это код для создания растровых изображений.

 val bmpFactoryOptions = BitmapFactory.Options()
                bmpFactoryOptions.inJustDecodeBounds = false
                bmp = (BitmapFactory.decodeFile(it.mediaUrl)).rotate(270f)

                alteredBitmap = Bitmap.createBitmap(
                    bmp!!.width, bmp!!
                        .height, bmp!!.config
                )
  

Затем я создаю объекты canvas, paint и matrix.

 canvas = Canvas(alteredBitmap!!)
paint = Paint()
paint!!.color = Color.GREEN
paint!!.strokeWidth = 5f
matrix = Matrix()
canvas!!.drawBitmap(bmp!!, matrix!!, paint)
  

Затем я устанавливаю alteredBitmap как изображение представления изображения

 annotateIV!!.setImageBitmap(alteredBitmap)
  

Последнее место, где ошибка имела бы смысл, находится в TouchListener ImageView.

 annotateIV!!.setOnTouchListener { view, motionEvent ->
                    when (motionEvent.action) {
                        ACTION_DOWN -> {
                            downx = motionEvent.x
                            downy = motionEvent.y
                        }
                        ACTION_MOVE -> {
                            upx = motionEvent.x
                            upy = motionEvent.y
                            canvas!!.drawLine(downx, downy, upx, upy, paint!!)
                            annotateIV!!.invalidate()
                            downx = upx
                            downy = upy
                        }
                        ACTION_UP -> {
                            upx = motionEvent.x
                            upy = motionEvent.y
                            canvas!!.drawLine(downx, downy, upx, upy, paint!!)
                            annotateIV!!.invalidate()
                        }
                        ACTION_CANCEL -> {
                        }
                        else -> {

                        }
                    }
                    return@setOnTouchListener true
                }
  

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

Спасибо всем, кто посмотрел, и любая помощь будет высоко оценена.

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

 bmp = (BitmapFactory.decodeFile(it.mediaUrl)).rotate(270f)

                alteredBitmap = Bitmap.createBitmap(
                    bmp!!.width, bmp!!
                        .height, bmp!!.config
                )
                alteredBitmap = Bitmap.createScaledBitmap(alteredBitmap!!, annotateIV.width, annotateIV.height, false)
  

Ответ №1:

ваш Canvas размер Bitmap , вероятно, намного больше, чем размер вашего экрана. вы устанавливаете Bitmap значение annotateIV , которое, как я полагаю ImageView , и scaleType настроено для подгонки всего Bitmap внутреннего вида. на самом деле это все еще не изменяет размер Bitmap / Canvas , это просто «предварительный просмотр»

для исправления этого вам следует масштабировать свой Bitmap размер до размера ImageView или сделать некоторое значение коэффициента / отношения bitmapSize / imageViewSize и умножить все motionEvent.x и motionEvent.y на него

кстати. вызов invalidate() при каждом MotionEvent появлении неэффективен … вот почему ваша линия не закруглена, она явно сделана прямыми линиями

Комментарии:

1. alteredBitmap = Bitmap.CreateBitmap(annotateIV.width, annotateIV.height, bmp !!.config ) Я изменил создание растрового изображения на это, теперь изображение сильно увеличено, но линии нарисованы в правильной области на экране. Не могли бы вы уточнить, что вы подразумеваете под последней частью своего сообщения, если это возможно. Большое вам спасибо

2. о invalidate() чем? вы вызываете этот метод с каждым новым MotionEvent , но для рисования требуется время. каждый следующий invalidate вызов во время предыдущего запуска просто пропускается, поскольку пользовательский интерфейс зависает на предыдущей операции, поэтому вы теряете некоторые точки для рисования — это хорошо видно в нижней части вашей зеленой линии, она сделана с несколькими прямыми линиями («точки соединены»), не округляется, как при перемещении пальцаэкран

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

4. но для недействительности, как часто вы бы рекомендовали его вызывать?

5. загрузите свой Bitmap , как и раньше, но сразу после этого используйте Bitmap.createScaledBitmap метод и масштабируйте его до размера ImageView . используя Bitmap.createBitmap( annotateIV.width, annotateIV.height,... , вы загружаете только часть Bitmap , которая, установленная на ImageView , выглядит как увеличенная