बिटमैप के Android फसल केंद्र


150

मेरे पास बिटमैप हैं जो वर्ग या आयत हैं। मैं सबसे छोटा पक्ष लेता हूं और कुछ ऐसा करता हूं:

int value = 0;
if (bitmap.getHeight() <= bitmap.getWidth()) {
    value = bitmap.getHeight();
} else {
    value = bitmap.getWidth();
}

Bitmap finalBitmap = null;
finalBitmap = Bitmap.createBitmap(bitmap, 0, 0, value, value);

तो मैं इसे एक 144 x 144 बिटमैप का उपयोग करके इसे स्केल करता हूं:

Bitmap lastBitmap = null;
lastBitmap = Bitmap.createScaledBitmap(finalBitmap, 144, 144, true);

समस्या यह है कि यह मूल बिटमैप के शीर्ष बाएँ कोने में फ़सल करता है, किसी के पास बिटमैप के केंद्र को क्रॉप करने के लिए कोड है?

जवाबों:


354

यहाँ छवि विवरण दर्ज करें

इसके साथ प्राप्त किया जा सकता है: Bitmap.createBitmap (स्रोत, x, y, चौड़ाई, ऊंचाई)

if (srcBmp.getWidth() >= srcBmp.getHeight()){

  dstBmp = Bitmap.createBitmap(
     srcBmp, 
     srcBmp.getWidth()/2 - srcBmp.getHeight()/2,
     0,
     srcBmp.getHeight(), 
     srcBmp.getHeight()
     );

}else{

  dstBmp = Bitmap.createBitmap(
     srcBmp,
     0, 
     srcBmp.getHeight()/2 - srcBmp.getWidth()/2,
     srcBmp.getWidth(),
     srcBmp.getWidth() 
     );
}

1
उत्तर को संपादित किया ताकि वास्तविक गंतव्य बिटमैप एक वर्ग हो।
जोरम वैन डेन बोएजम

1
@ लुमिस: आपने 3 में संशोधन क्यों किया? यह एक वैध सही प्रतीत हुआ। आपका वर्तमान संस्करण सही प्रारंभिक बिंदु बनाता है, लेकिन फिर बहुत लंबा पक्ष शेष है। उदाहरण के लिए, आपको दी गई 100x1000छवि वापस मिल जाती है 100x550
ग्वेंटे

धन्यवाद, आप सही हैं, प्रारूप Bitmap.createBitmap (स्रोत, x, y, चौड़ाई, ऊंचाई) है
Lumis

11
अंतर्निहित ThumbnailUtils.extractThumbnail () विधि का उपयोग करने के बारे में मेरा उत्तर देखें। पहिया को क्यों मजबूत करें ??? stackoverflow.com/a/17733530/1103584
DiscDev

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

319

जबकि ऊपर दिए गए अधिकांश उत्तर ऐसा करने का एक तरीका प्रदान करते हैं, इसे पूरा करने के लिए पहले से ही एक अंतर्निहित तरीका है और यह कोड की 1 पंक्ति है ( ThumbnailUtils.extractThumbnail())

int dimension = getSquareCropDimensionForBitmap(bitmap);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);

...

//I added this method because people keep asking how 
//to calculate the dimensions of the bitmap...see comments below
public int getSquareCropDimensionForBitmap(Bitmap bitmap)
{
    //use the smallest dimension of the image to crop to
    return Math.min(bitmap.getWidth(), bitmap.getHeight());
}

यदि आप चाहते हैं कि बिटमैप ऑब्जेक्ट को पुनर्नवीनीकरण किया जाए, तो आप ऐसे विकल्प पारित कर सकते हैं जो इसे बनाते हैं:

bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);

से: थंबनेल दस्तावेज़

सार्वजनिक स्थैतिक बिटमैप निष्कर्षण थम्बनेल (बिटमैप स्रोत, इंट चौड़ाई, इंट ऊंचाई)

एपीआई स्तर 8 में जोड़ा गया वांछित आकार का एक केंद्रित बिटमैप बनाता है।

पैरामीटर स्रोत मूल बिटमैप स्रोत चौड़ाई लक्षित चौड़ाई ऊंचाई लक्षित ऊंचाई

स्वीकृत उत्तर का उपयोग करते समय मैं कभी-कभी मेमोरी त्रुटियों से बाहर निकल रहा था, और थम्बनेल यूटिल्स का उपयोग करके मेरे लिए उन मुद्दों को हल किया। इसके अलावा, यह बहुत क्लीनर और अधिक पुन: प्रयोज्य है।


6
+1 मुझे लगता है कि आपको इस कोड में सुधार करना होगा और 400px का उपयोग करने के बजाय, ऊपर के मूल पद के लिए एक विकल्प प्रदान करने के लिए सबसे छोटे bmp के आकार को पास करना होगा। लेकिन हमारे ध्यान में लाने के लिए धन्यवाद, यह एक बहुत उपयोगी कार्य है। अफ़सोस कि मैंने इसे पहले नहीं देखा है ...
लुमिस

ठीक है, मैं सिर्फ एक ठोस उदाहरण देने के लिए 400 हार्डकोड करता हूं ... विवरण कार्यान्वयनकर्ता तक हैं :)
डिस्कवरी

4
@DiscDev - यह इस पूरी साइट पर सबसे उपयोगी उत्तरों में से एक है। गंभीरता से। यह एंड्रॉइड सवालों के साथ अजीब है - आप साधारण स्पष्ट उत्तर खोजने से पहले अक्सर दो घंटे खोज सकते हैं। पता नहीं कैसे आपको पर्याप्त धन्यवाद। बाउंटी एन मार्ग!
फेटी

2
आप पुराने बिटमैप को रीसायकल करने के लिए थोड़ा अलग फ़ंक्शन का भी उपयोग कर सकते हैं: = ThumbnailUtils.extractThumbnail (बिटमैप, चौड़ाई, ऊँचाई, ThumbnailUtils.OPTIONS_RECCCLE_INPUT)
Android डेवलपर

1
यह सबसे शक्तिशाली उत्तर है जो मैंने अब तक Android प्रश्न के लिए देखा है। मैंने 20 अलग-अलग समाधानों की तरह देखा है कि एंड्रॉइड पर बिटमैप पर स्केल / क्रॉप / डाउनस्केल / आकार और इतने पर कैसे। सभी उत्तर अलग-अलग हैं। और यह सिर्फ 1 लाइन लेता है और उम्मीद के मुताबिक काम करता है। धन्यवाद।
एलेक्स सोरोकोलेटोव

12

क्या आपने ऐसा करने से माना है layout.xml? आप अपने लिए सेट कर सकते हैं ScaleType करने और में चित्र के आयाम सेट के अंदर ।ImageViewandroid:scaleType="centerCrop"ImageViewlayout.xml


मैंने इस विचार को निम्नलिखित OpenGLRenderer त्रुटि के साथ आज़माया: "बिटमैप को बनावट में अपलोड करने के लिए बहुत बड़ा (2432x4320, अधिकतम = 4096x4096)" तो, मुझे लगता है कि 4320 की ऊँचाई को संसाधित नहीं किया जा सकता है।
ग्रेग जूल 15'14

1
बेशक यह एक सही जवाब है और सवाल का सही जवाब देता है! बड़ी छवि के लिए छवि गुणवत्ता / आकार का अनुकूलन ... खैर, यह एक अलग सवाल है!
इखलोस

@ichalos शायद आपको वह मिला जो आप ढूंढ रहे थे, लेकिन यह मूल प्रश्न का उत्तर नहीं देता है। मूल प्रश्न कैनवस पर मैन्युअल रूप से रेंडर करने के बारे में था .. वास्तव में, मुझे यकीन नहीं है कि किसी को फोटो क्रॉप करने का पहला प्रयास मैन्युअल रूप से एक कैनवास पर कैसे किया जाएगा, लेकिन हे, अच्छा है कि आपको यहां एक समाधान मिला :)
milosmns

@milosmns शायद आप सही हैं। हो सकता है कि यह केवल उपयोगकर्ता ने केंद्र में मैन्युअल रूप से फसल की समस्या के लिए संपर्क करने का प्रयास किया हो। यह सब मूल उपयोगकर्ता की सटीक आवश्यकताओं पर निर्भर करता है।
इखलास

9

आप निम्नलिखित कोड का उपयोग कर सकते हैं जो आपकी समस्या को हल कर सकता है।

Matrix matrix = new Matrix();
matrix.postScale(0.5f, 0.5f);
Bitmap croppedBitmap = Bitmap.createBitmap(bitmapOriginal, 100, 100,100, 100, matrix, true);

ऊपर विधि क्रॉप करने से पहले छवि को पोस्ट-कॉलिंग करती है, इसलिए आप OOM त्रुटि प्राप्त किए बिना क्रॉप की गई छवि के साथ सर्वोत्तम परिणाम प्राप्त कर सकते हैं।

अधिक विवरण के लिए आप इस ब्लॉग को देख सकते हैं


1
E / AndroidRuntime (30010): इसके कारण: java.lang.IllegalArgumentException: x + चौड़ाई का होना चाहिए <= bitmap.width () और इसकी वजह से 4 गुना 100px
स्टेन

9

यहां एक अधिक संपूर्ण स्निपेट जो मनमाने आयामों के [बिटमैप] के केंद्र को बाहर निकालता है और आपके वांछित [IMAGE_SIZE] को परिणाम देता है । तो आपको हमेशा एक [क्रॉपबीटमैप] मिलेगा एक निश्चित आकार के साथ छवि केंद्र का स्केल्ड वर्ग । थंबनेल और इस तरह के लिए आदर्श।

इसका अन्य समाधानों का अधिक पूर्ण संयोजन है।

final int IMAGE_SIZE = 255;
boolean landscape = bitmap.getWidth() > bitmap.getHeight();

float scale_factor;
if (landscape) scale_factor = (float)IMAGE_SIZE / bitmap.getHeight();
else scale_factor = (float)IMAGE_SIZE / bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale_factor, scale_factor);

Bitmap croppedBitmap;
if (landscape){
    int start = (tempBitmap.getWidth() - tempBitmap.getHeight()) / 2;
    croppedBitmap = Bitmap.createBitmap(tempBitmap, start, 0, tempBitmap.getHeight(), tempBitmap.getHeight(), matrix, true);
} else {
    int start = (tempBitmap.getHeight() - tempBitmap.getWidth()) / 2;
    croppedBitmap = Bitmap.createBitmap(tempBitmap, 0, start, tempBitmap.getWidth(), tempBitmap.getWidth(), matrix, true);
}

8

संभवतः अब तक का सबसे आसान समाधान:

public static Bitmap cropCenter(Bitmap bmp) {
    int dimension = Math.min(bmp.getWidth(), bmp.getHeight());
    return ThumbnailUtils.extractThumbnail(bmp, dimension, dimension);
}

आयात:

import android.media.ThumbnailUtils;
import java.lang.Math;
import android.graphics.Bitmap;

3

@Willsteel समाधान को ठीक करने के लिए:

if (landscape){
                int start = (tempBitmap.getWidth() - tempBitmap.getHeight()) / 2;
                croppedBitmap = Bitmap.createBitmap(tempBitmap, start, 0, tempBitmap.getHeight(), tempBitmap.getHeight(), matrix, true);
            } else {
                int start = (tempBitmap.getHeight() - tempBitmap.getWidth()) / 2;
                croppedBitmap = Bitmap.createBitmap(tempBitmap, 0, start, tempBitmap.getWidth(), tempBitmap.getWidth(), matrix, true);
            }

यह विलसेल समाधान का एक समाधान है। इस मामले में, tempBitmap केवल मूल (अनअलेच्ड) बिटमैप या स्वयं की एक प्रति है।
यमन

1
public static Bitmap resizeAndCropCenter(Bitmap bitmap, int size, boolean recycle) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();
    if (w == size && h == size) return bitmap;
    // scale the image so that the shorter side equals to the target;
    // the longer side will be center-cropped.
    float scale = (float) size / Math.min(w,  h);
    Bitmap target = Bitmap.createBitmap(size, size, getConfig(bitmap));
    int width = Math.round(scale * bitmap.getWidth());
    int height = Math.round(scale * bitmap.getHeight());
    Canvas canvas = new Canvas(target);
    canvas.translate((size - width) / 2f, (size - height) / 2f);
    canvas.scale(scale, scale);
    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
    canvas.drawBitmap(bitmap, 0, 0, paint);
    if (recycle) bitmap.recycle();
    return target;
}

private static Bitmap.Config getConfig(Bitmap bitmap) {
    Bitmap.Config config = bitmap.getConfig();
    if (config == null) {
        config = Bitmap.Config.ARGB_8888;
    }
    return config;
}

1
public Bitmap getResizedBitmap(Bitmap bm) {
    int width = bm.getWidth();
    int height = bm.getHeight();

    int narrowSize = Math.min(width, height);
    int differ = (int)Math.abs((bm.getHeight() - bm.getWidth())/2.0f);
    width  = (width  == narrowSize) ? 0 : differ;
    height = (width == 0) ? differ : 0;

    Bitmap resizedBitmap = Bitmap.createBitmap(bm, width, height, narrowSize, narrowSize);
    bm.recycle();
    return resizedBitmap;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.