Android: केंद्र बिंदु पर बिटमैप को कैसे घुमाएं


84

मैं इस समस्या के समाधान के लिए एक दिन से अधिक समय से तलाश कर रहा हूं, लेकिन यहां तक ​​कि कुछ भी मदद नहीं करता है, यहां तक ​​कि उत्तर भी। प्रलेखन कुछ भी स्पष्ट नहीं करता है।

मैं बस किसी अन्य वस्तु की दिशा में घूमने की कोशिश कर रहा हूं। समस्या यह है कि बिटमैप को एक निश्चित बिंदु के आसपास नहीं घुमाया जाता है, बल्कि बिटमैप (0,0) के आसपास घुमाया जाता है।

यहाँ वह कोड है जिससे मुझे परेशानी हो रही है:

  Matrix mtx = new Matrix();
  mtx.reset();
  mtx.preTranslate(-centerX, -centerY);
  mtx.setRotate((float)direction, -centerX, -centerY);
  mtx.postTranslate(pivotX, pivotY);
  Bitmap rotatedBMP = Bitmap.createBitmap(bitmap, 0, 0, spriteWidth, spriteHeight, mtx, true);
  this.bitmap = rotatedBMP;

अजीब हिस्सा है, इससे कोई फर्क नहीं पड़ता कि मैं pre/ postTranslate()और फ्लोट तर्कों के भीतर मूल्यों को कैसे बदलता हूं setRotation()। क्या कोई मदद कर सकता है और मुझे सही दिशा में धकेल सकता है? :)


1
मैं इसे ऊपर ले कोड कई प्रयास बदलाव के बाद है। ऐसा लगता है कि mtx.setRotate (dir, x, y) को सभी पूर्व पोस्ट सामग्री के बिना, अपने आप चाल चलनी चाहिए। इसके अलावा, आपको नए सिरे से newएड मैट्रिक्स को रीसेट करने की आवश्यकता नहीं है । इसकी पहले से ही पहचान है।
मार्क स्टॉपर

जवाबों:


101

मुझे आशा है कि कोड का निम्नलिखित अनुक्रम आपकी सहायता करेगा:

Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight, config);
Canvas canvas = new Canvas(targetBitmap);
Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
canvas.drawBitmap(source, matrix, new Paint());

यदि आप निम्न विधि से जाँच करते हैं ~frameworks\base\graphics\java\android\graphics\Bitmap.java

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
        Matrix m, boolean filter)

यह समझाता है कि यह रोटेशन और अनुवाद के साथ क्या करता है।


1
क्या आप इसे Bitmap.createBitmap के साथ कर सकते हैं जो एक मैट्रिक्स लेता है? आप टारगेट की गणना कैसे कर रहे हैं? सरल ट्रिगर, मुझे लगता है, लेकिन क्या एक "आसान" तरीका है?

कृपया नीचे दिए गए उत्तर की जाँच करें, (क्षमा करें, मैं टिप्पणियों में कोड नहीं जोड़ सका)
सुदर्शन निमन

इसे लगाते समय गुणवत्ता खराब हो जाती है। कोई भी समाधान ?
MSaudi

1
कैनवास को बदलें। बिटमैप (स्रोत, मैट्रिक्स, नया पेंट ()); कैनवस के साथ। निकासीमैप (स्रोत, मैट्रिक्स, नया पेंट (पेंट.ANTI_ALIAS_FLAG));
सुदर निमलन

3
बस टिप्पणी करते हुए कि यह प्रक्रिया बहुत स्मृति-भूख है, और इसका उपयोग चरण विधियों में नहीं किया जाना चाहिए।
MLProgrammer-CiM

79

संपादित : अनुकूलित कोड।

public static Bitmap RotateBitmap(Bitmap source, float angle)
{
      Matrix matrix = new Matrix();
      matrix.postRotate(angle);
      return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}

संसाधनों से बिटमैप प्राप्त करने के लिए:

Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);

किसी भी w या h के साथ बिटमैप को घुमाने के लिए यह कोशिश करें: मैट्रिक्स मैट्रिक्स = नया मैट्रिक्स (); matrix.postRotate (90); bitmapPicture = Bitmap.createBitmap (बिटमैपचित्र, 0, 0, bitmapPicture.getWidth (), bitmapPicture.getHeight (), मैट्रिक्स, सच);
मार्क मोलिना

यह पूरी तरह से मेरे लिए काम करता है क्योंकि मैं छवि बिंदुओं के लिए पैरामीटर सेट कर रहा हूं। आपको बस बिटमैप को कैनवास पर आरेखण करते समय मैट्रिक्स का उपयोग करना सुनिश्चित करना होगा।
a54studio

6
क्या आप सुनिश्चित हैं कि यह कुशल है? यदि रोटेटबिटमैप () एन टाइम निष्पादित करने वाले लूप में था, तो बिटमैप के रिज़ॉल्यूशन के आधार पर आप एक जबरदस्त मेमोरी और साथ ही उन सभी नए मैट्रिक्स ऑब्जेक्ट आवंटन को बर्बाद कर सकते हैं।
रिहान

परीक्षण नहीं किया गया है लेकिन डॉक्स कहते हैं: "यदि स्रोत बिटमैप अपरिवर्तनीय है और अनुरोधित सबसेट, स्रोत बिटमैप के समान ही है, तो स्रोत बिटमैप वापस आ जाता है और कोई नया बिटमैप नहीं बनाया जाता है।" मैट्रिक्स ऑब्जेक्ट के रूप में यह सिर्फ निर्देशांक वर्ग को बदल रहा है। आप पुनरावृत्ति के लिए स्वतंत्र रूप से कोड का अनुकूलन कर सकते हैं और लूप में समान मैट्रिक्स ऑब्जेक्ट का उपयोग कर सकते हैं।
अरविस

FYI करें, बिटमैप को
म्यूट

25

मैं अब इस समस्या पर वापस आ गया हूं कि हम खेल को अंतिम रूप दे रहे हैं और मैंने सोचा कि मेरे लिए क्या काम करना है।

यह मैट्रिक्स को घुमाने की विधि है:

this.matrix.reset();
this.matrix.setTranslate(this.floatXpos, this.floatYpos);
this.matrix.postRotate((float)this.direction, this.getCenterX(), this.getCenterY()); 

(this.getCenterX() मूल रूप से बिटमैप्स X स्थिति + बिटमैप्स चौड़ाई / 2)

और बिटमैप ड्राइंग के लिए विधि (एक RenderManagerकक्षा के माध्यम से ):

canvas.drawBitmap(this.bitmap, this.matrix, null);

तो यह सीधे-सीधे दिखावा है लेकिन मुझे यह अजीब लगता है कि मैं setRotateइसके बाद काम नहीं कर पायाpostTranslate । शायद कुछ जानते हैं कि यह काम क्यों नहीं करता है? अब सभी बिटमैप्स ठीक से घूमते हैं लेकिन यह बिटमैप गुणवत्ता में कुछ मामूली कमी के बिना नहीं है: /

वैसे भी, आपकी मदद के लिए धन्यवाद!


पिछला उत्तर कोड भी काम करता है। गुणवत्ता की इसी समस्या के साथ।
MSaudi

7

तुम भी ImageViewएक का उपयोग कर बारी बारी से कर सकते हैं RotateAnimation:

RotateAnimation rotateAnimation = new RotateAnimation(from, to,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setDuration(ANIMATION_DURATION);
rotateAnimation.setFillAfter(true);

imageView.startAnimation(rotateAnimation);

4
आप गलत प्रश्न का उत्तर दे रहे हैं। वह दृश्य को घुमाना नहीं चाहता, बस उसके भीतर एक बिटमैप है।
मार्क स्टॉपर

जैसा कि मैंने अनुभव किया, setFillAfter (बूल) विधि काम नहीं कर रही है क्योंकि यह Android API lvl 11 और नीचे होने की उम्मीद है। इसलिए, डेवलपर्स दृश्य वस्तुओं पर निरंतर रोटेशन की घटना का उपयोग करने में असमर्थ हैं, न ही वे रोटेशन के बाद इन विचारों के घुमाए गए संस्करण प्राप्त करते हैं। तो @ मर्क स्टॉपर, मकार्से ने तार्किक दृष्टिकोण पर सही उत्तर दिया यदि आप 0 के साथ एनीमेशन अवधि सेट करते हैं या 0. के करीब कुछ
Gökhan Barış Aker

5

आप निम्नलिखित कुछ का उपयोग कर सकते हैं:


Matrix matrix = new Matrix();
matrix.setRotate(mRotation,source.getWidth()/2,source.getHeight()/2);
RectF rectF = new RectF(0, 0, source.getWidth(), source.getHeight());
matrix.mapRect(rectF);
Bitmap targetBitmap = Bitmap.createBitmap(rectF.width(), rectF.height(), config);
Canvas canvas = new Canvas(targetBitmap);
canvas.drawBitmap(source, matrix, new Paint());


सभी समाधानों के लिए एक ही समस्या: बिटमैप की गुणवत्ता में कमी
MSAudi

कैनवास को बदलें। बिटमैप (स्रोत, मैट्रिक्स, नया पेंट ()); कैनवास के साथ। बिटमैप (स्रोत, मैट्रिक्स, नया पेंट (पेंट.ANTI_ALIAS_FLAG));
सुदर निमलन

आपके द्वारा उपयोग किया जा रहा कॉन्फ़िगरेशन क्या है?
सुदर निमलन

मैंने उत्तर के रूप में नीचे दिए गए कोड को पोस्ट किया। टिप्पणी में यह नहीं लिख सकता। बहुत बहुत धन्यवाद सर :)
MSaudi


1

मैंने इस विन्यास का उपयोग किया और अभी भी पिक्सेलाइज़ेशन की समस्या है:

Bitmap bmpOriginal = BitmapFactory.decodeResource(this.getResources(), R.drawable.map_pin);
        Bitmap targetBitmap = Bitmap.createBitmap((bmpOriginal.getWidth()),
                (bmpOriginal.getHeight()), 
                Bitmap.Config.ARGB_8888);
        Paint p = new Paint();
        p.setAntiAlias(true);

        Matrix matrix = new Matrix();       
        matrix.setRotate((float) lock.getDirection(),(float) (bmpOriginal.getWidth()/2),
                (float)(bmpOriginal.getHeight()/2));

        RectF rectF = new RectF(0, 0, bmpOriginal.getWidth(), bmpOriginal.getHeight());
        matrix.mapRect(rectF);

        targetBitmap = Bitmap.createBitmap((int)rectF.width(), (int)rectF.height(), Bitmap.Config.ARGB_8888);


        Canvas tempCanvas = new Canvas(targetBitmap); 
        tempCanvas.drawBitmap(bmpOriginal, matrix, p);

1
क्या आप setFilterBitmap को सेट कर सकते हैं, या तो विकल्प
Sudar Nimalan

1
हाँ, यह पूरी तरह से काम किया। थैंक यू सोदर, आपने वास्तव में मेरी बहुत मदद की।
MSAudi

1
अद्यतन कोड के साथ अपने स्वयं के अनुवर्ती के लिए लिंक जोड़ना: stackoverflow.com/questions/13048953/…
क्रिस राए

0
matrix.reset();
matrix.setTranslate( anchor.x, anchor.y );
matrix.postRotate((float) rotation , 0,0);
matrix.postTranslate(positionOfAnchor.x, positionOfAnchor.x);
c.drawBitmap(bitmap, matrix, null); 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.