Android: BitmapFactory.decodeByteArray дает пикселизированный битовый массив

Я работаю над приложением для Android, которое отображает фотографии, которые загружаются с Flickr. Я получаю растровый объект из массива байтов, который в свою очередь читается из соответствующего URL Flickr, следующим образом:

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); 

Проблема состоит в том, что получившее изображение пикселизировано, и я не могу выяснить почему; я попробовал много изменений выбирания и крашу объекты без удачи. Различие между изображением, отображенным в моем приложении и изображением в исходном URL, примерно продемонстрировано следующим:

Плохо отобразите, посмотрите растрирование в верхнем левом углу http://homepages.inf.ed.ac.uk/s0677975/bad.jpg

Хорошее изображение, это - ожидаемый результат http://homepages.inf.ed.ac.uk/s0677975/good.jpg

Посмотрите, например, на облака в верхнем левом углу для наблюдения различия.

Обратите внимание, что изображения JPEG, которые загружены из ресурсов проекта и оттянуты похожим способом дисплей очень хорошо, т.е. не имеют никакого растрирования.

Кто-либо может дать мне подсказку относительно того, почему это происходит?

Для разработки немного массив байтов получен из Flickr следующим образом; это основано на коде из Фотопотокового приложения Romain Guy:

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();

PS: Я также отправил вариант этого вопроса на android.developer группе Google.


Большое спасибо за Ваше предложение - теперь я действительно озадачен! Я сделал, поскольку Вы предложили и нашли, что изображение, происходящее непосредственно от загруженного массива байтов, действительно пикселизировано. Однако это загружается с точно того же URL, который при доступе на моем компьютере НЕ пикселизирован. Вот соответствующий URL Flickr:

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

Еще более странный, когда я запускаю то же приложение в средстве моделирования, а не по моему телефону (HTC Hero), нет никакого растрирования.

Как же это возможно?

Ниже код, который я использую для загрузки битового массива от URL - это основано на Фотопотоковом приложении Romain Guy, и это включает предложение Will для записи необработанного массива байтов в файл:

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);
        }
    }
}

Я схожу с ума здесь? Лучше всего, Michael.

12
задан Brad Larson 24 November 2013 в 01:34
поделиться

2 ответа

Записать необработанные байты, полученные из URL, в /sdcard/tmp.jpg и просмотрите на своем ПК.

Изображения JPEG сжимаются в плитки 8x8 (или 16x16). «Пикселизация», как вы ее описываете, на самом деле присутствует в этих плитках, предполагая, что «плохое» изображение - это JPEG, который более агрессивно сжат, чем другой.

Таким образом, я ожидал, что реальная проблема заключается в том, что загружаемый образ является версией очень низкого качества, например один предназначен для использования в миниатюрах / предварительном просмотре.

3
ответ дан 2 December 2019 в 22:51
поделиться

Итак, я наконец понял: похоже, моя мобильная сеть выполняет сжатие изображений для экономии полосы пропускания.

Следовательно, изображение, загруженное с моего телефона, имеет более низкое качество, чем такое же изображение, загруженное с моего компьютера.

Это неприятно для моего приложения, но я не думаю, что что-то могу с этим поделать. Вздох.

Еще раз спасибо за ваш вклад!

С уважением, Майкл.

4
ответ дан 2 December 2019 в 22:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: