I'm trying to resize and crop images into Google App engine in order to create thumbnails
I would like to be able to create 200x150 thumbs from any size.
This is the code I'm using so far now I need to crop it so it doesn't go bigger than 200x150:
Image oldImage = ImagesServiceFactory.makeImage(picture);
//Create the Image Service Factory and the Resize Transform
ImagesService imagesService = ImagesServiceFactory.getImagesService();
int w = 0;
int h = 0;
if (oldImage.getWidth() > oldImage.getHeight()) {
w = 1000;
h = height;
} else {
h = 1000;
w = width;
}
Transform resize = ImagesServiceFactory.makeResize(w, h);
//Resize The Image using the transform created above
Image resizedImage = imagesService.applyTransform(resize, oldImage);
Transform crop = ImagesServiceFactory.makeCrop(0.0, 0.0, width / resizedImage.getHeight(), height / resizedImage.getHeight());
Image cropedImage = imagesService.applyTransform(crop, resizedImage);
//Serve the newly transformed image
return cropedImage.getImageData();
Thanks !
I serve thumbnails with google app engine dynamically using getServingUrl
That can resize and crop storing only one image doing the resize and crop dynamically. Since I'm very satisfied with that solution I hope it can work for you too.
Your oldImage is less than 200px wide.
Related
I am working on a module where we are generating a JPG file through Android App. Here is the sample code.
Bitmap bitmap = BitmapFactory.decodeResource(ctx.getResources(), R.drawable.banner).copy(Bitmap.Config.ARGB_8888, true);
Canvas g = new Canvas(bitmap);
Paint paint = new Paint();
int x = 200; int y = 1850;
g.drawText("www.google.com", x, y, paint);
return bitmap;
Now we have this requirement of making the above text ("www.google.com") as a hyperlink, so that when user touches or clicks on this text in the JPG, the link gets opened in the browser. The JPG can be opened in any system (mobile or desktop).
How can we achieve this functionality?
I am developing the application for Android devices.
I want to generate QR code with logo inside it.
With ZXing I know how to generate simple QR codes like this one:
But I want to generate QR code with logo inside it.
So I want to get something like this:
Is there any way to do it?
I have no idea how to do it.
Could you help me please? May there is some ready library or example of how to do it.
Thank you!
You can add your logo it as an Image Overlay like
public BufferedImage getQRCodeWithOverlay(BufferedImage qrcode)
{
BufferedImage scaledOverlay = scaleOverlay(qrcode);
Integer deltaHeight = qrcode.getHeight() - scaledOverlay.getHeight();
Integer deltaWidth = qrcode.getWidth() - scaledOverlay.getWidth();
BufferedImage combined = new BufferedImage(qrcode.getWidth(), qrcode.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D)combined.getGraphics();
g2.drawImage(qrcode, 0, 0, null);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, overlayTransparency));
g2.drawImage(scaledOverlay, Math.round(deltaWidth/2), Math.round(deltaHeight/2), null);
return combined;
}
private BufferedImage scaleOverlay(BufferedImage qrcode)
{
Integer scaledWidth = Math.round(qrcode.getWidth() * overlayToQRCodeRatio);
Integer scaledHeight = Math.round(qrcode.getHeight() * overlayToQRCodeRatio);
BufferedImage imageBuff = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
Graphics g = imageBuff.createGraphics();
g.drawImage(overlay.getScaledInstance(scaledWidth, scaledHeight, BufferedImage.SCALE_SMOOTH), 0, 0, new Color(0,0,0), null);
g.dispose();
return imageBuff;
}
Please refer this post & github for more info
I created the following Kotlin Extention, which adds a Bitmap to the centre of another Bitmap:
fun Bitmap.addOverlayToCenter(overlayBitmap: Bitmap): Bitmap {
val bitmap2Width = overlayBitmap.width
val bitmap2Height = overlayBitmap.height
val marginLeft = (this.width * 0.5 - bitmap2Width * 0.5).toFloat()
val marginTop = (this.height * 0.5 - bitmap2Height * 0.5).toFloat()
val canvas = Canvas(this)
canvas.drawBitmap(this, Matrix(), null)
canvas.drawBitmap(overlayBitmap, marginLeft, marginTop, null)
return this
}
Can find my full solution here.
In Kotlin with zxing library and overlay from assets folder.
The correction needs to be made because the overlay will hide some part of the QR Code;
Class MatrixToImageWriter is from: https://github.com/kenglxn/QRGen
private fun generateQrCodeWithOverlay(qrCodeData: String): Bitmap? {
val hints = HashMap<EncodeHintType?, Any?>()
// The Error Correction level H provide a QR Code that can be covered by 30%
hints[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.H
val writer = QRCodeWriter()
return try {
// Create a QR Code from qrCodeData and 512 by 512 pixels, same size as my Logo
val encodedQrCode = writer.encode(qrCodeData, BarcodeFormat.QR_CODE, 512, 512, hints)
var qrCodeBitmap: Bitmap = MatrixToImageWriter.toBitmap(encodedQrCode)
val qrCodeCanvas = Canvas(qrCodeBitmap)
// Used to resize the image
val scaleFactor = 4
val logo =
BitmapFactory.decodeStream(app.assets.open("path/to/your/logo.png"))
// Resizing the logo increasing the density to keep it sharp
logo.density = logo.density * scaleFactor
val xLogo = (512 - logo.width / scaleFactor) / 2f
val yLogo = (512 - logo.height / scaleFactor) / 2f
qrCodeCanvas.drawBitmap(logo, xLogo, yLogo, null)
qrCodeBitmap
} catch (e: Exception) {
// handle errors
null
}
}
There is plenty online QR code generator, such as https://app.aotol.com/qr/api
You can just reference the QR image url to it such as
<img src="https://app.aotol.com/qr/api?qr_content=https://wwww.google.com&qr_logo=https://blog.hubspot.com/hubfs/image8-2.jpg">
I'm rendering PDFs with XHTML and flying saucer. I've added SVG images (icons etc) as well. However, when I try to draw a lot of images (like 5000+) the rendering takes really long (obviously). There are only 10 or so different images to draw, but just repeating them a lot of times (same size).
Is there a way/library to do this efficiently?
Currently using batik, flying saucer combo to draw images. The following code is used to parse the xhtml and find the img tags to place the SVG images:
#Override
public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockBox blockBox, UserAgentCallback userAgentCallback, int cssWidth, int cssHeight) {
Element element = blockBox.getElement();
if (element == null) {
return null;
}
String nodeName = element.getNodeName();
if ("img".equals(nodeName)) {
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
SVGDocument svgImage = null;
try {
svgImage = factory.createSVGDocument(new File(element.getAttribute("src")).toURL().toString());
} catch (IOException e) {
e.printStackTrace();
}
Element svgElement = svgImage.getDocumentElement();
element.appendChild(element.getOwnerDocument().importNode(svgElement, true));
return new SVGReplacedElement(svgImage, cssWidth, cssHeight);
}
return this.superFactory.createReplacedElement(layoutContext, blockBox, userAgentCallback, cssWidth, cssHeight);
}
And to draw the images i use:
#Override
public void paint(RenderingContext renderingContext, ITextOutputDevice outputDevice,
BlockBox blockBox) {
PdfContentByte cb = outputDevice.getWriter().getDirectContent();
float width = cssWidth / outputDevice.getDotsPerPoint();
float height = cssHeight / outputDevice.getDotsPerPoint();
PdfTemplate template = cb.createTemplate(width, height);
Graphics2D g2d = template.createGraphics(width, height);
PrintTranscoder prm = new PrintTranscoder();
TranscoderInput ti = new TranscoderInput(svg);
prm.transcode(ti, null);
PageFormat pg = new PageFormat();
Paper pp = new Paper();
pp.setSize(width, height);
pp.setImageableArea(0, 0, width, height);
pg.setPaper(pp);
prm.print(g2d, pg, 0);
g2d.dispose();
PageBox page = renderingContext.getPage();
float x = blockBox.getAbsX() + page.getMarginBorderPadding(renderingContext, CalculatedStyle.LEFT);
float y = (page.getBottom() - (blockBox.getAbsY() + cssHeight)) + page.getMarginBorderPadding(
renderingContext, CalculatedStyle.BOTTOM);
x /= outputDevice.getDotsPerPoint();
y /= outputDevice.getDotsPerPoint();
cb.addTemplate(template, x, y);
}
An idea of the scaling. 100 images take 2 seconds, 5000 images take about 42 seconds on an i5 8gb RAM.
So is there a way to store a drawn SVG in memory and paste it more quickly or something? Because right now it seems to take all images as separate images and eat all my memory and take forever.
Managed to optimize the memory and speed by doing two things.
I pre-generated the SVGDocuments in the createReplacedElement method which sped it up a bit.
The main improvement was pre-generating all pdfTemplates for all the images. This greatly increased speed as the templates already contained the rendered images.
The rendering of all regular text is still slow, so I might turn down the DPI.
EDIT: further optimization see Is there any way improve the performance of FlyingSaucer?
I have an Android application and I want to show up a PDF into it (without external applications). The only solution that I thought is to convert the pages of the PDF to images. Someone has experience with that issue? which library do you recommend me?
I tested the next libraries, but I have had troubles:
1) PdfRenderer library does not work with modern PDF
2) jPDFImages not work in Android (works in java desktop application)
Sorry for my English
I'm expanding on the accpeted answer and providing a complete solution.
Using this library: android-pdfview and the following code, you can reliably convert the PDF pages into images (JPG, PNG):
DecodeServiceBase decodeService = new DecodeServiceBase(new PdfContext());
decodeService.setContentResolver(mContext.getContentResolver());
// a bit long running
decodeService.open(Uri.fromFile(pdf));
int pageCount = decodeService.getPageCount();
for (int i = 0; i < pageCount; i++) {
PdfPage page = decodeService.getPage(i);
RectF rectF = new RectF(0, 0, 1, 1);
// do a fit center to 1920x1080
double scaleBy = Math.min(AndroidUtils.PHOTO_WIDTH_PIXELS / (double) page.getWidth(), //
AndroidUtils.PHOTO_HEIGHT_PIXELS / (double) page.getHeight());
int with = (int) (page.getWidth() * scaleBy);
int height = (int) (page.getHeight() * scaleBy);
// you can change these values as you to zoom in/out
// and even distort (scale without maintaining the aspect ratio)
// the resulting images
// Long running
Bitmap bitmap = page.renderBitmap(with, height, rectF);
try {
File outputFile = new File(mOutputDir, System.currentTimeMillis() + FileUtils.DOT_JPEG);
FileOutputStream outputStream = new FileOutputStream(outputFile);
// a bit long running
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (IOException e) {
LogWrapper.fatalError(e);
}
}
You should do this work in the background i.e. by using an AsyncTask or something similar as quite a few methods take computation or IO time (I have marked them in comments).
You can use MuPDF. Here is a link that describes how to build MuPDF for android: http://mupdf.com/docs/how-to-build-mupdf-for-android
I recommend use this library, android-pdfview
I am making an Android game, but when I load my Bitmaps, I get a memory error. I know that this is caused by a very large Bitmap (it's the game background), but I don't know how I could keep from getting a "Bitmap size extends VM Budget" error. I can't rescale the Bitmap to make it smaller because I can't make the background smaller. Any suggestions?
Oh yeah, and here's the code that causes the error:
space = BitmapFactory.decodeResource(context.getResources(),
R.drawable.background);
space = Bitmap.createScaledBitmap(space,
(int) (space.getWidth() * widthRatio),
(int) (space.getHeight() * heightRatio), false);
You're going to have to sample down the image. You can't "scale" it down smaller than the screen obviously, but for small screens etc it doesn't have to be as high resolution as it is for big screens.
Long story short you have to use the inSampleSize option to downsample. It should actually be pretty easy if the image fits the screen:
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
final int dimension = Math.max(display.getHeight(), display.getWidth());
final Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
InputStream bitmapStream = /* input stream for bitmap */;
BitmapFactory.decodeStream(bitmapStream, null, opt);
try
{
bitmapStream.close();
}
catch (final IOException e)
{
// ignore
}
final int imageHeight = opt.outHeight;
final int imageWidth = opt.outWidth;
int exactSampleSize = 1;
if (imageHeight > dimension || imageWidth > dimension)
{
if (imageWidth > imageHeight)
{
exactSampleSize = Math.round((float) imageHeight / (float) dimension);
}
else
{
exactSampleSize = Math.round((float) imageWidth / (float) dimension);
}
}
opt.inSampleSize = exactSampleSize; // if you find a nearest power of 2, the sampling will be more efficient... on the other hand math is hard.
opt.inJustDecodeBounds = false;
bitmapStream = /* new input stream for bitmap, make sure not to re-use the stream from above or this won't work */;
final Bitmap img = BitmapFactory.decodeStream(bitmapStream, null, opt);
/* Now go clean up your open streams... : ) */
Hope that helps.
This may help you: http://developer.android.com/training/displaying-bitmaps/index.html
From the Android Developer Website, a tutorial on how to efficiently display bitmaps + other stuff. =]
I don't understand why are you using ImageBitmap? for background. If its necessary , its okay. Otherwise please use Layout and set its background because you are using background image.
This is important. (Check Android docs. They have clearly indicated this issue.)
You can do this in following way
Drawable d = getResources().getDrawable(R.drawable.your_background);
backgroundRelativeLayout.setBackgroundDrawable(d);
In most android devices the Intent size equals 16MB. You MUST Follow these instructions Loading Large Bitmap Efficiently