I am working with pdf files, I want to implement page viewer to my pdf file. My idea is to convert pdf file into bmp images, and then to use viewPager. but I am stuck in converting pdf to bitmap. Any suggestions?
Include dependencies in your gradle
compile 'com.github.barteksc:android-pdf-viewer:2.8.1'
Use following function to convert PDF page to bitmap image
private Bitmap generateImageFromPdf(String assetFileName, int pageNumber, int width, int height) {
PdfiumCore pdfiumCore = new PdfiumCore(mActivity);
try {
File f = FileUtils.fileFromAsset(mActivity, assetFileName);
ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
PdfDocument pdfDocument = pdfiumCore.newDocument(fd);
pdfiumCore.openPage(pdfDocument, pageNumber);
//int width = pdfiumCore.getPageWidthPoint(pdfDocument, pageNumber);
//int height = pdfiumCore.getPageHeightPoint(pdfDocument, pageNumber);
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
pdfiumCore.renderPageBitmap(pdfDocument, bmp, pageNumber, 0, 0, width, height);
//saveImage(bmp, filena);
pdfiumCore.closeDocument(pdfDocument);
return bmp;
} catch(Exception e) {
//todo with exception
}
return null;
}
this is a way to render pdf to image
its take 20 to 25 seconds to render pdf file to image
its working in android 10 , android 9 and all lower versions
private void generateImageFromPdf() {
try {
PDDocument doc=PDDocument.load(new File(fileurl));
PDFRenderer pdfRenderer = new PDFRenderer(doc);
Bitmap bffim = pdfRenderer.renderImageWithDPI(0, 100, Bitmap.Config.RGB_565);
String fileName = "image-" + 0 + ".png";
img.setImageBitmap(bffim);
} catch (IOException e) {
e.printStackTrace();
}
}
Related
I'm showing lot of pdfs using recyclerview. I'm converting first page of a pdf into image and then showing it beside the pdf file. I'm using glide library for loading those bitmaps. But, recyclerview lags while scrolling. How to make the scrolling smooth?
Code for converting pdf to bitmap:-
public static Bitmap pdfToBitmap(File pdfFile) {
Bitmap bitmap = null;
try {
PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));
final int pageCount = renderer.getPageCount();
if (pageCount > 0) {
PdfRenderer.Page page = renderer.openPage(0);
int width = (int) (page.getWidth());
int height = (int) (page.getHeight());
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
page.close();
renderer.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return bitmap;
}
Code for loading the bitmap into imageview:
Glide.with(viewHolder.itemView.getContext())
.load(bitmap)
.into(viewHolder.pdfImg);
How to get the bitmap of current layout(For sharing the screen as image) instead of taking screenshot? I'm getting the view of layout using following line,
I can able to get bitmap of this layout but the image is looking as empty(I got blank image). This is my code.
View cardShareView = getLayoutInflater().inflate(R.layout.activity_cad_profile, null);
boolean imageResult=saveImageInLocal(getBitmapFromView(cardShareView), "cad_share.png") == true
public static Bitmap getBitmapFromView(View view) {
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
view.draw(canvas);
return bitmap;
}
private boolean saveImageInLocal(Bitmap imageData, String filename) {
String iconsStoragePath = Environment.getExternalStorageDirectory() + "/KKMC/";
File sdIconStorageDir = new File(iconsStoragePath);
//create storage directories, if they don't exist
sdIconStorageDir.mkdirs();
try {
filePath = sdIconStorageDir.toString() + filename;
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
//choose another format if PNG doesn't suit you
imageData.compress(Bitmap.CompressFormat.PNG, 70, bos);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
Log.w("TAG", "Error saving image file: " + e.getMessage());
return false;
} catch (IOException e) {
Log.w("TAG", "Error saving image file: " + e.getMessage());
return false;
}
return true;
}
Advance Thanks for your response.
Expecting this image
Bit I got this image
Finally, I created duplicate layout(activity_cad_profile.xml) for take the full view as image which is loaded at the time of main layout is loading. I don't know this is correct way or not. But it's working fine for me.
I have PDF files that contains 1 single icon.
I need to render this icons in GridView.
On Android 5 I'm using PdfRenderer system class and it works amazing:
On Android 4, I'm using "Android-Pdf-Viewer-Library".
https://github.com/jblough/Android-Pdf-Viewer-Library
It works, but the quality is poor:
Can you please suggest any alternatives for rendering PDF as Bitmap?
Or maybe there is a way to increase quality of rendering for that library?
Here is my code:
private static Bitmap renderToBitmap(Context context, InputStream inStream) {
Bitmap bitmap = null;
try {
byte[] decode = IOUtils.toByteArray(inStream);
ByteBuffer buf = ByteBuffer.wrap(decode);
PDFPage mPdfPage = new PDFFile(buf).getPage(0, true);
float width = mPdfPage.getWidth();
float height = mPdfPage.getHeight();
bitmap = mPdfPage.getImage((int) (width), (int) (height), null, true,
true);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException e) {
}
}
return bitmap;
}
Currently I'm loading MediaStore Image Thumbnails using picasso into the ListView with the following snippet: (video.getData() returns the actual path of the image such as mnt/sdcard/...)
Picasso.with(this.context)
.load(new File(photo.getData()))
.resize(50, 50).config(config)
.centerCrop()
.into(viewHolder.imageViewItem);
Now I'm and unable to load the MediaStore Video Thumbnails by just passing the video.getData() instead of photo.getData()?
First You need to create VideoRequestHandler
public class VideoRequestHandler extends RequestHandler{
public String SCHEME_VIDEO="video";
#Override
public boolean canHandleRequest(Request data)
{
String scheme = data.uri.getScheme();
return (SCHEME_VIDEO.equals(scheme));
}
#Override
public Result load(Request data, int arg1) throws IOException
{
Bitmap bm;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
Size size = new Size(250, 250);
bm = ThumbnailUtils.createVideoThumbnail(new File(data.uri.getPath()), size, null);
} catch (IOException e) {
e.printStackTrace();
}
}
else
{
bm = ThumbnailUtils.createVideoThumbnail(data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND);
}
return new Result(bm,LoadedFrom.DISK);
}
}
After That
VideoRequestHandler videoRequestHandler;
Picasso picassoInstance;
Build only once
videoRequestHandler = new VideoRequestHandler();
picassoInstance = new Picasso.Builder(context.getApplicationContext())
.addRequestHandler(videoRequestHandler)
.build();
Then load file from path
picassoInstance.load(VideoRequestHandler.SCHEME_VIDEO+":"+filepath).into(holder.videoThumbnailView);
Updated October 2020
ThumbnailUtils.createVideoThumbnail(data.uri.getPath(), MediaStore.Images.Thumbnails.MINI_KIND);
is deprecated in Android Q. I will write in Kotlin:
val bm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ThumbnailUtils.createVideoThumbnail(
File(data.uri.path!!),
Size(200f.toPx(), 200f.toPx()),
CancellationSignal()
)
} else {
ThumbnailUtils.createVideoThumbnail(
data.uri.path!!,
MediaStore.Images.Thumbnails.MINI_KIND
)
}
to Px is an extension function which is like below;
fun Float.toPx() =
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
.toInt()
You can use any dp value for it :) I hope this can help you :)
Before, you had two options:
1) Do a call beforehand, when you were retrieving your videos for example and storing the bitmap:
Bitmap thumbnailBitmap = MediaStore.Video.Thumbnails.getThumbnail(content, id, MediaStore.Video.Thumbnails.MINI_KIND, options);
2) Creating a custom Downloader (not verified for local media)
But now, with Picasso 2.4, you can create a RequestHandler. You can have a look at this page for example: http://blog.jpardogo.com/requesthandler-api-for-picasso-library/
In my current usage, I fetch the thumbnail path and then call Picasso with that path. To get the thumbnail path, I referred to: android get video thumbnail PATH, not Bitmap.
public void bindTo(MediaListHolder mediaListRowHolder, int i) {
DataPictures message = itemList.get(i);
try {
Uri uri = Uri.fromFile(new File(message.getFilePath()));
if (message.getFileType().equalsIgnoreCase("video")) {
Bitmap bmThumbnail = ThumbnailUtils.extractThumbnail(ThumbnailUtils.createVideoThumbnail(message.getFilePath(),
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND), MAX_WIDTH, MAX_HEIGHT);
mediaListRowHolder.thumbnail.setImageBitmap(bmThumbnail);
} else {
Picasso.with(ApplicationSingleton.getInstance()).load(uri)
.resize(size, size)
.placeholder(R.drawable.logo_slogan)
.into(mediaListRowHolder.thumbnail);
}
Log.i(TAG, "bindTo: ");
} catch (Exception e) {
e.printStackTrace();
}
}
Note - Follow this comment if you simply want to show thumbnail in your image view and apply no extra Picasso functions on it .
I just modified it a little to show circular thumbnail coz it looks cool .
Don't use Picasso . Here's a very simple way to do it .
videoPathUrl = /*your Video File Url */
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(videoPathUrl , MediaStore.Video.Thumbnails.MICRO_KIND);
bMap = transformBitmapToCircularBitmap(bMap);
yourImageView.setImageBitmap(bMap);
and transformBitmapToCircularBitmap function is as follows -
public static Bitmap transformBitmapToCircularBitmap(Bitmap source)
{
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap,
BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
i'm developer an app that have more image (about 3000) that has space in filename like:
Im An image.jpg
being new to Android, I only found out now that are not accepted by the resources that have blank spaces or capital letters in the name, and this is a very big problem!
I use the same images in an application for iOS (without problems), and it would be almost impossible now to change all the names.
there is a way to solve this problem without renaming images?
if not, is there a way to quickly rename 3000 images?
thanks at all
there is a way to solve this problem without renaming images?
Nope. Res files can not have spaces.
You could put them in the assets folder and use them fom there, but you will have to get each image as a bitmap without the possibility of using the R.drawable.image_name notation.
I use this method:
public static Bitmap getFoodImage(Context context, String foodType){
InputStream bitmap = null;
Bitmap bit = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
try {
bitmap = context.getAssets().open(foodType.toUpperCase() + ".png");
if(bitmap != null){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int sWidth = metrics.widthPixels;
options.inJustDecodeBounds = true;
Bitmap dBit = BitmapFactory.decodeStream(bitmap, null, options);
int intrinsicHeight = options.outHeight;
int intrinsicWidth = options.outWidth;
//int height = (int) (intrinsicWidth * proportion);
int nHeight = (int) (intrinsicHeight/1.3);
try {
bitmap.reset();
} catch (IOException e) {
Log.e("SGNAM", e.getMessage());
}
options.inJustDecodeBounds = false;
dBit = BitmapFactory.decodeStream(bitmap, null, options);
Bitmap bP = Bitmap.createBitmap(dBit, 0, 0, intrinsicWidth, nHeight);
if(sWidth < intrinsicWidth){
bit = Bitmap.createScaledBitmap(bP, intrinsicWidth, intrinsicHeight, false);
}
else{
bit = Bitmap.createScaledBitmap(bP, sWidth, intrinsicHeight, false);
}
bitmap.close();
dBit = null;
bP = null;
}
} catch (IOException e) {
e.printStackTrace();
}
return bit;
}
As you can see i have all the image names in uppercase but you can skip that part if not needed (same for the png).
If you are in your onCreate method and the image you want is called An image.png (remember that in this example the .png is added by the method):
Context context = this;
Bitmap myBitmap = getFoodImage(context, An image);
You can set this bitmap as a resource for an imageView this way:
ImageView myImageView = findViewById(R.id.imageView);
myImageView.setImageBitmap(myBitmap);
This should do he trick.