I am using library Dmitry-Borodin/pdfview-android for showing pdf in android. My view is showing pdf correctly but the scaling of pdf doesnot seems to be working.
pdfView!!.fromFile(file!!).scale(500f).show()
Above is my code for showing pdf and scaling it.
With scaling I mean that width of pdf is quite small than that of device screen width
Instead of using Library, Please go through ImageView Component.
You need to create a Bitmap that matches the aspect ratio of the Page. It's best to match the dimensions of the ImageView as well:
PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
PdfRenderer.Page page = renderer.openPage(0);
int pageWidth = page.getWidth();
int pageHeight = page.getHeight();
float scale = Math.min((float) REQ_WIDTH / pageWidth, (float) REQ_HEIGHT / pageHeight);
Bitmap bitmap = Bitmap.createBitmap((int) (pageWidth * scale), (int) (pageHeight * scale), Bitmap.Config.ARGB_8888);
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
imageView.setImageBitmap(bitmap);
Related
I am storing an Image in the filesystem like:
FileImageOutputStream fos = new FileImageOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
And all images are stored correctly in the filesystem. (Also with correct aspect ratio with width and height!)
However, later, I am loading my image like:
File imgFile ...
FileImageInputStream stream = new FileImageInputStream(imgFile);
BufferedImage srcImage = ImageIO.read(stream);
And I want to get the width and height for my images like:
int actualHeight = srcImage.getHeight();
int actualWidth = srcImage.getWidth();
This works totally fine for images in landscape format.
However, for images in upfront format, the width and height is always swapped, so that the width is the height of the orginial image. So, e.g. I have an image that is 200x500 (width x height) and the two integers above are actualHeight = 200 and actualWidth = 500.
Am I missing something?
Most likely, your images are Exif images ("Exif-in-JPEG") from a digital camera/phone. For such images, the pixel data is often stored in the "natural" orientation of the sensor, which is always the same (usually landscape). For portrait images, the orientation is only stored in the Exif metadata, and the ImageIO JPEG plugin doesn't take this orientation into account.
Some cameras, like my Canon DSLR, has an option to do in-camera rotation to match the orientation, but this feature is typically disabled by default. This is obviously only a possible fix if you control the input images.
To fix this in the Java side, you hava some options. You already mentioned using Thumbnailator:
BufferedImage srcImage = Thumbnails.of(new FileInputStream(imgFile))
.scale(1)
.asBufferedImage();
Another option is to use EXIFUtilities from TwelveMonkeys (I'm the author of that library):
IIOImage image = EXIFUtilities.readWithOrientation(imgFile);
BufferedImage srcImage = (BufferedImage) image.getRenderedImage();
Or, if you don't need the other metadata for anything:
BufferedImage srcImage = (BufferedImage) EXIFUtilities.readWithOrientation(imgFile)
.getRenderedImage();
Work Story: Need to convert fabric js generated one page design json code to pdf file using java.
Issue: When i try to apply drop shadow to components like rectangle, circle or text i could not find any supported classes from PDFBox Library.
I am trying to explore how to apply drop shadow styles after creating components using pdfbox API.
Below is the code snippet for creating a rectangle. Need help after creating the component for applying drop shadow effects.
PDDocument doc = new PDDocument();
PDImageXObject pdImage = PDImageXObject.createFromFile("imagepath",doc);
PDPage page = new PDPage();
doc.addPage(page);
PDPageContentStream contentStream = new PDPageContentStream(doc, page);
int left = -60;
int top = 96;
int width = 471;
int height = 365;
contentStream.setStrokingColor(1, 0, 0);
contentStream.setLineWidth(4);
int imageOriginalWidth = 633;
int imageOriginalHeight = 422;
float scaleX = 0.99f;
float scaleY = 0.99f;
float imageWidth = imageOriginalWidth*scaleX;
float imageHeight = imageOriginalHeight*scaleY;
float imageY = page.getMediaBox().getHeight() - (top + imageHeight-58);
float imageX = -104;
contentStream.addRect(left, page.getMediaBox().getHeight() - top - height,
width, height);
contentStream.clip();
contentStream.drawImage(pdImage, imageX, imageY, imageWidth, imageHeight);
contentStream.close();
doc.save(new File(RESULT_FOLDER, "dummy.pdf"));
doc.close();
Below image is expected output of drop shadow applied rectangle:
You can add a drop shadow by first drawing a dark rectangle with transparency at a slight offset right before drawing your content. In your case e.g. like this:
...
float imageWidth = imageOriginalWidth*scaleX;
float imageHeight = imageOriginalHeight*scaleY;
float imageY = page.getMediaBox().getHeight() - (top + imageHeight-58);
float imageX = -104;
// vvv--- code added for shadow
PDExtendedGraphicsState extGS = new PDExtendedGraphicsState();
extGS.setNonStrokingAlphaConstant(.2f);
contentStream.saveGraphicsState();
contentStream.setGraphicsStateParameters(extGS);
contentStream.setNonStrokingColor(Color.BLACK);
contentStream.addRect(left + 5, page.getMediaBox().getHeight() - top - height - 5, width, height);
contentStream.fill();
contentStream.restoreGraphicsState();
// ^^^--- code added for shadow
contentStream.addRect(left, page.getMediaBox().getHeight() - top - height, width, height);
contentStream.clip();
contentStream.drawImage(pdImage, imageX, imageY, imageWidth, imageHeight);
contentStream.close();
...
(AddDropShadow test testRectangleWithDropShadow)
You might want to play around with different values for the alpha value (.2f), the color (BLACK), and the offsets (5 each) I used. Also I took the clip path as area to apply a shadow to. If your image does not fully fill that area, you might want to play around with the coordinates here.
I'm using PDFBox 1.7.0 (I do not have a choice for the version due to old version in production server). I am trying to add an image to an existing PDF which has already a logo.
When I add the new image, the old one disappears like it is replaced.
// Use for convert mm to dots
// ... 72 dots per inch
static final int DEFAULT_USER_SPACE_UNIT_DPI = 72;
// ... mm -> inch -> dots
static final float MM_TO_UNITS = 1 / (10 * 2.54f) * DEFAULT_USER_SPACE_UNIT_DPI;
/**
* Add a given image to a specific page of a PDF
* #param document PDF document to manipulate
* #param input image inputStream
* #param pdfpage page number to target
* #param x image position (en mm)
* #param y image position (en mm)
* #param width max width of the image (mm)
* #param height max height of the image (en mm)
* #param opacity opacity level of the image (fraction)
*/
void addImageToPage (PDDocument document, InputStream input, int pdfpage, int x, int y, int width, int height, float opacity) throws IOException {
if (input != null) {
// Convert inputstream to usable BufferedImage
BufferedImage tmp_image = ImageIO.read (input);
// User TYPE_4BYTE_ABGR to fix PDFBox issue with transparent PNG
BufferedImage image = new BufferedImage (tmp_image.getWidth(), tmp_image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
// Prepare the image
image.createGraphics().drawRenderedImage (tmp_image, null);
PDXObjectImage ximage = new PDPixelMap (document, image);
// Resize the image
int iWidth = ximage.getWidth();
int iHeight = ximage.getHeight();
if (width / height > iWidth / iHeight) {
ximage.setWidth (Math.round (width * MM_TO_UNITS));
ximage.setHeight (Math.round ((iHeight * width / iWidth) * MM_TO_UNITS));
} else {
ximage.setWidth (Math.round ((iWidth * height / iHeight) * MM_TO_UNITS));
ximage.setHeight (Math.round (height * MM_TO_UNITS));
}
// Retrieve the page to update
PDPage page = (PDPage)document.getDocumentCatalog().getAllPages().get (pdfpage);
PDResources resources = page.findResources();
// Get graphics states
Map graphicsStates = resources.getGraphicsStates();
if (graphicsStates == null) {
graphicsStates = new HashMap();
}
// Set graphics states configurations
PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
// Set the opacity of the image
extendedGraphicsState.setNonStrokingAlphaConstant (opacity);
graphicsStates.put ("TransparentState", extendedGraphicsState);
// Restore graphics states
resources.setGraphicsStates (graphicsStates);
// Retrieve the content stream
PDPageContentStream contentStream = new PDPageContentStream (document, page, true, true);
// Activate transparency options
contentStream.appendRawCommands ("/TransparentState gs\n");
contentStream.endMarkedContentSequence();
// Insert image
contentStream.drawImage (
ximage,
(float) x * MM_TO_UNITS,
(float) y * MM_TO_UNITS
);
// close the stream
contentStream.close();
}
}
I expected to have the new image within the page, but the existing image inside the page has disappeared instead of the new one.
Example of used PDF : http://www.mediafire.com/folder/g6p7c2b5ob1c7/PDFBox_issue
There are several bugs in 1.7... one I mentioned in a comment (turns out it doesn't affect you), the other one is that the resources does some caching but isn't managed properly… long story short, you need to save and restore your xobject resources like this:
Map<String, PDXObject> xObjectsMap = page.getResources().getXObjects(); // save xobjects
…
PDXObjectImage ximage = new PDPixelMap (document, image);
String imgName = page.getResources().addXObject(ximage, "Im");
cs.drawImage(ximage, 0, 0); // bug happens here, old xobjects gets lost
xObjectsMap.put(imgName, ximage);
page.getResources().setXObjects(xObjectsMap); // restore xobjects
This is really just a workaround… there may be more bad surprises coming. You should not use old versions. They no longer spark joy. You should thank them for their service and then let them go without guilt.
Ok. I have given up trying to use PDFbox 1.7 for this part of the development. It requirement to many fixes to implements few things. It is not really maintainable for the future works. Thanks to everyone for the hints and helps.
I have a problem with a function that I implemented. On some phones I get a out of memory error.
private Bitmap getIconMarkerOfPlayer(Player p) {
Drawable drawable = getIconOfPlayer(p);
Bitmap img = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(img);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
final float scale = this.getResources().getDisplayMetrics().density;
int heigthPixels = (int) (24 * scale + 0.5f);
int widthPixels = (int) (24 * scale + 0.5f);
return Bitmap.createScaledBitmap(img, widthPixels, heigthPixels, false);
}
The getIconMarkerOfPlayer(Player p) function gives a "programmed" drawable depending on the player's status (dead, alive, offline, ...) and its color. Each player has a unique color assigned to it in the early games.
How can I resize my bitmap from a Drawable object without having a out of memory error?
I suggest you to use some ImageLibraries to load Bitmaps efficiently.
Some of them are Fresco, Glide, Piccasio.
I suggest you to go with Glide. Have a look at it here
I have some difficulties creating a high quality thumbnail for my captured images. I understand that there are many snippet codes and tutorials in the web to create a thumbnail. I tried them and my problem is I can't produce a high quality thumbnail image. The output is always pixelated. Any suggestion ,library or links guys? thanks in advance.
I tried this one but its low quality also.
public static Bitmap scaleBitmap(Bitmap bitmap, int wantedWidth, int wantedHeight) {
Bitmap output = Bitmap.createBitmap(wantedWidth, wantedHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
Matrix m = new Matrix();
m.setScale((float) wantedWidth / bitmap.getWidth(), (float) wantedHeight / bitmap.getHeight());
canvas.drawBitmap(bitmap, m, new Paint());
return output;
}
Use RapidDecoder library. It is simple as follow:
import rapid.decoder.BitmapDecoder;
...
Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.image)
.scale(width, height)
.useBuiltInDecoder(true)
.decode();
Don't forget to use builtin decoders if you want to scale down less than 50% and a HQ result.
Did you try this,
Bitmap src = Thumbnails.getThumbnail(getContentResolver(), ContentUris.parseId(sourceUri), Thumbnails.MINI_KIND, options);
Try this
Bitmap ThumbImage =ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(imagePath),THUMBSIZE, THUMBSIZE);
This Utility is available from API_LEVEl 8. [Source]