2010-02-02 13 views
12

देता है मैं एक एंड्रॉइड ऐप पर काम कर रहा हूं जो फ़्लिकर से डाउनलोड की गई तस्वीरों को प्रदर्शित करता है। मैं एक बाइट सरणी, जो बारी में प्रासंगिक फ़्लिकर URL से पढ़ा जाता है से एक बिटमैप वस्तु प्राप्त, इस प्रकार है:एंड्रॉइड: बिटमैपफैक्टरी.decodeByteArray पिक्सलेटेड बिटमैप

BitmapFactory.Options opt = new BitmapFactory.Options(); 
opt.inDither = true; 
opt.inPreferredConfig = Bitmap.Config.ARGB_8888; 
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt); 

मैं तो एक दृश्य वस्तु की OnDraw विधि में एक कैनवास पर बिटमैप आकर्षित:

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); 
canvas.drawBitmap(bitmap, 0, 0, paint); 

समस्या यह है कि परिणामी तस्वीर पिक्सलेट की गई है और मैं यह नहीं समझ सकता कि क्यों; मैंने भाग्य के साथ ऑप्ट और पेंट ऑब्जेक्ट्स की कई भिन्नताओं की कोशिश की है।

Bad image, see pixelation in top left corner http://homepages.inf.ed.ac.uk/s0677975/bad.jpg

Good picture, this is the expected result http://homepages.inf.ed.ac.uk/s0677975/good.jpg

देखो उदहारण के लिए: चित्र मेरे एप्लिकेशन में दिखाया गया है और मूल URL पर चित्र के बीच का अंतर लगभग पालन करके प्रदर्शित किया गया है अंतर देखने के लिए ऊपरी-बाएं कोने में बादलों पर।

ध्यान दें कि जेपीईजी चित्र जो परियोजना संसाधनों से लोड होते हैं और इसी तरह से प्रदर्शित होते हैं, ठीक है, यानी कोई पिक्सेलेशन नहीं है।

क्या कोई मुझे यह संकेत दे सकता है कि यह क्यों हो रहा है?

थोड़ा विस्तार करने के लिए, बाइट सरणी फ़्लिकर से निम्नानुसार प्राप्त की जाती है; इस रोमेन लड़का द्वारा फ़ोटोस्ट्रीम app से कोड पर आधारित है:

InputStream in = new BufferedInputStream(url.openStream(), IO_BUFFER_SIZE); 
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE); 
copy(in, out); 
out.flush(); 
final byte[] data = dataStream.toByteArray(); 

पुनश्च: मैं भी android.developer गूगल समूह पर इस सवाल का एक संस्करण था।


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

http://farm3.static.flickr.com/2678/4315351421_54e8cdb8e5.jpg

भी अजनबी, जब मैं सिम्युलेटर में के बजाय मेरे फोन (एक एचटीसी हीरो) पर एक ही अनुप्रयोग चलाने, वहाँ कोई पिक्सेलेशन है: यहाँ इसी फ़्लिकर यूआरएल है।

पृथ्वी पर यह कैसे संभव है?

नीचे कोड मैं किसी URL से एक बिटमैप लोड करने के लिए इस्तेमाल करते हैं - यह रोमेन लड़का द्वारा फ़ोटोस्ट्रीम एप्लिकेशन पर आधारित है, और यह विल के सुझाव कच्चे बाइट सरणी लिखने के लिए शामिल किया गया है दायर करने के लिए:

Bitmap loadPhotoBitmap(URL url) { 
    Bitmap bitmap = null; 
     InputStream in = null; 
     BufferedOutputStream out = null; 

     try { 

      FileOutputStream fos = new FileOutputStream("/sdcard/photo-tmp.jpg"); 
      BufferedOutputStream bfs = new BufferedOutputStream(fos); 

      in = new BufferedInputStream(url.openStream(), 
        IO_BUFFER_SIZE); 

      final ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 
      out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE); 
      copy(in, out);      
      out.flush(); 
      final byte[] data = dataStream.toByteArray(); 

      bfs.write(data, 0, data.length); 
      bfs.flush(); 

      BitmapFactory.Options opt = new BitmapFactory.Options(); 
      bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opt); 

     } catch (IOException e) { 
      android.util.Log.e(LOG_TAG, "Could not load photo: " + this, e); 
     } finally { 
      closeStream(in); 
      closeStream(out) 
      closeStream(bfs); 
     } 

     return bitmap; 
    } 

private static void copy(InputStream in, OutputStream out) throws IOException { 
    byte[] b = new byte[IO_BUFFER_SIZE]; 
    int read; 
    while ((read = in.read(b)) != -1) { 
     out.write(b, 0, read); 
    } 
} 

private static void closeStream(Closeable stream) { 
    if (stream != null) { 
     try { 
      stream.close(); 
     } catch (IOException e) { 
      android.util.Log.e(LOG_TAG, "Could not close stream", e); 
     } 
    } 
} 

क्या मैं यहाँ पागल हो रहा हूँ? बेस्ट, माइकल।

+0

मैंने छवियों को रेखांकित करने की स्वतंत्रता ली, क्योंकि आम तौर पर प्रश्न को अच्छे और पढ़ने में आसान बनाता है। – unwind

+1

क्या आपको कभी इसके लिए कोई समाधान मिला है? मैंने सुझावों का प्रयास किया है, लेकिन कोई भाग्य नहीं है। यह बहुत परेशान है। एक फुटनोट के रूप में – blork

+0

, यह न भूलें कि जेपीईजी एंड्रॉइड पर्यावरण में लापरवाह नहीं है। हालांकि यह समर्थित है, यह पीएनजी के पक्ष में निराश है। – user836725

उत्तर

3

URL से प्राप्त कच्चे बाइट /sdcard/tmp.jpg पर लिखें, और अपने पीसी पर देखें।

जेपीईजी छवियों को 8x8 (या 16x16) टाइल्स में संपीड़ित किया जाता है। जैसा कि आप वर्णन करते हैं 'पिक्सेलेशन' वास्तव में इन टाइल्स में है, यह बताते हुए कि 'खराब' छवि एक जेपीईजी है जो दूसरे की तुलना में अधिक आक्रामक रूप से संपीड़ित होती है।

तो मुझे उम्मीद है कि वास्तविक मुद्दा यह है कि डाउनलोड की जा रही छवि एक बहुत कम गुणवत्ता वाला संस्करण है, उदा। एक थंबनेलिंग/पूर्वावलोकन उपयोग मामलों के लिए इरादा है।

+0

मुझे यह भी संदेह था, लेकिन "खराब" छवि का वास्तविक फ़ाइल आकार "अच्छा" से लगभग 18% * बड़ा * है। Weirdness। – unwind

+0

यह कुछ भी साबित नहीं करता है :) – Will

4

ठीक है, इसलिए मुझे अंत में यह मिलता है: ऐसा लगता है कि मेरा मोबाइल नेटवर्क बैंडविड्थ को बचाने के लिए छवि संपीड़न करता है।

इसलिए मेरे फोन से डाउनलोड की गई तस्वीर मेरे कंप्यूटर से डाउनलोड की गई तस्वीर की तुलना में कम गुणवत्ता वाली है।

यह मेरे ऐप के लिए एक बमर है, लेकिन मुझे नहीं लगता कि मैं इसके बारे में कुछ भी कर सकता हूं। आह।

हालांकि आपके इनपुट के लिए धन्यवाद!

बेस्ट, माइकल।

+0

इसे http शीर्षलेख द्वारा भी प्रेरित किया जा सकता है - फेसबुक स्वयं मोबाइल फोन के लिए निम्न गुणवत्ता वाली छवियां प्रदान कर सकता है। भेजने से पहले हेडर संपादित करें - मूल रूप से, उन सभी को हटा दें! – Will

+1

आप http हेडर को Accept-Encoding gzip पर सेट करने का प्रयास कर सकते हैं। निश्चित नहीं है, लेकिन यह संभव है कि यह नेटवर्क छवि संपीड़न के आसपास हो जाएगा। Http://stackoverflow.com/questions/1573391/android-http-communication-should-use-accept-encoding-gzip –

+0

क्या आपने ब्राउज़र में छवि को डाउनलोड करने के माध्यम से इसकी पुष्टि करने का प्रयास किया है? मुझे एक ही समस्या है लेकिन यदि मैं वेब ब्राउज़र में छवि खोलता हूं तो मुझे एक अनपिक्सेल छवि मिलती है। इसलिए सही छवि प्राप्त करने का एक तरीका होना चाहिए। – Janusz

1

एंड्रॉइड के कुछ संस्करण में बिटमैप क्लास में एक बग है और कुछ ऑपरेशन पर बिटमैप को RGB_565 में परिवर्तित करें। यह आपकी तस्वीरों के समान कलाकृतियों में प्रकट होगा। यह नीले आकाश की बैंडिंग को भी समझाएगा। इसके अलावा, ध्यान रखें कि एंड्रॉइड संसाधन फ़ाइलों में लोडिंग और यहां तक ​​कि संकलित करने पर उन्हें rgb_565 में परिवर्तित करके छवि को "ऑप्टिमाइज़" करने का प्रयास करता है। इस पर एक नज़र डालें: http://android.nakatome.net/2010/04/bitmap-basics.html

संबंधित मुद्दे