Android: गैलरी से लोड किए गए बिटमैप्स ImageView में घुमाए जाते हैं


138

जब मैं मीडिया गैलरी से एक बिटमैप में एक छवि लोड करता हूं, तो सब कुछ ठीक काम कर रहा है, सिवाय इसके कि तस्वीरें जो कैमरे के साथ शूट की गई थीं, जबकि फोन को लंबवत रखा गया था, घुमाया जाता है ताकि मुझे हमेशा एक क्षैतिज तस्वीर मिल जाए, भले ही यह लंबवत दिखाई दे गेलरी। ऐसा क्यों है और मैं इसे सही तरीके से कैसे लोड कर सकता हूं?


मेरे पास असली उत्तर stackoverflow.com/questions/29971319/image-orientation-android/…
A.Sanchez.SD

जवाबों:


40

क्या आपने छवियों के EXIF ​​डेटा को देखा है? जब चित्र लिया गया था तो यह कैमरे के उन्मुखीकरण को जान सकता है।


2
आप सही कह रहे हैं, यह निश्चित रूप से समाधान था। मैं बाद में एक अलग उत्तर में एक उदाहरण के रूप में अपना कोड पोस्ट करने जा रहा हूं, लेकिन मैं इसे एक के रूप में स्वीकार करता हूं क्योंकि यह मुझे सही रास्ते पर मिला है।
मैनुअल

182

तो, एक उदाहरण के रूप में ...

सबसे पहले आपको एक ExifInterface बनाने की आवश्यकता है:

ExifInterface exif = new ExifInterface(filename);

तब आप छवि के उन्मुखीकरण को पकड़ सकते हैं:

orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

यहाँ उन्मुखीकरण मूल्यों का क्या अर्थ है: http://sylvana.net/jpegcrop/exif_orientation.html

तो, सबसे महत्वपूर्ण मान 3, 6 और 8 हैं। यदि अभिविन्यास है ExifInterface.ORIENTATION_ROTATE_90(जो 6 है), उदाहरण के लिए, आप छवि को इस तरह घुमा सकते हैं:

Matrix matrix = new Matrix();
matrix.postRotate(90);
rotatedBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), matrix, true);

यह सिर्फ एक त्वरित उदाहरण है, हालांकि। मुझे यकीन है कि वास्तविक रोटेशन करने के अन्य तरीके हैं। लेकिन आप उन StackOverflow पर भी मिल जाएगा।


5
विभिन्न अभिविन्यासों के लिए यहां सभी रोटेशन मान हैं: 3: 180, 6: 90, 8: 270
प्रदर्शन नाम

103
जब आप स्थिरांक नाम का उपयोग कर सकते हैं तो मैजिक नंबर का उपयोग न करें: ExifInterface.ORIENTATION_NORMAL, ExifInterface.ORIENTATION_ROTATE_90, ExifInterface.ORIENTATION_ROTATE_180, ExifInterface.ORIENTATION_ROTATE_270।
d60402

29
OutOfMemoryErrorइस दृष्टिकोण का उपयोग करते समय देखें जब आप एक ही समय में दो बिटमैप को मेमोरी में रखते हैं।
एलेक्स बोनल

एक और पूरा उदाहरण ... stackoverflow.com/questions/14066038/…
CGR

64

यह एक पूर्ण समाधान है (फेसबुक एसडीके से हैकबुक उदाहरण में पाया गया)। इसका लाभ यह है कि फ़ाइल को स्वयं एक्सेस करने की आवश्यकता नहीं है। यह बेहद उपयोगी है यदि आप सामग्री रिज़ॉल्वर चीज़ से एक छवि लोड कर रहे हैं (जैसे कि यदि आपका ऐप शेयर-फोटो इरादे का जवाब दे रहा है)।

public static int getOrientation(Context context, Uri photoUri) {
    /* it's on the external media. */
    Cursor cursor = context.getContentResolver().query(photoUri,
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);

    if (cursor.getCount() != 1) {
        return -1;
    }

    cursor.moveToFirst();
    return cursor.getInt(0);
}

और फिर आप निम्न प्रकार से एक घुमाया हुआ बिटमैप प्राप्त कर सकते हैं। यह कोड MAX_IMAGE_DIMENSION तक छवि को बुरी तरह से खराब कर देता है। अन्यथा आप मेमोरी से बाहर भाग सकते हैं।

public static Bitmap getCorrectlyOrientedImage(Context context, Uri photoUri) throws IOException {
    InputStream is = context.getContentResolver().openInputStream(photoUri);
    BitmapFactory.Options dbo = new BitmapFactory.Options();
    dbo.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, dbo);
    is.close();

    int rotatedWidth, rotatedHeight;
    int orientation = getOrientation(context, photoUri);

    if (orientation == 90 || orientation == 270) {
        rotatedWidth = dbo.outHeight;
        rotatedHeight = dbo.outWidth;
    } else {
        rotatedWidth = dbo.outWidth;
        rotatedHeight = dbo.outHeight;
    }

    Bitmap srcBitmap;
    is = context.getContentResolver().openInputStream(photoUri);
    if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) {
        float widthRatio = ((float) rotatedWidth) / ((float) MAX_IMAGE_DIMENSION);
        float heightRatio = ((float) rotatedHeight) / ((float) MAX_IMAGE_DIMENSION);
        float maxRatio = Math.max(widthRatio, heightRatio);

        // Create the bitmap from file
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = (int) maxRatio;
        srcBitmap = BitmapFactory.decodeStream(is, null, options);
    } else {
        srcBitmap = BitmapFactory.decodeStream(is);
    }
    is.close();

    /*
     * if the orientation is not 0 (or -1, which means we don't know), we
     * have to do a rotation.
     */
    if (orientation > 0) {
        Matrix matrix = new Matrix();
        matrix.postRotate(orientation);

        srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(),
                srcBitmap.getHeight(), matrix, true);
    }

    return srcBitmap;
}

1
MAX_IMAGE_DIMENDION का क्या मतलब है?
सज्जाद हिसैन खान

3
यह आपके द्वारा प्राप्त की गई छवि की अधिकतम चौड़ाई या ऊँचाई है। Ie कहो कि आपको केवल एक 512x512 छवि की आवश्यकता है, यदि आप एक 24 मेगापिक्सेल छवि को खोलते हैं तो यह बहुत अधिक कुशल है इसे खोलने के लिए पहले से ही पूरी चीज खोलने की तुलना में कम है और फिर इसे नीचे पैमाने पर रखें - जो कि वैसे भी आपकी सभी मेमोरी को समाप्त कर देगा।
टिम्मम नोव

मेरे कार्यक्रमों में मुझे निजी स्टेटिक के रूप में गतिविधि / टुकड़े में बिटमैप चर को परिभाषित करने और इसे कार्यों में अशक्त करने के लिए उपयोगी पाया गया। याददाश्त कम होने की परेशानी थी।
गुन्नार बर्नस्टीन

यह MAX_IMAGE_DIMENDION को MAX_IMAGE_WIDTH और MAX_IMAGE_HEIGHT में बदलने के लिए अधिक स्मार्ट है
fnc12

मेरा बहुत सारा समय बचा है :) बहुत धन्यवाद। अशक्त कर्सर पाने वालों के लिए, आप कोशिश कर सकते हैं ExifInterface exif = new ExifInterface(photoUri.getPath());और फिर exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1)अभिविन्यास प्राप्त कर सकते हैं (जैसे ORIENTATION_ROTATE_90, ORIENTATION_ROTATE_180)
अतुल

60

इस पोस्ट की मदद से इस कोड के साथ मेरे मामले में इसे हल किया:

            Bitmap myBitmap = getBitmap(imgFile.getAbsolutePath());

            try {
                ExifInterface exif = new ExifInterface(imgFile.getAbsolutePath());
                int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
                Log.d("EXIF", "Exif: " + orientation);
                Matrix matrix = new Matrix();
                if (orientation == 6) {
                    matrix.postRotate(90);
                }
                else if (orientation == 3) {
                    matrix.postRotate(180);
                }
                else if (orientation == 8) {
                    matrix.postRotate(270);
                }
                myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight(), matrix, true); // rotating bitmap
            }
            catch (Exception e) {

            }
            ImageView img = (ImageView) findViewById(R.id.imgTakingPic);
            img.setImageBitmap(myBitmap);

आशा है कि यह किसी का समय बचाता है!


सुझावों को संपादित करें: 6, 3, 8 के झुकावों के लिए कोई उचित नामांकित स्थिरांक नहीं हैं? यदि रोटेशन की आवश्यकता नहीं है तो क्या हम नए बिटमैप को छोड़ सकते हैं?
मैक्शरपफेस

जैसा कि @ d60402 ने पहले एक टिप्पणी में कहा था, आप नामांकित स्थिरांक का उपयोग कर सकते हैं: ExifInterface.ORIENTATION_NORMAL, ExifInterface.ORIENTATION_ROTATE_90, ExifInterface.ORIENTATION_ROTATE_180, ExifInterface.ORIENTATION_ROTATE_275।
एड्रियन

42

हैवी लिफ्टिंग करने के लिए एक यूटिलिटी का उपयोग करें।

9re ने EXIF ​​डेटा से निपटने और अपने सही अभिविन्यास के लिए छवियों को घुमाने के भारी उठाने को संभालने के लिए एक सरल उपयोगिता बनाई।

आप यहाँ उपयोगिता कोड पा सकते हैं: https://gist.github.com/9re/1990019

बस इसे डाउनलोड करें, इसे अपनी परियोजना की srcनिर्देशिका में जोड़ें और ExifUtil.rotateBitmap()सही अभिविन्यास प्राप्त करने के लिए उपयोग करें, जैसे:

String imagePath = photoFile.getAbsolutePath();             // photoFile is a File class.
Bitmap myBitmap  = BitmapFactory.decodeFile(imagePath);

Bitmap orientedBitmap = ExifUtil.rotateBitmap(imagePath, myBitmap);

2
मेरे लिये कार्य करता है ! मैंने बस बिटमैप को रीसाइज़ किया है HD इसे ExOUtil.rotateBitmap () से बचने के लिए फॉर्मेट से बचने के लिए। photo = ExifUtil.rotateBitmap (चित्रपट, आकार परिवर्तन);
फिल

@Phil का अच्छा जोड़। मैं उस में नहीं चला (मैं पुराने, shittier Android उपकरणों का उपयोग कर रहा हूं) लेकिन यह जानना बहुत अच्छा है।
जोशुआ पिंटर

3
तुम मेरे दोस्त हो :)
klutch

@ कच्छप तुमने अभी-अभी मेरा दिन बनाया है। :) निष्पक्ष होने के लिए, 9re ने उपयोगिता कोड लिखा ताकि वह असली नायक हो।
जोशुआ पिंटर

1
@ श्रीकांतकर्मनघाट महान प्रश्न! मैं शायद जानता था कि जब मैं इस बारे में गहराई में था, तो यह समझ में क्यों आया लेकिन अभी यह मेरे लिए भी बेमानी लगता है। शायद रिएक्ट नेटिव में बहुत अधिक समय बिताया।
जोशुआ पिंटर

8

इसकी वजह यह है कि गैलरी घूमती हुई छवियों को सही दिखाती है, लेकिन ImageView यहां नहीं दिखती:

                    myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(),optionss);
                    ExifInterface exif = new ExifInterface(selectedImagePath);
                    int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
                    int rotationInDegrees = exifToDegrees(rotation);
                    deg = rotationInDegrees;
                    Matrix matrix = new Matrix();
                    if (rotation != 0f) {
                        matrix.preRotate(rotationInDegrees);
                        myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight(), matrix, true);
                    }

और आपको इसकी आवश्यकता है:

private static int exifToDegrees(int exifOrientation) {        
    if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; } 
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {  return 180; } 
    else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {  return 270; }            
    return 0;    
} 

5

एक पोस्ट मैं अब नहीं मिल सकता है के लिए कई प्रयासों के बाद धन्यवाद काम करने के लिए मिल गया :-(

Exif हमेशा काम करने लगता है, कठिनाई फ़ाइलपथ को प्राप्त करने की थी। मुझे मिला कोड एपीआई के बीच 4.4 से अधिक और 4.4 के बाद एक अलग बनाता है। मूल रूप से 4.4+ के लिए चित्र URI में "com.android.providers" है। इस प्रकार के URI के लिए, कोड पिक्चर आईडी प्राप्त करने के लिए डॉक्यूमेंट्सकंट्रैक्ट का उपयोग करता है और फिर ContentResolver का उपयोग करके एक क्वेरी चलाता है, जबकि पुराने SDK के लिए, कोड सीधे URI को ContentResolver के साथ क्वेरी करने के लिए जाता है।

यहाँ कोड है (क्षमा करें, मैं इसे पोस्ट करने वाले को क्रेडिट नहीं कर सकता):

/**
 * Handles pre V19 uri's
 * @param context
 * @param contentUri
 * @return
 */
public static String getPathForPreV19(Context context, Uri contentUri) {
    String res = null;

    String[] proj = { MediaStore.Images.Media.DATA };
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    if(cursor.moveToFirst()){;
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        res = cursor.getString(column_index);
    }
    cursor.close();

    return res;
}

/**
 * Handles V19 and up uri's
 * @param context
 * @param contentUri
 * @return path
 */
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPathForV19AndUp(Context context, Uri contentUri) {
    String wholeID = DocumentsContract.getDocumentId(contentUri);

    // Split at colon, use second item in the array
    String id = wholeID.split(":")[1];
    String[] column = { MediaStore.Images.Media.DATA };

    // where id is equal to
    String sel = MediaStore.Images.Media._ID + "=?";
    Cursor cursor = context.getContentResolver().
            query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    column, sel, new String[]{ id }, null);

    String filePath = "";
    int columnIndex = cursor.getColumnIndex(column[0]);
    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }

    cursor.close();
    return filePath;
}

public static String getRealPathFromURI(Context context,
        Uri contentUri) {
    String uriString = String.valueOf(contentUri);
    boolean goForKitKat= uriString.contains("com.android.providers");

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && goForKitKat) {
            Log.i("KIKAT","YES");
            return getPathForV19AndUp(context, contentUri);
        } else {

            return getPathForPreV19(context, contentUri);
        }
}

आपके लिए बहुत धन्यवाद। शाप और एक्सफ़ि स के साथ घंटों काम करने के बाद, यह बचा हुआ दिन हो सकता है। जैसा कि आपने कहा, वास्तव में एक्सिस में कर्सर रिटर्न के बजाय सही और विश्वसनीय डेटा है। बस इसे काम करने की तुलना में सही रास्ता दें।
asozcan

3

आप बस एसडी कार्ड से रास्ता पढ़ सकते हैं और निम्न कोड कर सकते हैं ... यह मौजूदा तस्वीर को बदलने के बाद इसे बदल देगा ..

नहीं: Exif अधिकांश उपकरणों पर काम नहीं करता है, यह गलत डेटा देता है, इसलिए आपको किसी भी डिग्री को सहेजने से पहले घूर्णन को कठिन कोड के लिए अच्छा है, आपको बस उस कोण मान को बदलना होगा जो आप चाहते हैं।

    String photopath = tempphoto.getPath().toString();
    Bitmap bmp = BitmapFactory.decodeFile(photopath);

    Matrix matrix = new Matrix();
    matrix.postRotate(90);
    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

    FileOutputStream fOut;
    try {
        fOut = new FileOutputStream(tempphoto);
        bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
        fOut.flush();
        fOut.close();

    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

2
यह घूमने के लिए है लेकिन हमें नहीं पता कि छवि को रोटेशन की आवश्यकता है या नहीं।
मसूदी

3

कोटलिन कोड:

if (file.exists()){
    val bitmap = BitmapFactory.decodeFile(file.absolutePath)

    val exif = ExifInterface(file.absoluteFile.toString())
    val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
    val matrix = Matrix()

    when(orientation){
        ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90F)
        ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180F)
        ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270F)
    }

    val rotatedBitmap = Bitmap.createBitmap(bitmap, 0,0 , bitmap.width, bitmap.height, matrix, true)
    bitmap.recycle()
    iv_capture.setImageBitmap(rotatedBitmap)
}

2

मैं Teo Inke द्वारा जवाब पर सुधार हुआ। यह अब छवि को घुमाता नहीं है जब तक कि यह वास्तव में आवश्यक न हो। पढ़ना भी आसान है, और तेजी से चलना चाहिए।

// Load Image
Bitmap bitmap = BitmapFactory.decodeFile(filePath);

// Rotate Image if Needed
try
{
    // Determine Orientation
    ExifInterface exif = new ExifInterface(filePath);
    int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

    // Determine Rotation
    int rotation = 0;
    if      (orientation == 6)      rotation = 90;
    else if (orientation == 3)      rotation = 180;
    else if (orientation == 8)      rotation = 270;

    // Rotate Image if Necessary
    if (rotation != 0)
    {
        // Create Matrix
        Matrix matrix = new Matrix();
        matrix.postRotate(rotation);

        // Rotate Bitmap
        Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 

        // Pretend none of this ever happened!
        bitmap.recycle();
        bitmap = rotated;
        rotated = null;
     }
}
catch (Exception e)
{
    // TODO: Log Error Messages Here
}

// TODO: Use Result Here
xxx.setBitmap(bitmap);

2

पहली चीज़ जो आपको चाहिए वह है असली फ़ाइल पथ यदि आपके पास यह बहुत अच्छा है, यदि आप यूआरआई का उपयोग कर रहे हैं तो वास्तविक जीवन प्राप्त करने के लिए इस विधि का उपयोग करें:

 public static String getRealPathFromURI(Uri contentURI,Context context) {
    String path= contentURI.getPath();
    try {
        Cursor cursor = context.getContentResolver().query(contentURI, null, null, null, null);
        cursor.moveToFirst();
        String document_id = cursor.getString(0);
        document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
        cursor.close();

        cursor = context.getContentResolver().query(
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }
    catch(Exception e)
    {
        return path;
    }
    return path;
}

उदाहरण के लिए अपना बिटमैप निकालें:

  try {
                            Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);

                        }
                        catch (IOException e)
                        {
                            Log.e("IOException",e.toString());
                        }

यदि आप चाहें तो आप डिकोडाइल () का उपयोग कर सकते हैं।

अब जब आपके पास बिटमैप है और वास्तविक पथ को ओरिएंटेशन ऑफ़ द इमेज मिलता है:

 private static int getExifOrientation(String src) throws IOException {
        int orientation = 1;

        ExifInterface exif = new ExifInterface(src);
        String orientationString=exif.getAttribute(ExifInterface.TAG_ORIENTATION);
        try {
            orientation = Integer.parseInt(orientationString);
        }
        catch(NumberFormatException e){}

        return orientation;
    }

और अंत में इसे सही स्थिति में घुमाएं जैसे:

public static Bitmap rotateBitmap(String src, Bitmap bitmap) {
        try {
            int orientation = getExifOrientation(src);

            if (orientation == 1) {
                return bitmap;
            }

            Matrix matrix = new Matrix();
            switch (orientation) {
                case 2:
                    matrix.setScale(-1, 1);
                    break;
                case 3:
                    matrix.setRotate(180);
                    break;
                case 4:
                    matrix.setRotate(180);
                    matrix.postScale(-1, 1);
                    break;
                case 5:
                    matrix.setRotate(90);
                    matrix.postScale(-1, 1);
                    break;
                case 6:
                    matrix.setRotate(90);
                    break;
                case 7:
                    matrix.setRotate(-90);
                    matrix.postScale(-1, 1);
                    break;
                case 8:
                    matrix.setRotate(-90);
                    break;
                default:
                    return bitmap;
            }

            try {
                Bitmap oriented = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                bitmap.recycle();
                return oriented;
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                return bitmap;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

यही है, अब आपके पास बिटमैप सही स्थिति में घुमाया गया है।

खुश होती है।


1

यह काम करता है, लेकिन शायद इसे करने का सबसे अच्छा तरीका नहीं है, लेकिन यह किसी की मदद कर सकता है।

String imagepath = someUri.getAbsolutePath();
imageview = (ImageView)findViewById(R.id.imageview);
imageview.setImageBitmap(setImage(imagepath, 120, 120));    

public Bitmap setImage(String path, final int targetWidth, final int targetHeight) {
    Bitmap bitmap = null;
// Get exif orientation     
    try {
        ExifInterface exif = new ExifInterface(path);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
        if (orientation == 6) {
            orientation_val = 90;
        }
        else if (orientation == 3) {
            orientation_val = 180;
        }
        else if (orientation == 8) {
            orientation_val = 270;
        }
    }
        catch (Exception e) {
        }

        try {
// First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(path, options);

// Adjust extents
            int sourceWidth, sourceHeight;
            if (orientation_val == 90 || orientation_val == 270) {
                sourceWidth = options.outHeight;
                sourceHeight = options.outWidth;
            } else {
                sourceWidth = options.outWidth;
                sourceHeight = options.outHeight;
            }

// Calculate the maximum required scaling ratio if required and load the bitmap
            if (sourceWidth > targetWidth || sourceHeight > targetHeight) {
                float widthRatio = (float)sourceWidth / (float)targetWidth;
                float heightRatio = (float)sourceHeight / (float)targetHeight;
                float maxRatio = Math.max(widthRatio, heightRatio);
                options.inJustDecodeBounds = false;
                options.inSampleSize = (int)maxRatio;
                bitmap = BitmapFactory.decodeFile(path, options);
            } else {
                bitmap = BitmapFactory.decodeFile(path);
            }

// Rotate the bitmap if required
            if (orientation_val > 0) {
                Matrix matrix = new Matrix();
                matrix.postRotate(orientation_val);
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            }

// Re-scale the bitmap if necessary
            sourceWidth = bitmap.getWidth();
            sourceHeight = bitmap.getHeight();
            if (sourceWidth != targetWidth || sourceHeight != targetHeight) {
                float widthRatio = (float)sourceWidth / (float)targetWidth;
                float heightRatio = (float)sourceHeight / (float)targetHeight;
                float maxRatio = Math.max(widthRatio, heightRatio);
                sourceWidth = (int)((float)sourceWidth / maxRatio);
                sourceHeight = (int)((float)sourceHeight / maxRatio);
                bitmap = Bitmap.createScaledBitmap(bitmap, sourceWidth,     sourceHeight, true);
            }
        } catch (Exception e) {
        }
        return bitmap;
    }

1

शायद यह मदद करेगा (90 डिग्री घुमाएँ) (यह मेरे लिए काम किया)

private Bitmap rotateBitmap(Bitmap image){
        int width=image.getHeight();
        int height=image.getWidth();

        Bitmap srcBitmap=Bitmap.createBitmap(width, height, image.getConfig());

        for (int y=width-1;y>=0;y--)
            for(int x=0;x<height;x++)
                srcBitmap.setPixel(width-y-1, x,image.getPixel(x, y));
        return srcBitmap;

    }

1

इसे खोलने के बाद कर्सर को बंद कर देना चाहिए।

यहाँ एक उदाहरण है।

 public static int getOrientation(Context context, Uri selectedImage)
{
    int orientation = -1;
    Cursor cursor = context.getContentResolver().query(selectedImage,
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
    if (cursor.getCount() != 1)
       return orientation;

    cursor.moveToFirst();
    orientation = cursor.getInt(0);
    cursor.close(); // ADD THIS LINE
   return orientation;
}

1

मैंने @Timmmm उत्तर और @ मैनुअल को पिघला दिया है। यदि आप इस समाधान को करते हैं, तो आपको रन आउट ऑफ़ मेमोरी एक्सेप्शन नहीं मिलेगा।

यह विधि छवि अभिविन्यास को पुनः प्राप्त करती है:

private static final int ROTATION_DEGREES = 90;
// This means 512 px
private static final Integer MAX_IMAGE_DIMENSION = 512;

public static int getOrientation(Uri photoUri) throws IOException {

    ExifInterface exif = new ExifInterface(photoUri.getPath());
    int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

    switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            orientation = ROTATION_DEGREES;
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            orientation = ROTATION_DEGREES * 2;
            break;
        case ExifInterface.ORIENTATION_ROTATE_270:
            orientation = ROTATION_DEGREES * 3;
            break;
        default:
            // Default case, image is not rotated
            orientation = 0;
    }

    return orientation;
}

इसलिए, आप मेमोरी पर लोड करने से पहले छवि को आकार देने के लिए इस विधि का उपयोग करेंगे। उस तरह से, आपको मेमोरी एक्सेप्शन नहीं मिलेगा।

public static Bitmap getCorrectlyOrientedImage(Context context, Uri photoUri) throws IOException {
    InputStream is = context.getContentResolver().openInputStream(photoUri);
    BitmapFactory.Options dbo = new BitmapFactory.Options();
    dbo.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(is, null, dbo);
    is.close();

    int rotatedWidth, rotatedHeight;
    int orientation = getOrientation(photoUri);

    if (orientation == 90 || orientation == 270) {
        rotatedWidth = dbo.outHeight;
        rotatedHeight = dbo.outWidth;
    } else {
        rotatedWidth = dbo.outWidth;
        rotatedHeight = dbo.outHeight;
    }

    Bitmap srcBitmap;
    is = context.getContentResolver().openInputStream(photoUri);
    if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) {
        float widthRatio = ((float) rotatedWidth) / ((float) MAX_IMAGE_DIMENSION);
        float heightRatio = ((float) rotatedHeight) / ((float) MAX_IMAGE_DIMENSION);
        float maxRatio = Math.max(widthRatio, heightRatio);

        // Create the bitmap from file
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = (int) maxRatio;
        srcBitmap = BitmapFactory.decodeStream(is, null, options);
    } else {
        srcBitmap = BitmapFactory.decodeStream(is);
    }
    is.close();

    // if the orientation is not 0, we have to do a rotation.
    if (orientation > 0) {
        Matrix matrix = new Matrix();
        matrix.postRotate(orientation);

        srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(),
                srcBitmap.getHeight(), matrix, true);
    }

    return srcBitmap;
}

यह मेरे लिए पूरी तरह से काम करता है। मुझे उम्मीद है कि यह किसी और की मदद करता है


0

छवि को सीमा के भीतर फिट करने के लिए कुछ अतिरिक्त स्केलिंग जोड़ने के लिए टिम्म्म द्वारा उपरोक्त समाधान पर सुधार करना:

public static Bitmap loadBitmap(String path, int orientation, final int targetWidth, final int targetHeight) {
    Bitmap bitmap = null;
    try {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Adjust extents
        int sourceWidth, sourceHeight;
        if (orientation == 90 || orientation == 270) {
            sourceWidth = options.outHeight;
            sourceHeight = options.outWidth;
        } else {
            sourceWidth = options.outWidth;
            sourceHeight = options.outHeight;
        }

        // Calculate the maximum required scaling ratio if required and load the bitmap
        if (sourceWidth > targetWidth || sourceHeight > targetHeight) {
            float widthRatio = (float)sourceWidth / (float)targetWidth;
            float heightRatio = (float)sourceHeight / (float)targetHeight;
            float maxRatio = Math.max(widthRatio, heightRatio);
            options.inJustDecodeBounds = false;
            options.inSampleSize = (int)maxRatio;
            bitmap = BitmapFactory.decodeFile(path, options);
        } else {
            bitmap = BitmapFactory.decodeFile(path);
        }

        // Rotate the bitmap if required
        if (orientation > 0) {
            Matrix matrix = new Matrix();
            matrix.postRotate(orientation);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }

        // Re-scale the bitmap if necessary
        sourceWidth = bitmap.getWidth();
        sourceHeight = bitmap.getHeight();
        if (sourceWidth != targetWidth || sourceHeight != targetHeight) {
            float widthRatio = (float)sourceWidth / (float)targetWidth;
            float heightRatio = (float)sourceHeight / (float)targetHeight;
            float maxRatio = Math.max(widthRatio, heightRatio);
            sourceWidth = (int)((float)sourceWidth / maxRatio);
            sourceHeight = (int)((float)sourceHeight / maxRatio);
            bitmap = Bitmap.createScaledBitmap(bitmap, sourceWidth, sourceHeight, true);
        }
    } catch (Exception e) {
    }
    return bitmap;
}

0

छवि को सही ढंग से घुमाने के लिए निम्न कोड का उपयोग करें:

private Bitmap rotateImage(Bitmap bitmap, String filePath)
{
    Bitmap resultBitmap = bitmap;

    try
    {
        ExifInterface exifInterface = new ExifInterface(filePath);
        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);

        Matrix matrix = new Matrix();

        if (orientation == ExifInterface.ORIENTATION_ROTATE_90)
        {
            matrix.postRotate(ExifInterface.ORIENTATION_ROTATE_90);
        }
        else if (orientation == ExifInterface.ORIENTATION_ROTATE_180)
        {
            matrix.postRotate(ExifInterface.ORIENTATION_ROTATE_180);
        }
        else if (orientation == ExifInterface.ORIENTATION_ROTATE_270)
        {
            matrix.postRotate(ExifInterface.ORIENTATION_ROTATE_270);
        }

        // Rotate the bitmap
        resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }
    catch (Exception exception)
    {
        Logger.d("Could not rotate the image");
    }
    return resultBitmap;
}

यदि एक साथ छोटे कोड होने पर आप सभी शर्तों को मिला सकते हैं।
चंद्रवंशी

0

अभिविन्यास के अनुसार स्केल और नीचे बिटमैप को घुमाता है:

public Bitmap scaleAndRotateImage(String path, int orientation, final int targetWidth, final int targetHeight)
{
    Bitmap bitmap = null;

    try
    {
        // Check the dimensions of the Image
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Adjust the Width and Height
        int sourceWidth, sourceHeight;
        if (orientation == 90 || orientation == 270)
        {
            sourceWidth = options.outHeight;
            sourceHeight = options.outWidth;
        }
        else
        {
            sourceWidth = options.outWidth;
            sourceHeight = options.outHeight;
        }

        // Calculate the maximum required scaling ratio if required and load the bitmap
        if (sourceWidth > targetWidth || sourceHeight > targetHeight)
        {
            float widthRatio = (float)sourceWidth / (float)targetWidth;
            float heightRatio = (float)sourceHeight / (float)targetHeight;
            float maxRatio = Math.max(widthRatio, heightRatio);
            options.inJustDecodeBounds = false;
            options.inSampleSize = (int)maxRatio;
            bitmap = BitmapFactory.decodeFile(path, options);
        }
        else
        {
            bitmap = BitmapFactory.decodeFile(path);
        }

        // We need to rotate the bitmap (if required)
        int orientationInDegrees = exifToDegrees(orientation);
        if (orientation > 0)
        {
            Matrix matrix = new Matrix();
            if (orientation != 0f)
            {
                matrix.preRotate(orientationInDegrees);
            };

            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        }

        // Re-scale the bitmap if necessary
        sourceWidth = bitmap.getWidth();
        sourceHeight = bitmap.getHeight();

        if (sourceWidth != targetWidth || sourceHeight != targetHeight)
        {
            float widthRatio = (float)sourceWidth / (float)targetWidth;
            float heightRatio = (float)sourceHeight / (float)targetHeight;
            float maxRatio = Math.max(widthRatio, heightRatio);
            sourceWidth = (int)((float)sourceWidth / maxRatio);
            sourceHeight = (int)((float)sourceHeight / maxRatio);
            bitmap = Bitmap.createScaledBitmap(bitmap, sourceWidth, sourceHeight, true);
        }
    }
    catch (Exception e)
    {
        Logger.d("Could not rotate the image");
        Logger.d(e.getMessage());
    }
    return bitmap;
}

उदाहरण:

public void getPictureFromDevice(Uri Uri,ImageView imageView)
{
    try
    {
        ExifInterface exifInterface = new ExifInterface(Uri.getPath());
        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

        Bitmap bitmap = scaleAndRotateImage(Uri.getPath(), orientation, imageView.getWidth(), imageView.getHeight());
        imageView.setImageBitmap(bitmap);
    }
    catch (OutOfMemoryError outOfMemoryError)
    {
        Logger.d(outOfMemoryError.getLocalizedMessage());
        Logger.d("Failed to load image from filePath (out of memory)");
        Logger.d(Uri.toString());
    }
    catch (Exception e)
    {
        Logger.d("Failed to load image from filePath");
        Logger.d(Uri.toString());
    }
}

-3

मैंने निम्नलिखित समाधान के साथ समस्या को हल किया। ध्यान दें कि मैं उस छवि को भी स्केल कर रहा हूं, जो आउटऑफमेरी एक्ससेप्शन से बचने के लिए आवश्यक था।

खबरदार कि यह समाधान पोर्ट्रेट छवियों या अपसाइड-डाउन छवियों के साथ ठीक से काम नहीं करेगा (आपको ध्यान में रखने के लिए धन्यवाद)। यदि आवश्यक हो तो टिम्म्म का समाधान बेहतर विकल्प हो सकता है और यह अधिक सुरुचिपूर्ण दिखता है, भी: https://stackoverflow.com/a/8914291/449918

File path = // ... location of your bitmap file
int w = 512; int h = 384; // size that does not lead to OutOfMemoryException on Nexus One
Bitmap b = BitmapFactory.decodeFile(path);


// Hack to determine whether the image is rotated
boolean rotated = b.getWidth() > b.getHeight();

Bitmap resultBmp = null;

// If not rotated, just scale it
if (!rotated) {
    resultBmp = Bitmap.createScaledBitmap(b, w, h, true);
    b.recycle();
    b = null;

// If rotated, scale it by switching width and height and then rotated it
} else {
    Bitmap scaledBmp = Bitmap.createScaledBitmap(b, h, w, true);
    b.recycle();
    b = null;

    Matrix mat = new Matrix();
    mat.postRotate(90);
    resultBmp = Bitmap.createBitmap(scaledBmp, 0, 0, h, w, mat, true);

    // Release image resources
    scaledBmp.recycle();
    scaledBmp = null;
}

// resultBmp now contains the scaled and rotated image

चियर्स


यह ठीक से काम नहीं कर रहा है। पोर्ट्रेट छवियों के बारे में क्या? उल्टा चित्र? एक्सिफ़ डेटा का उपयोग करना बेहतर है।
टिम्मम

यह मेरे एक ऐप में ठीक से काम करता है, लेकिन निश्चित रूप से मैंने सभी प्रकार के परिदृश्यों का परीक्षण नहीं किया है। @Timmmm कृपया अधिक विशिष्ट हो सकता है कि यह किन परिदृश्यों में काम नहीं करता है? मैं भी काफी हैरान हूं कि आपने मेरी पोस्ट को वोट दिया। यह एक संभावित समाधान साझा करने के लिए एक ईमानदार प्रयास के लिए काफी कठोर प्रतिक्रिया प्रतीत होती है।
मार्टिन

मेरा मतलब कठोर नहीं था; माफ़ करना! मैं सिर्फ यह नहीं चाहता था कि कोई आपके समाधान की नकल करे, यह उम्मीद करता है कि यह काम करेगा। जैसा कि मैंने कहा, यह चित्र या उल्टा छवियों के लिए काम नहीं करेगा। मैं उत्तर के रूप में सही समाधान जोड़ूंगा।
टिमम्म

समझा। मैं एक टिप्पणी जोड़ दूंगा जो आपके समाधान को पसंद करता है, जिसे ऊपर पसंद किया गया है।
मार्टिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.