Высокое разрешение экрана в Android - программирование

Высокое разрешение экрана в Android

Есть ли способ получить снимок экрана с высоким разрешением определенного вида в действии.

Я хочу преобразовать содержимое html моего веб-представления в PDF. Для этого я попытался снять снимок веб-контента, а затем преобразовал его в PDF с помощью itext. Полученный PDF файл не имеет большей ясности.

Мой код:

    protected void takeimg() {
    Picture picture = mWebView.capturePicture();
    Bitmap b = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),
            Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    picture.draw(c);

    // byte[] bt = b.getNinePatchChunk();

    // Bitmap b;
    // View v1 = mWebView.getRootView();
    // v1.setDrawingCacheEnabled(true);
    // b = Bitmap.createBitmap(v1.getDrawingCache());
    // v1.setDrawingCacheEnabled(false);

    FileOutputStream fos = null;
    try {
        File root = new File(Environment.getExternalStorageDirectory(),
                "Sample");

        if (!root.exists()) {
            root.mkdir();
        }
        String sdcardhtmlpath = root.getPath().toString() + "/"
                + "temp_1.png";

        fos = new FileOutputStream(sdcardhtmlpath);
        // fos = openFileOutput("samsp_1.jpg", MODE_WORLD_WRITEABLE);
        if (fos != null) {
            b.compress(Bitmap.CompressFormat.PNG, 100, fos);

            // fos.write(bt);
            fos.close();
        }
    } catch (Exception e) {
        Log.e("takeimg", e.toString());
        e.printStackTrace();

    }
}


protected void pdfimg() {
    Document mydoc = new Document(PageSize.A3);
    try {
        File root = new File(Environment.getExternalStorageDirectory(),
                "Sample");

        if (!root.exists()) {
            root.mkdir();
        }
        String sdcardhtmlpath = root.getPath().toString() + "/";
        mydoc.setMargins(0, 0, 0, 0);
        PdfWriter.getInstance(mydoc, new FileOutputStream(sdcardhtmlpath
                + PDFfilename));
        mydoc.open();
        Image image1 = Image.getInstance(sdcardhtmlpath + "temp_1.jpg");
        image1.scalePercent(95f);

        mydoc.add(image1);
        // mydoc.newPage();

        mydoc.close();
    } catch (Exception e) {
        Log.e("pdi name", e.toString());
    }
}
4b9b3361

Ответ 1

Обновление: см. Редактировать 3 для ответа на исходный вопрос

Есть два варианта:

  • Используйте библиотеку для преобразования HTML в PDF. Это, безусловно, лучший вариант, поскольку он (вероятно) сохранит текст в виде векторов.

  • Получите рендеринг высокого разрешения HTML и сохраните его как PNG (не PDF, конечно!).

Для HTML в PDF wkhtmltopdf выглядит неплохо, но он полагается на Qt, который вы не можете использовать на Android, Есть некоторые другие библиотеки, но я сомневаюсь, что они очень хорошо выполняют PDF-рендеринг.

Для получения веб-представления с высоким разрешением вы можете попробовать создать свой собственный WebView и вызвать onMeasure(...) и onLayout(...) и передать соответствующие параметры, чтобы представление было действительно большим. Затем вызовите onDraw(myOwnCanvas), и веб-просмотр будет привязан к вашему холсту, который может быть подкреплен Bitmap с помощью Canvas.setBitmap().

Скорее всего вы можете скопировать состояние в новый WebView, используя что-то вроде

screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());

Orrr, возможно, будет возможно использовать тот же WebView, просто временно измените его размер на большой, onDraw() на его холст и снова измените его размер. Это становится очень хаки!

Вы можете столкнуться с проблемами памяти, если вы сделаете ее слишком большой.

Изменить 1

Я подумал о третьем, точно-то, что вы хотите, но это вроде хардкор. Вы можете создать пользовательский Canvas, который записывает в PDF файл. Фактически, это почти легко, поскольку базовый Canvas - это Skia, который фактически включает в себя PDF-архив. К сожалению, у вас нет доступа к нему на Android, поэтому вам в основном нужно будет создать свою собственную копию на Android (есть инструкции) и дублировать/переопределять все методы Canvas, чтобы указать на вашу Skia вместо Андроиды. Обратите внимание, что существует соблазнительный метод Picture.writeToStream(), который сериализует данные Skia, но, к сожалению, этот формат не является передовым или обратным, поэтому, если вы его используете, ваш код, вероятно, будет работать только в нескольких версиях Android.

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

Изменить 2

На самом деле невозможно сделать свой собственный "перехват" Canvas. Я начал делать это и прошел через утомительный процесс сериализации всех вызовов функций. Некоторые из них вы не можете сделать, потому что они скрыты, но они не выглядели важными. Но в конце я пришел к сериализации Path только для того, чтобы обнаружить, что он написан только для записи. Для меня это похоже на убийцу, поэтому единственным вариантом является интерпретация результата Picture.writeToStream(). К счастью, используются только две версии этого формата, и они почти идентичны.

Редактировать 3 - Действительно простой способ получить изображение Bitmap с высоким разрешением

Хорошо, получается, что получение растрового изображения с высоким разрешением (которое может быть всем приложением) тривиально. Вот как получить двойное разрешение. Очевидно, что все растровые изображения выглядят немного дерьмовыми, но текст отображается в полном разрешении:

View window = activity.getWindow().getDecorView()

Canvas bitmapCanvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(window.getWidth()*2, window.getHeight()*2, Bitmap.Config.ARGB_8888);

bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.scale(2.0f, 2.0f);
window.draw(bitmapCanvas);

bitmap.compress(Bitmap.CompressFormat.PNG, 0, myOutputStream);

Работает как шарм. Теперь я отказался от получения скриншота PDF с векторным текстом. Это, конечно, возможно, но очень сложно. Вместо этого я работаю над получением PSD с высоким разрешением, где каждая операция рисования является отдельным слоем, что должно быть намного проще.

Изменить 4

Woa это становится немного длиннее, но успех! Я создал .xcf (GIMP) и PDF, где каждый слой - это другая операция рисования холста. Это не совсем так, как я ожидал, но все же, очень полезно!

На самом деле мой код просто выводит полноразмерные PNG, и я использовал "Open as layers..." и "Autocrop layer" в GIMP для создания этих файлов, но, конечно, вы можете сделать это в коде, если хотите. Я думаю, что я превращу это в сообщение в блоге.

Загрузите демонстрационный файл GIMP или Photoshop (отображается с разрешением 3 раза).

Ответ 2

Когда вы захватываете представление, только привязка к экрану будет захватываться (из-за контрольного веса и конвейера рендеринга андроида).

Захват снимка экрана для преобразования в PDF - это сложный путь. Я думаю, что два пути - более разумные решения.

Решение № 1

Напишите синтаксический анализатор (это просто), чтобы преобразовать содержимое веб-просмотра (то есть HTML) в формат iText.
Вы можете обратиться к этой статье за ​​дополнительной информацией.
http://www.vogella.com/articles/JavaPDF/article.html

Также, чтобы написать синтаксический анализатор, вы можете использовать REGEX и предоставить свои собственные методы, такие как parseTable, parseImage,...

Решение №2 Требуется Интернет

Предоставьте URL-адрес (или веб-сервис) для преобразования HTML в PDF с помощью PHP или С#, в котором есть много хороших библиотек. Затем вы можете отправить ссылку загрузки на клиент (Android-устройство).

Таким образом, вы можете динамически добавлять некоторые теги, баннеры,... в PDF со стороны сервера.

Ответ 3

Экранный снимок - это не что иное, как изображение вашего устройства, которое обычно зависит от вашего абсолютного пикселя телефона, если ваш телефон имеет размер экрана 480x800, будет таким же и вообще применим для всех сценариев.

Ответ 4

Конечно, используйте это:

Bitmap bitmap;
View v1 = MyView.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

Здесь MyView - это вид, в котором вам нужен скриншот.