Fehlverhalten bei der Bildskalierung mit Matrix

  • Antworten:1
JanW
  • Forum-Beiträge: 50

13.07.2012, 12:42:58 via Website

Hallo liebe Android-Community,

ich stelle gerade ein Update fertig und habe ein allerletztes Problem, dass ich bereits seit Tagen nicht gelöst bekomme.
Ich habe die Frage bereits hier gestellt, jedoch scheint sich dort keiner zu melden. Deshalb hier nochmal auf Deutsch :)

Also es geht erstmal um ein View, dass der Skalierung und Verschiebung eines Bildes dient. Ein Teil des Bildes ist zoom und verschiebbar. Wenn dieser Teil des Bildes auf den gesamten View aufgespannt ist, funktioniert alles wunderbar. Auch die Begrenzung an der unteren rechten Ecke funktioniert (Siehe Bilder). Der Nutzer kann also z.B. das Bild nicht zu weit auszoomen oder so verschieben, dass der Bereich teilweise nicht mit dem Bild bedeckt ist.
Wenn jedoch nur ein bestimmter Bereich des Bildes skalierbar und zoombar ist, so kann der Benutzer das Bild an der rechten unteren Ecke aus dem Bereich ziehen (siehe Bilder).

Der innere Bereich wird über getPIXEL_INDEPENDENT_INNER_WIDTH / getPIXEL_INDEPENDENT_INNER_HEIGHT festgelegt. getPIXEL_INDEPENDENT_HEIGHT / getPIXEL_INDEPENDENT_WIDTH geben die Gesamtgröße des Views an. Warum nicht einfach getWidth? Weil ich so alles relativ zu meiner festen Größe berechnen kann und das View skalierbar wird und trotzdem sich das Seitenverhältnis nicht ändern. Die Image Matrix soll außerdem speicherbar sein, damit ein Benutzer seine Bildkreation sichern kann - deshalb die ganzen festgelegten Werte.

Die Matrix wird bei der Initialisierung so verändert, dass das Bild perfekt in den INNER-Bereich passt. Auf diesen Werten erfolgt auch die Verschiebung / Skalierung. Anschließend wird diese Matrix kopiert und nochmals skaliert und verschoben, damit das Bild mittig und verkleinert dargestellt wird. Änderungen sind dann direkt in der Matrix vorliegend und unabhängig von der View Größe.

Normalzustand:

Wenn der Benutzer das Bild an die untere rechte Ecke verschoben hat:


setContent:
1private float minScale;
2 private float PIXEL_INDEPENDENT_INNER_WIDTH;
3 private float PIXEL_INDEPENDENT_INNER_HEIGHT;
4
5 public void setContent(FailPictureInfoContainer ic, Bitmap bm) {
6 if (ic == null)
7 return;
8
9 ic.text[0] = (ic.text[0] != null) ? ic.text[0] : "";
10 ic.text[1] = (ic.text[1] != null) ? ic.text[1] : "";
11 bitmap = bm;
12
13 //CREATE MATRIX
14 Matrix m = new Matrix();
15 float[] matrixAsFloats = new float[9];
16 if (bitmap != null) {//Wenn Bild vorhanden und noch ohne Matrix, angepasste Matrix erzeugen.
17
18 //Wenn breiter als hoch
19 if (getPIXEL_INDEPENDENT_INNER_WIDTH()/bm.getWidth() < getPIXEL_INDEPENDENT_INNER_HEIGHT()/bm.getHeight())
20 m.postScale(getPIXEL_INDEPENDENT_INNER_HEIGHT() / bm.getHeight(), getPIXEL_INDEPENDENT_INNER_HEIGHT() / bm.getHeight());
21
22 //Wenn höher als breit
23 else
24 m.postScale(getPIXEL_INDEPENDENT_INNER_WIDTH() / bm.getWidth(), getPIXEL_INDEPENDENT_INNER_WIDTH() / bm.getWidth());
25 }
26 m.getValues(matrixAsFloats);
27 setMinScale((matrixAsFloats[Matrix.MSCALE_X]>matrixAsFloats[Matrix.MSCALE_Y]) ? matrixAsFloats[Matrix.MSCALE_X] : matrixAsFloats[Matrix.MSCALE_Y]);
28
29 if (ic.matrix == null)
30 ic.matrix = matrixAsFloats;
31
32 this.ic = ic;
33 update();
34 }
drawOnCanvas:
1@Override
2 void drawOnCanvas(Canvas canvas, float width, float height) {
3 if (bitmap == null || matrix_pixel_independent == null || ic == null)
4 return;
5
6 System.out.println(Arrays.toString(getIc().matrix));
7 // TopText & BottomText ANGLEICHEN
8 TextPaint_TOP = getFormattedTextView((int) (ic.textsize[0] * width / getPIXEL_OUTPUT_WIDTH()), ic.color[0]);
9 TextPaint_BOTTOM = getFormattedTextView((int) (ic.textsize[1] * width / getPIXEL_OUTPUT_WIDTH()), ic.color[1]);
10
11 // Canvas anpassen.
12 canvas.setDensity(bitmap.getDensity());
13 matrix_pixel_dependent.set(matrix_pixel_independent);
14 float borderPadding = 7f * width / getPIXEL_INDEPENDENT_WIDTH(); //Abstand zwischen Linie und Bild.
15 float paddingFactor = (getPIXEL_INDEPENDENT_WIDTH() - getPIXEL_INDEPENDENT_INNER_WIDTH()) / 2 * width
16 / getPIXEL_INDEPENDENT_WIDTH(); //Abstand zwischen View und Bild.
17 float lowerBound = getPIXEL_INDEPENDENT_INNER_HEIGHT() * height / getPIXEL_INDEPENDENT_HEIGHT() + paddingFactor + borderPadding; // Entspricht y-Wert unter Bild und Padding.
18 matrix_pixel_dependent.preScale(width / getPIXEL_INDEPENDENT_WIDTH(), height / getPIXEL_INDEPENDENT_HEIGHT(), 0,0);
19 matrix_pixel_dependent.postTranslate(paddingFactor, paddingFactor);
20 canvas.drawBitmap(bitmap, matrix_pixel_dependent, paint);
21 paint.setColorFilter(null);
22 }
onTouchEvent:
1@Override
2 public boolean onTouchEvent(MotionEvent event) {
3
4 if (bitmap == null || getIc() == null)
5 return true;
6
7 switch (event.getAction() & MotionEvent.ACTION_MASK) {
8 case MotionEvent.ACTION_DOWN:
9 //DOUBLE TAP
10 lastTapped = System.currentTimeMillis() - lastTapped;
11 if (lastTapped < 350 && lastTapped > 90){
12 touchEnabled = !touchEnabled;
13 lastTapped = System.currentTimeMillis()-900;
14 }else
15 lastTapped = System.currentTimeMillis();
16
17 if (!touchEnabled) {
18 invalidate();
19 return false;
20 }
21
22 //MOVE PREPARE
23 savedMatrix.set(matrix_pixel_independent);
24 Finger_startPosition.set(event.getX(), event.getY());
25 mode = DRAG;
26 break;
27 case MotionEvent.ACTION_POINTER_DOWN:
28 Finger_oldDistance = spacing(event);
29 if (Finger_oldDistance > 3f) {
30 savedMatrix.set(matrix_pixel_independent);
31 midPoint(Finger_Midpoint, event);
32 mode = ZOOM;
33 }
34 break;
35 case MotionEvent.ACTION_UP:
36 case MotionEvent.ACTION_POINTER_UP:
37 case MotionEvent.ACTION_CANCEL:
38 case MotionEvent.ACTION_OUTSIDE:
39 mode = NONE;
40
41 if (posChanged) {
42 posChanged = false;
43
44 if (getIc().matrix[Matrix.MSCALE_X] < getMinScale()) {
45 float scale = getMinScale() / getIc().matrix[Matrix.MSCALE_X];
46 matrix_pixel_independent.preScale(scale, scale, Finger_Midpoint.x, Finger_Midpoint.y);
47 }
48
49 matrix_pixel_independent.getValues(getIc().matrix);
50
51 float newX_post = 0;
52 float newY_post = 0;
53 float imageWidth_post = newX_post + bitmap.getWidth() * getIc().matrix[Matrix.MSCALE_X];
54 float imageHeight_post = newY_post + bitmap.getHeight() * getIc().matrix[Matrix.MSCALE_Y];
55 RectF drawingRect_post = new RectF(getIc().matrix[Matrix.MTRANS_X], getIc().matrix[Matrix.MTRANS_Y],
56 getIc().matrix[Matrix.MTRANS_X] + imageWidth_post, getIc().matrix[Matrix.MTRANS_Y] + imageHeight_post);
57 float diffUp_post = Math.min(getPIXEL_INDEPENDENT_INNER_HEIGHT() - drawingRect_post.bottom, -drawingRect_post.top);
58 float diffDown_post = Math.max(getPIXEL_INDEPENDENT_INNER_HEIGHT() - drawingRect_post.bottom, -drawingRect_post.top);
59 float diffLeft_post = Math.min(getPIXEL_INDEPENDENT_INNER_WIDTH() - drawingRect_post.right, -drawingRect_post.left);
60 float diffRight_post = Math.max(getPIXEL_INDEPENDENT_INNER_WIDTH() - drawingRect_post.right, -drawingRect_post.left);
61
62 if (diffUp_post > 0)
63 newY_post += diffUp_post;
64
65 if (diffDown_post < 0)
66 newY_post += diffDown_post;
67
68 if (diffLeft_post > 0)
69 newX_post += diffLeft_post;
70
71 if (diffRight_post < 0)
72 newX_post += diffRight_post;
73
74 matrix_pixel_independent.postTranslate(newX_post, newY_post);
75
76
77 Log.d(MainActivity.TAG, "width: "+imageWidth_post+" height: "+imageHeight_post+ " xstart: "+getIc().matrix[Matrix.MTRANS_X]+ " ystart: " +getIc().matrix[Matrix.MTRANS_Y]+ " xend: "+ getIc().matrix[Matrix.MTRANS_X] + imageWidth_post+" yend: "+getIc().matrix[Matrix.MTRANS_Y] + imageHeight_post);
78
79 //Listener anstupsen.
80 if (OnMeGustaViewChangedListener != null)
81 OnMeGustaViewChangedListener.onViewChanged();
82
83 matrix_pixel_independent.getValues(getIc().matrix);
84 }
85 break;
86 case MotionEvent.ACTION_MOVE:
87 matrix_pixel_independent.set(savedMatrix);
88 if (mode == DRAG) {
89 //DRAGGING
90 float eventX = event.getX() - Finger_startPosition.x;
91 float eventY = event.getY() - Finger_startPosition.y;
92 matrix_pixel_independent.postTranslate(eventX, eventY);
93
94 //Position hat sich geändert -> Listener.
95 posChanged = eventX != 0 || eventY != 0;
96 } else if (mode == ZOOM) {
97 //ZOOMING
98 float newDist = spacing(event);
99 if (newDist > 3f) {
100 float scale = newDist / Finger_oldDistance;
101 matrix_pixel_independent.postScale(scale, scale, Finger_Midpoint.x, Finger_Midpoint.y);
102
103 //Position hat sich geändert -> Listener.
104 posChanged = true;
105 }
106 }
107 matrix_pixel_independent.getValues(getIc().matrix);
108 }
109 invalidate();
110 return true;
111 }
112
113 /**
114 * Spacing between Fingers on event.
115 *
116 * @param event
117 * @return
118 */
119 private float spacing(MotionEvent event) {
120 float x = event.getX(0) - event.getX(1);
121 float y = event.getY(0) - event.getY(1);
122 return FloatMath.sqrt(x * x + y * y);
123 }
124
125 /**
126 * MidPoint between Fingers on event.
127 *
128 * @param point
129 * @param event
130 */
131 private void midPoint(PointF point, MotionEvent event) {
132 float x = event.getX(0) + event.getX(1);
133 float y = event.getY(0) + event.getY(1);
134 point.set(x / 2, y / 2);
135 }

Antworten
JanW
  • Forum-Beiträge: 50

15.07.2012, 19:32:58 via Website

Hat den keiner eine Idee?

Antworten