2012-11-20 19 views
16

Czy istnieje sposób na zrobienie ekranu wysokiej rozdzielczości określonego widoku w działaniu.Zdjęcie ekranu o wysokiej rozdzielczości w systemie Android:

Chcę przekonwertować zawartość html z mojej webview na PDF. W tym celu próbowałem zrobić zrzut ekranu z treścią widoku na WWW, a następnie przekonwertować go do formatu PDF za pomocą itext. Wynikowy plik PDF nie jest dużo bardziej przejrzysty.

Mój kod:

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()); 
    } 
} 
+3

Naprawdę ładne pytanie .. – prakash

+1

Dlaczego chcesz zrobić zrzut ekranu ... dostępne są różne biblioteki, które umożliwiają tworzenie plików PDF na Androidzie. Po prostu pobierz zawartość strony HTML ze strony internetowej i użyj dowolnej biblioteki do utworzenia pliku pdf. Ta technika zrzutu ekranu stworzy więcej nowych problemów, a następnie rozwiąże oryginalną. – mudit

+0

Bardzo się starałem i nie mogłem znaleźć najlepszego sposobu na konwersję HTML na PDF. Jeśli masz jakiś pomysł, wyjaśnij mi. – Sniper

Odpowiedz

11

Aktualizacja: Zobacz Edycja 3 na odpowiedź do pierwotnego pytania OP

Istnieją dwie opcje:

  1. użyć biblioteki do konwersji HTML do PDF. Jest to zdecydowanie najlepsza opcja, ponieważ prawdopodobnie zachowa tekst jako wektory.

  2. Uzyskaj renderowanie w wysokiej rozdzielczości HTML i zapisz go jako PNG (na pewno nie PDF!).

HTML do PDF, wkhtmltopdf wygląda dobrym rozwiązaniem, ale to zależy od Qt, które tak naprawdę nie można wykorzystać na Androida.Jest kilka innych bibliotek, ale wątpię, czy renderują one bardzo dobrze.

Aby uzyskać wysoką jakość podglądu strony internetowej, można spróbować utworzyć własne WebView i wywołać onMeasure(...) i onLayout(...) i przekazać odpowiednie parametry, dzięki czemu widok jest naprawdę duży. Następnie zadzwoń pod numer onDraw(myOwnCanvas), a widok internetowy wyświetli się na twoim płótnie, który może być wspierany przez Bitmap przy użyciu Canvas.setBitmap().

Prawdopodobnie można skopiować stan do nowego WebView użyciu coś jak

screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState()); 

Orrr może być nawet możliwe, aby korzystać z tego samego WebView, tylko tymczasowo zmienić rozmiar to być duża, onDraw() go na płótnie, i ponownie zmień jego rozmiar. To staje się bardzo hacky!

Możesz napotkać problemy z pamięcią, jeśli zrobisz je za duże.

Edycja 1

Myślałem trzeciej opcji, dokładnie-co-ty-chcesz, ale to trochę hardcore. Możesz utworzyć niestandardową Canvas, która zapisuje do pliku PDF. W rzeczywistości jest to bardzo łatwe, ponieważ podstawową wersją jest Skia, która w rzeczywistości zawiera backend PDF. Niestety nie masz do niego dostępu na Androida, więc będziesz musiał zbudować swoją własną kopię na Androida (są instrukcje) i powielić/zastąpić wszystkie metody Canvas wskazujące na Skia zamiast na Androidy. Zauważ, że istnieje kusząca metoda Picture.writeToStream() serializująca dane Skia, ale niestety ten format nie jest kompatybilny z poprzednimi wersjami ani z poprzednimi wersjami, więc jeśli go użyjesz, Twój kod będzie działał tylko w kilku wersjach Androida.

Zaktualizuję jeśli/kiedy mam w pełni działający kod.

Edycja 2

Właściwie jest to niemożliwe, aby stworzyć własną "przechwytywanie" Canvas. Zacząłem to robić i przeszedłem przez nużący proces serializowania wszystkich wywołań funkcji. Kilka, których nie możesz zrobić, ponieważ są one ukryte, ale te nie wyglądały na ważne. Ale na samym końcu doszedłem do serializacji Path tylko po to, aby odkryć, że jest to tylko zapis. To wydaje mi się zabójcą, więc jedyną opcją jest interpretacja wyniku Picture.writeToStream(). Na szczęście są tylko dwie wersje tego formatu i są prawie identyczne.

Edycja 3 - bardzo prosty sposób, aby uzyskać wysoką rozdzielczość Bitmap z widokiem

Ok, okazuje się po prostu coraz High Res bitmapę widokiem (co może być cała aplikacja) jest trywialne. Oto jak uzyskać podwójną rozdzielczość. Oczywiście wszystkie bitmapy wyglądają na trochę bzdurne, ale tekst jest renderowany w pełnej rozdzielczości:

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

Działa jak urok. Przestałem już robić zrzut ekranu PDF z tekstem wektorowym. Jest to z pewnością możliwe, ale bardzo trudne. Zamiast tego pracuję nad uzyskaniem wysokiej rozdzielczości PSD, gdzie każda operacja losowania jest osobną warstwą, która powinna być znacznie łatwiejsza.

Edytuj 4

Woa to robi się trochę długo, ale sukces! Wygenerowałem .xcf (GIMP) i PDF, gdzie każda warstwa jest inną operacją rysowania płótna.Nie jest tak drobnoziarnisty, jak się spodziewałem, ale nadal jest całkiem przydatny!

W rzeczywistości mój kod po prostu wyświetla pełnowymiarowy plik PNG, a ja użyłem "Otwórz jako warstwy ..." i "Autocrop layer" w GIMP, aby tworzyć te pliki, ale oczywiście możesz to zrobić w kodzie, jeśli chcesz. Myślę, że zmienię to w post na blogu.

Pobierz plik demonstracyjny GIMP lub Photoshop (renderowany w rozdzielczości 3x).

+0

Do edycji 3: Dlaczego przesyłasz bitmapę z jakością 0%? Zgadnij, że powinno być bardziej podobne: 'bitmap.compress (Bitmap.CompressFormat.PNG, 100, myOutputStream);' – Rappel

+0

[Jakość jest ignorowana dla PNG] (http://developer.android.com/reference/android/graphics /Bitmap.html#compress%28android.graphics.Bitmap.CompressFormat,%20int,%20java.io.OutputStream%29) – Timmmm

3

Screen Shot to nic innego jak obraz wyświetlacza urządzenia, które zwykle zależeć telefonie bezwzględnych pikseli, jeśli telefon jest 480x800 zrzut ekranu będą takie same i powszechnie stosowane dla wszystkich scenariuszy.

3

Jasne, użyj tego:

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

Tutaj MyView jest widok trzeba zrzut ekranu.

+2

To nie jest wysoka rozdzielczość. – Timmmm

4

Podczas przechwytywania widoku przechwytywane jest tylko przesunięcie ekranu (ze względu na wagę kontrolną i renderowanie renderowania systemu Android).

Przechwytywanie zrzutu ekranu do konwersji do formatu PDF jest trudnym sposobem. Myślę, że dwojaki sposób to rozsądniejsze rozwiązania.

Rozwiązanie nr 1

Napisz parsera (to proste) do konwersji Webview treści (czyli HTML) do formatu iText.
Więcej informacji można znaleźć w tym artykule.
http://www.vogella.com/articles/JavaPDF/article.html

także napisać parser można użyć wyrażenia regularnego i podać swoje własne metody, jak parseTableparseImage ...

Rozwiązanie nr 2Internet Wymagane

Podaj adres URL (lub webservice) do konwersji HTML na PDF za pomocą PHP lub C#, który ma wiele ładnych bibliotek. Następnie możesz wysłać łącze do pobierania do klienta (urządzenie z systemem Android).

Dzięki temu można również dynamicznie dodawać niektóre tagi, banery, ... do pliku PDF po stronie serwera.

Powiązane problemy