কেন ক্যামেরা অভিপ্রায় ব্যবহার করে ক্যাপচার করা একটি চিত্র অ্যান্ড্রয়েডের কিছু ডিভাইসে ঘোরানো হয়?


376

আমি একটি চিত্র ক্যাপচার করছি এবং এটি চিত্রের দৃশ্যে সেট করছি।

public void captureImage() {

    Intent intentCamera = new Intent("android.media.action.IMAGE_CAPTURE");
    File filePhoto = new File(Environment.getExternalStorageDirectory(), "Pic.jpg");
    imageUri = Uri.fromFile(filePhoto);
    MyApplicationGlobal.imageUri = imageUri.getPath();
    intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intentCamera, TAKE_PICTURE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intentFromCamera) {
    super.onActivityResult(requestCode, resultCode, intentFromCamera);

    if (resultCode == RESULT_OK && requestCode == TAKE_PICTURE) {

        if (intentFromCamera != null) {
            Bundle extras = intentFromCamera.getExtras();
            if (extras.containsKey("data")) {
                bitmap = (Bitmap) extras.get("data");
            }
            else {
                bitmap = getBitmapFromUri();
            }
        }
        else {
            bitmap = getBitmapFromUri();
        }
        // imageView.setImageBitmap(bitmap);
        imageView.setImageURI(imageUri);
    }
    else {
    }
}

public Bitmap getBitmapFromUri() {

    getContentResolver().notifyChange(imageUri, null);
    ContentResolver cr = getContentResolver();
    Bitmap bitmap;

    try {
        bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, imageUri);
        return bitmap;
    }
    catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

তবে সমস্যাটি হ'ল প্রতিবার কিছু ডিভাইসে চিত্রটি ঘোরানো হয়। উদাহরণস্বরূপ, একটি স্যামসুং ডিভাইসে এটি ভাল কাজ করে তবে একটি সনি এক্সপেরিয়ায় চিত্রটি 90 ডিগ্রি এবং তোশিবা থ্রাইভ (ট্যাবলেট) 180 ডিগ্রি ঘোরানো হয় ।


1
আপনার মধ্যে এটি চেষ্টা করুন অ্যানড্রয়েডের ক্রিয়াকলাপটি প্রকাশ করুন: কনফিগারেশন = "ওরিয়েন্টেশন" অ্যান্ড্রয়েড: স্ক্রিন ওরিয়েন্টেশন = "প্রতিকৃতি"
নরেন্দ্র পাল

@ অনিক এটি কাজ করে না, এখন ছবিটি ট্যাবটিতে 180 ডিগ্রির পরিবর্তে 90 ডিগ্রীতে
ঘোরে যায়

1
যেমনটি আমি মনে করি আপনি যখন ক্যামেরা অ্যাপ্লিকেশানের সাথে লেনদেনের জন্য অভ্যন্তরীণ অভিপ্রায়টি ব্যবহার করেন, তখন এটি চিত্রটি ঘোরায়। এটি আপনার চিত্রটি ক্যাপচার করতে কীভাবে ডিভাইসটি ধরে রাখে তার উপর নির্ভরশীল। সুতরাং আপনি ব্যবহারকারীকে নির্দিষ্ট পদ্ধতিতে চিত্র নিতে সীমাবদ্ধ করতে পারেন এর অর্থ ব্যবহারকারী সর্বদা ডিভাইসটিকে প্রতিকৃতি বা ল্যান্ডস্কেপে ধারণ করে চিত্র ক্যাপচার করবে। এর পরে আপনি ইচ্ছেমতো ছবিটি পেতে এটি নির্দিষ্ট কোণে পরিবর্তন করতে পারেন .. বা অন্য বিকল্প, আপনার নিজের ক্যামেরা অ্যাপ্লিকেশন তৈরি করুন।
নরেন্দ্র পাল

@ নিক "আপনি ব্যবহারকারীকে নির্দিষ্ট পদ্ধতিতে চিত্র নিতে বাধা দিতে পারেন" এর অর্থ এটি কী সেটিং অরিয়েন্টেশন = "পোট্রেট" হিসাবে একই? এবং কীভাবে "এর পরে আপনি ইমেজ পেতে চান হিসাবে নির্দিষ্ট কোণে এটি পরিবর্তন করতে পারেন" অর্জন? দয়া করে আপনি কিছু দরকারী লিঙ্কগুলি দিতে পারেন
শিরীশ হারওয়াড

3
আমি বিশ্বাস করি ক্যাপচার অভিপ্রায়টি সর্বদা ডিফল্ট ক্যামেরা অ্যাপ্লিকেশন নিয়ে আসে যা প্রতিটি ডিভাইসে নির্দিষ্ট ওরিয়েন্টেশন এবং ফলস্বরূপ - স্থির ফটো ওরিয়েন্টেশন। এটি ব্যবহারকারীকে যেভাবে ডিভাইসটি ধরেছে বা আপনার ক্রিয়াকলাপের অভিপ্রায়কে কেন্দ্র করে তা নির্ভর করে না।
অ্যালেক্স কোহন

উত্তর:


440

বেশিরভাগ ফোন ক্যামেরা হ'ল ল্যান্ডস্কেপ, মানে আপনি যদি প্রতিকৃতিতে ছবি তুলেন, ফলস্বরূপ ছবিগুলি 90 ডিগ্রি ঘোরানো হবে। এই ক্ষেত্রে, ক্যামেরা সফ্টওয়্যারটি ফটোটি দেখতে হবে এমন দৃষ্টিভঙ্গি সহ এক্সিফ ডেটা পপুলেট করবে।

নোট করুন যে নীচের সমাধানটি ক্যামেরার সফ্টওয়্যার / ডিভাইস প্রস্তুতকারকের উপর নির্ভর করে এক্সিফ ডেটা তৈরি করে, তাই এটি বেশিরভাগ ক্ষেত্রে কাজ করবে তবে এটি 100% নির্ভরযোগ্য সমাধান নয়।

ExifInterface ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                     ExifInterface.ORIENTATION_UNDEFINED);

Bitmap rotatedBitmap = null;
switch(orientation) {

    case ExifInterface.ORIENTATION_ROTATE_90:
        rotatedBitmap = rotateImage(bitmap, 90);
        break;

    case ExifInterface.ORIENTATION_ROTATE_180:
        rotatedBitmap = rotateImage(bitmap, 180);
        break;

    case ExifInterface.ORIENTATION_ROTATE_270:
        rotatedBitmap = rotateImage(bitmap, 270);
        break;

    case ExifInterface.ORIENTATION_NORMAL:
    default:
        rotatedBitmap = bitmap;
}

rotateImageপদ্ধতিটি এখানে :

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

1
থেকে @JasonRobinson কোড আমি কীভাবে প্রকৃত অভিযোজন পেতে শিখতে সাথে সংমিশ্রিত করে এর এই কোড আমি সফলভাবে অভিযোজন পরিচালনা করুন।
রাদিত্য কুরিয়ান্তো

দ্বিতীয় প্যারামিটারটি ডিফল্ট মান হিসাবে exif.getAttributeIntব্যবহারের দ্বিতীয় বিকল্পটি ExifInterface.ORIENTATION_UNDEFINEDপ্রায় একই রকম, যদি ফাংশনটি মান প্রদান করতে ব্যর্থ হয়।
দর্পণ

5
এই কোডটি কোনও চিত্রের জন্য ইতিমধ্যে ডিস্কে লেখা হয়েছে, তাই না? ডিস্কে বিটম্যাপ লেখার বিষয়ে আমি এই পদ্ধতিটি ব্যবহার করে কোনও ফলাফল পাচ্ছি না।
থ্রেসিয়ান

4
এটি সর্বদা আমাকে 0 মান প্রদান করে। প্রকৃত অভিমুখীকরণ কীভাবে পাবেন তা দয়া করে বলুন।
অনুরাগ শ্রীবাস্তব

3
সর্বদা 0 পাওয়া, কোন ধারণা কেন?
নভ্য রামসান

186

মিশ্রন দ্বারা জেসন রবিনসন এর উত্তর দিয়ে ফেলিক্স s 'এর উত্তর এবং হারিয়ে যাওয়া অংশের ভর্তি, এখানে এই সমস্যার জন্য চূড়ান্ত সম্পূর্ণ সমাধান যে Android এর উপর এটা পরীক্ষার পর নিম্নলিখিত কি করতে হবে অ্যান্ড্রয়েড 4.1 ( জেলি বিন ), অ্যান্ড্রয়েড 4.4 ( কিটক্যাট ) এবং অ্যান্ড্রয়েড 5.0 ( ললিপপ )।

ধাপ

  1. চিত্রটি যদি 1024x1024 এর চেয়ে বড় হয় তবে এটি স্কেল করুন।

  2. অধিকার অভিযোজন ছবিতে ঘোরান শুধুমাত্র যদি এটা ঘোরান 90 180 বা 270 ডিগ্রী ছিল।

  3. মেমরির উদ্দেশ্যে ঘোরানো চিত্রটি পুনরায় চালিত করুন।

কোড অংশটি এখানে:

বর্তমান Contextএবং যে চিত্রটি URIআপনি ঠিক করতে চান তার সাথে নিম্নলিখিত পদ্ধতিটি কল করুন

/**
 * This method is responsible for solving the rotation issue if exist. Also scale the images to
 * 1024x1024 resolution
 *
 * @param context       The current context
 * @param selectedImage The Image URI
 * @return Bitmap image results
 * @throws IOException
 */
public static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage)
        throws IOException {
    int MAX_HEIGHT = 1024;
    int MAX_WIDTH = 1024;

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
    BitmapFactory.decodeStream(imageStream, null, options);
    imageStream.close();

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    imageStream = context.getContentResolver().openInputStream(selectedImage);
    Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);

    img = rotateImageIfRequired(context, img, selectedImage);
    return img;
}

CalculateInSampleSizeপূর্বোক্ত উত্স থেকে পদ্ধতিটি এখানে :

/**
  * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
  * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
  * the closest inSampleSize that will result in the final decoded bitmap having a width and
  * height equal to or larger than the requested width and height. This implementation does not
  * ensure a power of 2 is returned for inSampleSize which can be faster when decoding but
  * results in a larger bitmap which isn't as useful for caching purposes.
  *
  * @param options   An options object with out* params already populated (run through a decode*
  *                  method with inJustDecodeBounds==true
  * @param reqWidth  The requested width of the resulting bitmap
  * @param reqHeight The requested height of the resulting bitmap
  * @return The value to be used for inSampleSize
  */
private static int calculateInSampleSize(BitmapFactory.Options options,
                                         int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee a final image
        // with both dimensions larger than or equal to the requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

        // This offers some additional logic in case the image has a strange
        // aspect ratio. For example, a panorama may have a much larger
        // width than height. In these cases the total pixels might still
        // end up being too large to fit comfortably in memory, so we should
        // be more aggressive with sample down the image (=larger inSampleSize).

        final float totalPixels = width * height;

        // Anything more than 2x the requested pixels we'll sample down further
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;

        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }
    }
    return inSampleSize;
}

তারপরে এমন পদ্ধতি আসবে যা ঘূর্ণন কোণটি নির্ধারণের জন্য বর্তমান চিত্রের অরিয়েন্টেশন পরীক্ষা করবে

 /**
 * Rotate an image if required.
 *
 * @param img           The image bitmap
 * @param selectedImage Image URI
 * @return The resulted Bitmap after manipulation
 */
private static Bitmap rotateImageIfRequired(Context context, Bitmap img, Uri selectedImage) throws IOException {

InputStream input = context.getContentResolver().openInputStream(selectedImage);
ExifInterface ei;
if (Build.VERSION.SDK_INT > 23)
    ei = new ExifInterface(input);
else
    ei = new ExifInterface(selectedImage.getPath());

    int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

    switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            return rotateImage(img, 90);
        case ExifInterface.ORIENTATION_ROTATE_180:
            return rotateImage(img, 180);
        case ExifInterface.ORIENTATION_ROTATE_270:
            return rotateImage(img, 270);
        default:
            return img;
    }
}

অবশেষে ঘূর্ণন পদ্ধতি নিজেই

private static Bitmap rotateImage(Bitmap img, int degree) {
    Matrix matrix = new Matrix();
    matrix.postRotate(degree);
    Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
    img.recycle();
    return rotatedImg;
}

- তাদের প্রচেষ্টা এবং শিরীশ হার্ভেদে যারা এই সহায়ক প্রশ্নটি করেছিলেন তাদের উত্তরগুলির জন্য ভোট দিতে ভুলবেন না ।


2
এটি আমার জন্য পুরোপুরি নিখুঁত। ধন্যবাদ আপনাকে
শোহেল রানা

1
পদ্ধতিটি ঘোরান আইমেজআইফরিওয়ার্ড () খুব ভালভাবে কাজ করে .. ধন্যবাদ !!
mapo

5
আমার জন্য কাজ করে না। কখনও কখনও আমার ফোন প্রতিকৃতি দেয়, কখনও কখনও ল্যান্ডস্কেপ ফটো দেয় তবে সনাক্তকরণের দিকনির্দেশ সর্বদা 0 ডিগ্রি থাকে।
মাকালেলে

@ মাকালেলে কি এই সমস্যাটি ফটো তোলা এবং হোয়াটসঅ্যাপের মাধ্যমে সংযুক্ত করার সময় ঘটে?
মনোজ পেরুমারথ

আমি হোয়াটসঅ্যাপ ব্যবহার করি না তাই আমি বলতে পারি না তবে সম্ভবত হ্যাঁ। কারণ এটি এমনকি স্টক ফটো অ্যাপ্লিকেশনে (গুগল স্টক ক্যামেরা) এ ঘটে।
মাকালেলে

45

ইমেজ অরিয়েন্টেশন সনাক্তকরণ এবং বিটম্যাপটি ব্যবহার করে এটি ব্যবহার করা সহজ:

 /**
 * Rotate an image if required.
 * @param img
 * @param selectedImage
 * @return
 */
private static Bitmap rotateImageIfRequired(Context context,Bitmap img, Uri selectedImage) {

    // Detect rotation
    int rotation = getRotation(context, selectedImage);
    if (rotation != 0) {
        Matrix matrix = new Matrix();
        matrix.postRotate(rotation);
        Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
        img.recycle();
        return rotatedImg;
    }
    else{
        return img;
    }
}

/**
 * Get the rotation of the last image added.
 * @param context
 * @param selectedImage
 * @return
 */
private static int getRotation(Context context,Uri selectedImage) {

    int rotation = 0;
    ContentResolver content = context.getContentResolver();

    Cursor mediaCursor = content.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                                       new String[] { "orientation", "date_added" },
                                       null, null, "date_added desc");

    if (mediaCursor != null && mediaCursor.getCount() != 0) {
        while(mediaCursor.moveToNext()){
            rotation = mediaCursor.getInt(0);
            break;
        }
    }
    mediaCursor.close();
    return rotation;
}

বড় ছবি সহ স্মৃতি না এড়াতে, আমি আপনাকে ব্যবহার করে চিত্রটি পুনরুদ্ধার করার পরামর্শ দিচ্ছি:

private static final int MAX_HEIGHT = 1024;
private static final int MAX_WIDTH = 1024;
public static Bitmap decodeSampledBitmap(Context context, Uri selectedImage)
    throws IOException {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
    BitmapFactory.decodeStream(imageStream, null, options);
    imageStream.close();

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    imageStream = context.getContentResolver().openInputStream(selectedImage);
    Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);

    img = rotateImageIfRequired(img, selectedImage);
    return img;
}

ওরিয়েন্টেশন পাওয়ার জন্য এটি এক্সিফাইনটারফেস ব্যবহার করা উপযুক্ত নয় কারণ একটি অ্যান্ড্রয়েড ওএস ইস্যু: https://code.google.com/p/android/issues/detail?id=19268

এবং এখানে calculateInSampleSize

/**
 * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
 * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
 * the closest inSampleSize that will result in the final decoded bitmap having a width and
 * height equal to or larger than the requested width and height. This implementation does not
 * ensure a power of 2 is returned for inSampleSize which can be faster when decoding but
 * results in a larger bitmap which isn't as useful for caching purposes.
 *
 * @param options   An options object with out* params already populated (run through a decode*
 *                  method with inJustDecodeBounds==true
 * @param reqWidth  The requested width of the resulting bitmap
 * @param reqHeight The requested height of the resulting bitmap
 * @return The value to be used for inSampleSize
 */
public static int calculateInSampleSize(BitmapFactory.Options options,
                                        int reqWidth, int reqHeight) {

    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee a final image
        // with both dimensions larger than or equal to the requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

        // This offers some additional logic in case the image has a strange
        // aspect ratio. For example, a panorama may have a much larger
        // width than height. In these cases the total pixels might still
        // end up being too large to fit comfortably in memory, so we should
        // be more aggressive with sample down the image (=larger inSampleSize).

        final float totalPixels = width * height;

        // Anything more than 2x the requested pixels we'll sample down further
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;

        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }
    }
    return inSampleSize;
}

1
এখানে হিসাববিজ্ঞাপনের পদ্ধতি কী
মধু কোটাগিরি

1
@ মধুকাটাগিরি এখানে আপনার গণনার জন্য প্রয়োগকরণের উদাহরণ রয়েছে: নমুনা আকার
ফেলিক্স

থ্যাঙ্কস ম্যান, আপনি অবশ্যই একজন! আমি ঠিক ভাবছি যে অপারেশনটি মাঝে মাঝে সঞ্চালন করা হলে পুনরায় আকারটি কতটা কার্যকর হবে।
মেরিনো

4
উরি নির্বাচিত ইমেজ পরামিতি getRotation (...) পদ্ধতিতে ব্যবহৃত হয় না। আমাদের এটি কীভাবে দরকার? ধন্যবাদ.
valerybodak

1
প্যারামিটার 'সিলেক্ট ইমেজ' কোথাও ব্যবহার করা হবে বলে মনে হয় না। কোন কারণ আছে?
অ্যালেক্স

20

একটি লাইন সমাধান:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

অথবা

Picasso.with(context).load("file:" + photoPath).into(imageView);

এটি ঘূর্ণনটি স্বয়ংচালিত করবে এবং চিত্রকে সঠিক দিকনির্দেশে স্থাপন করবে

আপনার অ্যাপ্লিকেশনটিতে চিত্রগুলি পরিচালনা করার জন্য পিকাসো হ'ল একটি শক্তিশালী পাঠাগার min


1
আকর্ষণীয় সমাধান
ভবিক মেহতা

8
এটি কেবলমাত্র একটি ভিউতে চিত্রটি লোড করে, এটি আপনাকে কোনও বিটম্যাপ বা কোনও ফাইল দেয় না যা আপনি কোনও সার্ভারে ম্যানিপুলেট করতে বা আপলোড করতে পারেন।
flawyte

4
এর প্রদর্শিত চিত্রটি যেমন রয়েছে তেমন ক্লিক করা হয়েছে। এটি প্রয়োজনীয় হিসাবে ঘুরছে না।
সীমা

1
@ ফ্লাইয়েট আপনি কলব্যাকের সাহায্যে ফাইলের পরিবর্তে টার্গেটে লোড করে এটি করতে পারবেন যা ক্রপড / পুনরায় আকারিত বিটম্যাপটি ফিরে আসে: পিকাসো.উইথ (এই) .লোড (ক্রপউরিটোলোড.স্রাইজ (1080, 810)। সেন্টারআইনসাইড ()। এর মধ্যে (লক্ষ্য); যেখানে লক্ষ্য = নতুন টার্গেট () it বিটম্যাপলয়েড (বিটম্যাপ বিটম্যাপ, পিকাসো.লয়েডফর্ম থেকে) ওভাররাইড করুন te
ভয়েটেজ

আমি এখনও যে সমস্যার মুখোমুখি হয়েছি তা চিত্র প্রদর্শিত হতে কয়েক সেকেন্ড সময় নেয়
আনু

12

আমি এর সমাধান খুঁজতে অনেক সময় ব্যয় করেছি। এবং অবশেষে এটি করতে পরিচালিত। @ জেসন রবিনসন উত্তরটিকে উস্কে দিতে ভুলবেন না কারণ আমার তার উপর ভিত্তি করে।

তাই প্রথমত, আপনি জানেন যে অ্যান্ড্রয়েড 7.0 যেহেতু আমাদের ব্যবহার করতে হবে FileProviderএবং এর কিছু বলা আছে ContentUri, অন্যথায় আপনি আপনার কাছে যাওয়ার চেষ্টা করে বিরক্তিকর ত্রুটি পাবেন Intent। এটি নমুনা কোড:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriFromPath(context, "[Your path to save image]"));
startActivityForResult(intent, CAPTURE_IMAGE_RESULT);

পদ্ধতি getUriFromPath(Context, String)Android এর ব্যবহারকারী সংস্করণের উপর ভিত্তি তৈরি FileUri (file://...)বা ContentUri (content://...)তা থাকে:

public Uri getUriFromPath(Context context, String destination) {
    File file =  new File(destination);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        return FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
    } else {
        return Uri.fromFile(file);
    }
}

onActivityResultআপনি uriযেখানে ক্যামেরা দ্বারা চিত্রটি সংরক্ষণ করা হয়েছে তা ধরার পরে , তবে এখন আপনাকে ক্যামেরার আবর্তন সনাক্ত করতে হবে, এখানে আমরা সংশোধিত @ জেসন রবিনসন উত্তরটি ব্যবহার করব:

প্রথমে আমাদের ExifInterfaceউপর ভিত্তি করে তৈরি করা দরকারUri

@Nullable
public ExifInterface getExifInterface(Context context, Uri uri) {
    try {
        String path = uri.toString();
        if (path.startsWith("file://")) {
            return new ExifInterface(path);
        }
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (path.startsWith("content://")) {
                InputStream inputStream = context.getContentResolver().openInputStream(uri);
                return new ExifInterface(inputStream);
            }
        }
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

উপরে কোড সরলীকৃত করা যেতে পারে, তবে আমি সবকিছু দেখাতে চাই। সুতরাং FileUriআমরা এর ExifInterfaceউপর ভিত্তি করে তৈরি করতে পারি String path, তবে ContentUriআমরা পারি না, অ্যান্ড্রয়েড সেটিকে সমর্থন করে না।

সেক্ষেত্রে আমাদের উপর ভিত্তি করে অন্যান্য কনস্ট্রাক্টর ব্যবহার করতে হবে InputStream। মনে রাখবেন এই নির্মাতা ডিফল্টরূপে উপলভ্য নয়, আপনাকে অতিরিক্ত পাঠাগার যুক্ত করতে হবে:

compile "com.android.support:exifinterface:XX.X.X"

এখন আমরা getExifInterfaceআমাদের কোণ পেতে পদ্ধতি ব্যবহার করতে পারি :

public float getExifAngle(Context context, Uri uri) {
    try {
        ExifInterface exifInterface = getExifInterface(context, uri);
        if(exifInterface == null) {
            return -1f;
        }

        int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED);

        switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                return 90f;
            case ExifInterface.ORIENTATION_ROTATE_180:
                return 180f;
            case ExifInterface.ORIENTATION_ROTATE_270:
                return 270f;
            case ExifInterface.ORIENTATION_NORMAL:
                return 0f;
            case ExifInterface.ORIENTATION_UNDEFINED:
                return -1f;
            default:
                return -1f;
        }
    }
    catch (Exception e) {
        e.printStackTrace();
        return -1f;
    }
}

আপনার চিত্রটি সঠিকভাবে আবর্তিত করার জন্য এখন আপনার কাছে কোণ রয়েছে :)।


2
বাস্তবায়ন 'androidx.exifinterface: exifinterface: XXX' এটি তাদের জন্য যারা অ্যান্ড্রয়েডেক্স ব্যবহার করছেন। আপনার পোস্টিংয়ের জন্য আপনাকে ধন্যবাদ
দোঙ্গসিল

11
// Try this way,hope this will help you to solve your problem...

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center">
        <ImageView
            android:id="@+id/imgFromCameraOrGallery"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_launcher"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btnCamera"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="Camera"/>
        <Button
            android:id="@+id/btnGallery"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_marginLeft="5dp"
            android:layout_height="wrap_content"
            android:text="Gallery"/>

    </LinearLayout>
</LinearLayout>

MainActivity.java

    public class MainActivity extends Activity {

    private ImageView imgFromCameraOrGallery;
    private Button btnCamera;
    private Button btnGallery;

    private String imgPath;
    final private int PICK_IMAGE = 1;
    final private int CAPTURE_IMAGE = 2;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imgFromCameraOrGallery = (ImageView) findViewById(R.id.imgFromCameraOrGallery);
        btnCamera = (Button) findViewById(R.id.btnCamera);
        btnGallery = (Button) findViewById(R.id.btnGallery);

        btnCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, setImageUri());
                startActivityForResult(intent, CAPTURE_IMAGE);
            }
        });

        btnGallery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent, ""), PICK_IMAGE);
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == CAPTURE_IMAGE) {
                setCapturedImage(getImagePath());
            } else if (requestCode == PICK_IMAGE) {
                imgFromCameraOrGallery.setImageBitmap(BitmapFactory.decodeFile(getAbsolutePath(data.getData())));
            }
        }

    }

    private String getRightAngleImage(String photoPath) {

        try {
            ExifInterface ei = new ExifInterface(photoPath);
            int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            int degree = 0;

            switch (orientation) {
                case ExifInterface.ORIENTATION_NORMAL:
                    degree = 0;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
                case ExifInterface.ORIENTATION_UNDEFINED:
                    degree = 0;
                    break;
                default:
                    degree = 90;
            }

            return rotateImage(degree,photoPath);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return photoPath;
    }

    private String rotateImage(int degree, String imagePath){

        if(degree<=0){
            return imagePath;
        }
        try{
            Bitmap b= BitmapFactory.decodeFile(imagePath);

            Matrix matrix = new Matrix();
            if(b.getWidth()>b.getHeight()){
                matrix.setRotate(degree);
                b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(),
                        matrix, true);
            }

            FileOutputStream fOut = new FileOutputStream(imagePath);
            String imageName = imagePath.substring(imagePath.lastIndexOf("/") + 1);
            String imageType = imageName.substring(imageName.lastIndexOf(".") + 1);

            FileOutputStream out = new FileOutputStream(imagePath);
            if (imageType.equalsIgnoreCase("png")) {
                b.compress(Bitmap.CompressFormat.PNG, 100, out);
            }else if (imageType.equalsIgnoreCase("jpeg")|| imageType.equalsIgnoreCase("jpg")) {
                b.compress(Bitmap.CompressFormat.JPEG, 100, out);
            }
            fOut.flush();
            fOut.close();

            b.recycle();
        }catch (Exception e){
            e.printStackTrace();
        }
        return imagePath;
    }

    private void setCapturedImage(final String imagePath){
        new AsyncTask<Void,Void,String>(){
            @Override
            protected String doInBackground(Void... params) {
                try {
                    return getRightAngleImage(imagePath);
                }catch (Throwable e){
                    e.printStackTrace();
                }
                return imagePath;
            }

            @Override
            protected void onPostExecute(String imagePath) {
                super.onPostExecute(imagePath);
                imgFromCameraOrGallery.setImageBitmap(decodeFile(imagePath));
            }
        }.execute();
    }

    public Bitmap decodeFile(String path) {
        try {
            // Decode deal_image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(path, o);
            // The new size we want to scale to
            final int REQUIRED_SIZE = 1024;

            // Find the correct scale value. It should be the power of 2.
            int scale = 1;
            while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE)
                scale *= 2;
            // Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            return BitmapFactory.decodeFile(path, o2);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getAbsolutePath(Uri uri) {
        if(Build.VERSION.SDK_INT >= 19){
            String id = "";
            if(uri.getLastPathSegment().split(":").length > 1)
                id = uri.getLastPathSegment().split(":")[1];
            else if(uri.getLastPathSegment().split(":").length > 0)
                id = uri.getLastPathSegment().split(":")[0];
            if(id.length() > 0){
                final String[] imageColumns = {MediaStore.Images.Media.DATA };
                final String imageOrderBy = null;
                Uri tempUri = getUri();
                Cursor imageCursor = getContentResolver().query(tempUri, imageColumns, MediaStore.Images.Media._ID + "=" + id, null, imageOrderBy);
                if (imageCursor.moveToFirst()) {
                    return imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
                }else{
                    return null;
                }
            }else{
                return null;
            }
        }else{
            String[] projection = { MediaStore.MediaColumns.DATA };
            Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null) {
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            } else
                return null;
        }

    }

    private Uri getUri() {
        String state = Environment.getExternalStorageState();
        if(!state.equalsIgnoreCase(Environment.MEDIA_MOUNTED))
            return MediaStore.Images.Media.INTERNAL_CONTENT_URI;

        return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    }

    public Uri setImageUri() {
        Uri imgUri;
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/",getString(R.string.app_name) + Calendar.getInstance().getTimeInMillis() + ".png");
            imgUri = Uri.fromFile(file);
            imgPath = file.getAbsolutePath();
        }else {
            File file = new File(getFilesDir() ,getString(R.string.app_name) + Calendar.getInstance().getTimeInMillis()+ ".png");
            imgUri = Uri.fromFile(file);
            this.imgPath = file.getAbsolutePath();
        }
        return imgUri;
    }

    public String getImagePath() {
        return imgPath;
    }
}

নিখুঁত সমাধান হরেশ ভাই
সাগর পিঠিয়া

9

আপনি ডকুমেন্টেশনে গুগলের দ্বারা নির্দেশিত ক্যামেরার সেন্সরের ওরিয়েন্টেশনটি কেবলমাত্র পড়তে পারেন: https://developer.android.com/references/android/hardware/camera2/CameraCharacterics.html

SENSOR_ORIENTATION

Added in API level 21
Key<Integer> SENSOR_ORIENTATION
Clockwise angle through which the output image needs to be rotated to be upright on the device screen in its native orientation.

Also defines the direction of rolling shutter readout, which is from top to bottom in the sensor's coordinate system.

Units: Degrees of clockwise rotation; always a multiple of 90

Range of valid values:
0, 90, 180, 270

This key is available on all devices.

কোডের উদাহরণ:

CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
int orientation = 0;
try {
    String cameraId = manager.getCameraIdList()[0];
    CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
    orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
}
catch (Exception e)
{
}

6

জেসন রবিনসনের উত্তর এবং সামি এলটামাউয়ের উত্তর দুর্দান্ত

অ্যাপ্রোচ সম্পূর্ণ করার জন্য কেবল একটি উন্নতি, আপনার কমপিট এক্সিফিন্টারফেস ব্যবহার করা উচিত।

com.android.support:exifinterface:${lastLibVersion}

"ফাইল পাওয়া যায় নি ব্যতিক্রমগুলি" এড়ানো আপনি ইউরি পাথের পরিবর্তে InputStream(থেকে ContentResolver) এক্সিফিন্টারফেস (পিয়র এপিআই <24) ইনস্ট্যান্ট করতে সক্ষম হবেন

https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html


4

সাধারণত জেসি রবিনসন যেমন পরামর্শ দিয়েছিলেন ঠিক তেমনই ExifInterface নিয়ে সমস্যাটি সমাধান করার পরামর্শ দেওয়া হয়। যদি এই পদ্ধতির কাজ না হয় তবে আপনি নেওয়া সর্বশেষ চিত্রটির ওরিয়েন্টেশনটি দেখার চেষ্টা করতে পারেন ...

private int getImageOrientation(){
    final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION };
    final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
    Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            imageColumns, null, null, imageOrderBy);

    if(cursor.moveToFirst()){
        int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION));
        cursor.close();
        return orientation;
    } else {
        return 0;
    }
}

1
আমি মনে করি এই কোডটি কেবলমাত্র ডিগ্রি ঘূর্ণন ঘটেছিল তা সনাক্ত করে। এখন আমি এটি করতে সক্ষম, কিন্তু পরবর্তী কার্যে অক্ষম অর্থাৎ চিত্রটি ঘোরানো।
শিরিশ হেরওয়াদে

আপনি ঠিক বলেছেন, তবে আপনি এই থ্রেডে আবর্তনের জন্য জিজ্ঞাসা করেননি, তাই আসুন এটি পরিষ্কার রাখুন;) এজন্য আমি আপনার ঘোরানো সমস্যার উত্তরটি আমার অন্য থ্রেডে রেখেছি ... আশা করি এটি সাহায্য করে, এটি কাজ করে আমি: স্ট্যাকওভারফ্লো
ক্রিস কনওয়ে

4

দুঃখের বিষয়, উপরে @ জেসন-রবিনসন উত্তর আমার পক্ষে কাজ করে নি।

যদিও ঘোরানো ফাংশন পুরোপুরি কাজ করে:

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

এক্সিফ ওরিয়েন্টেশন সবসময় 0 থাকায় ওরিয়েন্টেশন পেতে আমাকে নিম্নলিখিত কাজগুলি করতে হয়েছিল

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode,resultCode,data);
    if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && data != null) {
            Uri selectedImage = data.getData();
            String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
            Cursor cur = managedQuery(imageUri, orientationColumn, null, null, null);
            int orientation = -1;
            if (cur != null && cur.moveToFirst()) {
                    orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
            }
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);
            Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
            switch(orientation) {
                    case 90:
                            bitmap = rotateImage(chosen_image_bitmap, 90);
                            break;
                    case 180:
                            bitmap = rotateImage(chosen_image_bitmap, 180);
                            break;
                    case 270:
                            bitmap = rotateImage(chosen_image_bitmap, 270);
                            break;
                    default:
                            break;
            }
            imageView.setImageBitmap(bitmap );

1
আলওয়্যাসিস 0, সামসং 7
ডিজেড্যান্স

2

একটি নির্দিষ্ট অরিয়েন্টেশনে ছবি তুলতে আরও ভাল চেষ্টা করুন।

android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"

সেরা ফলাফলের জন্য ক্যামেরাভিউ ক্রিয়াকলাপে ল্যান্ডস্কেপ ওরিয়েন্টেশন দিন।


দুঃখিত, এটি কাজ করে না প্রকৃতপক্ষে ট্যাবে, অ্যাক্টিভিটিআরসাল্টের সম্পাদন শেষ করার পরে প্রতিবারই আশ্চর্যজনকভাবে অনক্রিট কল হয়।
শিরীশ হারওয়াদে

1
দুঃখিত, সমস্যাটি যেমন রয়েছে তেমন
শিরীশ হার্ভাডে

2

সঙ্গে কারো অভিজ্ঞতা সমস্যার তাহলে ExifInterfaceউপর অ্যান্ড্রয়েড 4.4 (KitKat) বিশিষ্ট অভিযোজন পাবার জন্য, এটা ভুল কারণ হতে পারে পাথ কোনো URI থেকে পেয়েছিলাম। getPathস্ট্যাক ওভারফ্লো প্রশ্নে প্রোপোয়ারের একটি সমাধান দেখুন ইউআরআই, অ্যান্ড্রয়েড কিটকাট নতুন স্টোরেজ অ্যাক্সেস ফ্রেমওয়ার্কের কাছ থেকে আসল পথ পান


এই একটি মন্তব্য আমার প্রয়োজন ছিল। বাবু, তোমাকে অনেক ধন্যবাদ
জোয়েল নেইম্যান


1

নির্বাচিত উত্তরগুলি এই এবং অনুরূপ প্রশ্নের উত্তরগুলির মধ্যে সবচেয়ে সাধারণ পদ্ধতি ব্যবহার করে। তবে স্যামসাংয়ের সামনে এবং পিছনের উভয় ক্যামেরার সাথে এটি কাজ করে না। স্যামসুং এবং অন্যান্য বড় নির্মাতাদের জন্য সামনের এবং পিছনের উভয় ক্যামেরা জুড়ে কাজ করে এমন সমাধানের সন্ধানকারীদের জন্য, এনভৌসিডের এই উত্তরটি দুর্দান্ত:

https://stackoverflow.com/a/18915443/6080472

যারা ক্লিক করতে চান না তাদের জন্য প্রাসঙ্গিক যাদু হ'ল ক্যামেরাআইএনফো ব্যবহার করা বরং এক্সআইএফের উপর নির্ভর করা।

Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length);
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(mCurrentCameraId, info);
Bitmap bitmap = rotate(realImage, info.orientation);

লিঙ্কে সম্পূর্ণ কোড।


না, বিভিন্ন কোণে ভুল রোটেশন (স্মাগং এস 7)। আমি অবশ্যই গ্যালারী বলতে চাই
djdance

1

এটি সম্ভবত বলার অপেক্ষা রাখে না তবে সর্বদা মনে রাখবেন যে আপনি নিজের সার্ভারে ইমেজ হ্যান্ডলিংয়ের কয়েকটি বিষয় পরিচালনা করতে পারেন। আমি চিত্রটির তাত্ক্ষণিক প্রদর্শনটি পরিচালনা করতে এই থ্রেডে থাকা প্রতিক্রিয়াগুলির মতো ব্যবহার করেছি। তবে আমার অ্যাপ্লিকেশনটির চিত্রগুলি সার্ভারে সঞ্চয় করা দরকার (আপনি যদি ব্যবহারকারীদের ফোনের স্যুইচ হিসাবে চিত্রটি অবিরত রাখতে চান তবে এটি সম্ভবত একটি সাধারণ প্রয়োজন)।

এই বিষয়ের সাথে সম্পর্কিত অনেকগুলি থ্রেডে থাকা সমাধানগুলি বিআইটিএম্যাপের চিত্র সংকোচনে টিকবে না এমন EXIF ​​ডেটার অধ্যবসায়ের অভাব নিয়ে আলোচনা করে না, অর্থাত আপনার সার্ভারটি যখন এটি লোড করবে তখন আপনাকে চিত্রটি ঘোরানো দরকার। বিকল্পভাবে, আপনি আপনার সার্ভারে EXIF ​​ওরিয়েন্টেশন ডেটা প্রেরণ করতে পারেন, এবং তারপরে প্রয়োজনে চিত্রটি ঘোরান।

সার্ভারে স্থায়ী সমাধান তৈরি করা আমার পক্ষে সহজ ছিল কারণ অ্যান্ড্রয়েডের গোপনীয় ফাইলের পাথ সম্পর্কে আমাকে কোনও চিন্তা করতে হবে না।


চিত্র ক্যাপচারের সময় আপনি একবারে এটি ঘোরতে পারেন এবং সেভাবে সংরক্ষণ করতে পারেন যাতে এটি আর কখনও ঘোরানোর দরকার হয় না?
jk7

হ্যাঁ আপনি করতে পারেন এবং এটিই আসলে প্রক্রিয়াটি আমি শেষ পর্যন্ত বাস্তবায়ন করে শেষ করেছি। অ্যান্ড্রয়েড ফোনে চিত্রটি থেকে ফাইলের পথটি পেতে আমার সমস্যা হয়েছে যা আমাকে এটি করতে দেয়। এটি এই উত্তরটি সাহায্য করেছিল: stackoverflow.com/a/36714242/5443056
ব্র্যাডেন হল্ট

1

এই সমস্যার সহজ সমাধান:

captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
                   characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION));

আমি ছবিটি jpg ফর্ম্যাটে সংরক্ষণ করছি।


0

Xamarin.Androidসংস্করণটি এখানে :

@ জেসন রবিনসনের উত্তর থেকে :

Bitmap rotate(Bitmap bitmap, int angle)
{
    var matrix = new Matrix();
    matrix.PostRotate(angle);

    return Bitmap.CreateBitmap(bitmap, 0, 0, bitmap.Width, bitmap.Height, matrix, true);
}

Bitmap rotateIfRequired(Bitmap bitmap, string imagePath)
{
    var ei = new ExifInterface(imagePath);
    var orientation = ei.GetAttributeInt(ExifInterface.TagOrientation, (int)Android.Media.Orientation.Undefined);

    switch (orientation)
    {
        case (int)Android.Media.Orientation.Rotate90: return rotate(bitmap, 90);
        case (int)Android.Media.Orientation.Rotate180: return rotate(bitmap, 180);
        case (int)Android.Media.Orientation.Rotate270: return rotate(bitmap, 270);
        default: return bitmap;
    }
}

তারপরে calculateInSampleSizeপদ্ধতি:

int calculateInSampleSize(BitmapFactory.Options options, int reqW, int reqH)
{
    float h = options.OutHeight;
    float w = options.OutWidth;
    var inSampleSize = 1;

    if (h > reqH || w > reqW)
    {
        if (reqH == 0) inSampleSize = (int)Math.Floor(w / reqW);
        else if (reqW == 0) inSampleSize = (int)Math.Floor(h / reqH);
        else
        {
            var hRatio = (int)Math.Floor(h / reqH);
            var wRatio = (int)Math.Floor(w / reqW);
            inSampleSize = false ? Math.Max(hRatio, wRatio) : Math.Min(hRatio, wRatio);
        }
    }

    return inSampleSize;
}

@ সামি এলটামাউয়ের উত্তর থেকে :

Bitmap handleSamplingAndRotationBitmap(string imagePath)
{
    var maxHeight = 1024;
    var maxWidth = 1024;

    var options = new BitmapFactory.Options();
    options.InJustDecodeBounds = true;
    BitmapFactory.DecodeFile(imagePath, options);

    options.InSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);

    options.InJustDecodeBounds = false;

    var bitmap = BitmapFactory.DecodeFile(imagePath, options);

    bitmap = rotateIfRequired(bitmap, imagePath);

    return bitmap;
}

0

আপনি যদি ফ্রেস্কো ব্যবহার করেন তবে আপনি এটি ব্যবহার করতে পারেন -

final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)
.setRotationOptions(RotationOptions.autoRotate())
.build();

mSimpleDraweeView.setController(
Fresco.newDraweeControllerBuilder()
    .setImageRequest(imageRequest)
    .build());

এটি এক্সিফ ডেটার উপর ভিত্তি করে চিত্রগুলি স্বয়ংক্রিয়ভাবে ঘোরে।

সূত্র: https://frescolib.org/docs/rotation.html


0

নীচের কোডটি আমার সাথে কাজ করেছিল, এটি ফাইলআউরি থেকে বিটম্যাপ পেয়েছে এবং প্রয়োজনে রোটেশন ফিক্সিংও করুন:

    private fun getCapturedImage(selectedPhotoUri: Uri): Bitmap {
        val bitmap = when {
            Build.VERSION.SDK_INT < 28 -> MediaStore.Images.Media.getBitmap(
                this.contentResolver,
                selectedPhotoUri
            )
            else -> {
                val source = ImageDecoder.createSource(this.contentResolver, selectedPhotoUri)
                ImageDecoder.decodeBitmap(source)
            }
        }

        // If the image is rotated, fix it
        return when (ExifInterface(contentResolver.run { openInputStream(selectedPhotoUri) }).getAttributeInt(
            ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)) {
            ExifInterface.ORIENTATION_ROTATE_90 ->
                Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, Matrix().apply {
                    postRotate(90F) }, true)
            ExifInterface.ORIENTATION_ROTATE_180 ->
                Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, Matrix().apply {
                    postRotate(180F) }, true)
            ExifInterface.ORIENTATION_ROTATE_270 ->
                Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, Matrix().apply {
                    postRotate(270F) }, true)
            else -> bitmap
        } 
    }

0

এক্সিফাইনটারফেস ব্যবহার না করেই এই সমস্যার উত্তর পেয়েছি । বিটম্যাপ তৈরি করার সময় আমরা ম্যাট্রিক্স.পোস্টরোটেট (ডিগ্রি) ব্যবহার করে বিটম্যাপটি ঘোরান either

public int getRotationDegree() {
    int degree = 0;

    for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            degree = info.orientation;

            return degree;
        }
    }

    return degree;
}

ঘূর্ণন গণনা করার পরে আপনি নীচের মত বিটম্যাপ ঘোরান:

 Matrix matrix = new Matrix();

 matrix.postRotate(getRotationDegree());

 Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);

হেরারে বিএম আপনার বিটম্যাপ হওয়া উচিত।

আপনি আপনার সামনের ক্যামেরা আবর্তনের জানতে চান শুধু পরিবর্তন Camera.CameraInfo.CAMERA_FACING_BACK করার Camera.CameraInfo.CAMERA_FACING_FRONT উপরে।

আশা করি এটা কাজে লাগবে.


1
ভয়াবহ উত্তর কিন্তু আমি ঘটনাক্রমে upvated। এই কোডটি ধরে নেয় আপনার গ্যালারী থেকে প্রতিটি চিত্র আপনার ক্যামেরা দিয়ে তৈরি । এটি ক্ষেত্রে নয়
জুন

-1

আমি একটি কোটলিন এক্সটেনশন ফাংশন তৈরি করেছি যা @ জেসন রবিনসনের উত্তরের ভিত্তিতে কোটলিন বিকাশকারীদের জন্য অপারেশনটিকে সহজতর করে। আমি আসা করি এটা সাহায্য করবে.

fun Bitmap.fixRotation(uri: Uri): Bitmap? {

    val ei = ExifInterface(uri.path)

    val orientation: Int = ei.getAttributeInt(
        ExifInterface.TAG_ORIENTATION,
        ExifInterface.ORIENTATION_UNDEFINED
    )

    return when (orientation) {
        ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage( 90f)
        ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage( 180f)
        ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage( 270f)
        ExifInterface.ORIENTATION_NORMAL -> this
        else -> this
    }
}

fun Bitmap.rotateImage(angle: Float): Bitmap? {
    val matrix = Matrix()
    matrix.postRotate(angle)
    return Bitmap.createBitmap(
        this, 0, 0, width, height,
        matrix, true
    )
}

1
দুর্দান্ত কিন্তু এক্সটেনশন বা কোনও ফাংশন হিসাবে সমস্ত সমাধানের মতো একই সমস্যার সাথে ভুগছে - Android 10 এ কাজ করে না
লিওর ইলুজ

-2

এই ত্রুটিটি ঠিক করার জন্য আরও একটি সহজ কমান্ড রয়েছে।

কেবলমাত্র আপনার আইজামভিউ.সেটবিটম্যাপ (বিটম্যাপ) এর পরে যুক্ত করুন; এই আপনার ইমেজভিউ.সেটরোটেশন (90);

এই স্থির খনি। আশা করি এটা সাহায্য করবে !


6
ওপি যেমন বলেছে, কিছু ডিভাইস চিত্রটি ঘোরান না, কিছু এটিকে 90 ডিগ্রি, কিছু 180, ..সেটিকে ঘোরান। সুতরাং সর্বদা 90 টি ঘোরানো কিছু ক্ষেত্রে ভুল হবে।
jk7

-8

এটি আমার জন্য কাজ করেছে

ImageView display_image = findViewById(R.id.image);
this.display_image.setRotation(90);

হাহাকার কি এটাই। ক্যামেরায় তোলা ছবিটি কীভাবে জানবে -৯০ / 90/0 / ... ব্যবহারকারী সম্ভবত ল্যান্ডস্কেপ হিসাবে ছবি তুলছেন এবং আপনি যেটি ঘোরান তা বিবেচনা করেই নয় ... lmao
অ্যালেক্স

এই ক্ষেত্রে এটি আমার পক্ষে কাজ করেছে যেহেতু আমার ক্ষেত্রে ব্যবহারকারী সর্বদা ফোনটির সাথে উল্লম্বভাবে ছবিটি তুলবেন।
খ্রিস্টান এডুয়ার্ডো গালাদামেজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.