Is there a method to resize bitmap image? - android

I'm having problem with my file browser.
When it reached to any directory : Get folder list to list map, and use onBindCustomView for setting icon for each list items.
If that file format is image, it shows the image preview instead of showing image icon.
But the problem is, one or less than 10 image file is OK. But when the image file count is reached to over 50, it lags very hard.
I think this lag problem is caused by image preview. Because it didn't resize, so I add the code to resize image preview from any x any to 100x100.
But there is another problem.
bitmap.createBitmap(bitmap, 0, 0, 100, 100)
This cut image and make it small. This only resize the image. So the result is the small part of image.
Is there a method to resize the image and keep the image looks original?

You can use canvas:
In your view.
<script>
$('#files')
.bind('change', function(ev) {
message_loading("none");
ev.preventDefault();
ev.stopPropagation();
uploadFiles(this);
message_loading("display");
})
</script>
In your script
function uploadFiles(target) {
var content = target.files;
var img = reduceImgSize(content[0], content[0]["name"]);
}
function reduceImgSize(f, name){
var reader = new FileReader();
reader.onload = function (readerEvent) {
var image = new Image();
image.onload = function (imageEvent) {
var canvas = document.createElement('canvas'),
max_size = image.width/1.1,
width = image.width,
height = image.height;
if (width > height) {
if (width > max_size) {
height *= max_size / width;
width = max_size;
}
} else {
if (height > max_size) {
width *= max_size / height;
height = max_size;
}
}
canvas.width = width; // write your width
canvas.height = height; // write your height
canvas.getContext('2d').drawImage(image, 0, 0, width, height);
var dataUrl = canvas.toDataURL('image/jpeg');
var resizedImage = dataURLToBlob(dataUrl);
var imageFile = new File([resizedImage], name, {type : "image/jpeg"});
return imageFile;
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(f);
}
I hope it helps

Related

Preview file from original file is bigger in size android bitmap

Given a file (which of course is an Image) in Android i want to make a preview image which of course should be smaller in size. I use the code below
override fun createImagePreview(serverId: Long, fileName: String) {
if (fileName.fileType() != IMAGE_TYPE) return
val file = serverDir.getFileByName(fileName)
val originalBitmap = BitmapFactory.decodeFile(file.absolutePath) ?: return
var newWidth = DEFAULT_IMAGE_SIZE.toDouble()
var newHeight = DEFAULT_IMAGE_SIZE.toDouble()
if (originalBitmap.width > originalBitmap.height) {
val ratio = originalBitmap.width / originalBitmap.height
newHeight = newWidth / ratio
} else if (originalBitmap.width < originalBitmap.height) {
val ratio = originalBitmap.height / originalBitmap.width
newWidth = newHeight / ratio
}
val bmp = ThumbnailUtils.extractThumbnail(
originalBitmap,
newWidth.toInt().dpToPixel(appContext),
newHeight.toInt().dpToPixel(appContext)
)
FileOutputStream(File(serverDir, "p_$fileName")).use {
it.write(bmp.toByteArray())
it.flush()
}
}
However, i see inside my internalStorage that if the File is 5KB then the PreviewFile is 19KB. What is wrong with that?
bmp.toByteArray is the wrong way to store an image. The Bitmap object is uncompressed. That means it uses 4 bytes per pixel. A jpg or png is compressed, that means it uses less data per pixel. You want to store it in one of those formats. The way to do that is to use Bitmap.compress() and pass it a stream to the file you want to use.

manipulate the colours in a Bitmap android

I have a QrCode which i want to change its colours to white and blue...
I can do it using the following code:
val bitmap = qrgEncoder.encodeAsBitmap()
val width = bitmap.width
val height = bitmap.height
// All are 0, or black, by default
for (y in 0 until height) {
for (x in 0 until width) {
bitmap.getPixel(x, y).also {
if(it != -1)
bitmap.setPixel(x, y, ResourcesCompat.getColor(resources, R.color.defaultTextColor, null))
else
bitmap.setPixel(x, y, ResourcesCompat.getColor(resources, R.color.toolbarColor, null))
}
}
}
// Setting Bitmap to ImageView
qrImage.setImageBitmap(bitmap)
but this is too slow... so I am wondering what is the best approach to do the same thing and faster.
After trying different solutions, I realised the only way is to manipulate the pixels.
The following code is the optimum solution for now:
val pixelsArray = IntArray(mWidth * mHeight)
val newColor1 = getColor(context!!, R.color.color1)
val newColor2 = getColor(context!!, R.color.color2)
bitmap.getPixels(pixelsArray, 0, mWidth, 0, 0, mWidth, mHeight)
for (y in 0 until pixelsArray.size) {
if (pixelsArray[y] != -1)
pixelsArray[y] = newColor1
else
pixelsArray[y] = newColor2
}
note for accepted answer by msc87,
to save pixelsArray back to bitmap use:
bitmap.setPixels(pixelsArray,0,mWidth,0,0,mWidth,maskHeight)
you can also replace getColour to: (if needed)
Color.argb(255,0,177,64)
ect..
You can set a Drawable tint:
https://developer.android.com/reference/android/support/v4/graphics/drawable/DrawableCompat.html#setTint(android.graphics.drawable.Drawable,%20int)
val bitmap: Bitmap = ...
val bitmapDrawable = BitmapDrawable(resources, bitmap)
DrawableCompat.setTint(bitmapDrawable, Color.BLUE)

SkiaSharp load imge from ImageView

I am trying to load bitmap from ImageView to SKCanvasView.
The problem is that this image has CenterCrop set and image that was loaded to canvas is way too big. How to make it look exactly like in ImageView?
Code samples:
_skBitmap = ((BitmapDrawable)_frontView.ImageView.Drawable).Bitmap.ToSKBitmap();
And drawing:
private void _canvas_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
var scale = Resources.DisplayMetrics.Density;
canvas.Scale(scale);
if (_skBitmap != null)
{
canvas.DrawBitmap(_skBitmap, e.Info.Rect);
}
}
In case someone is interested (in my case image is always wider then screen):
private void _canvas_PaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
var canvas = e.Surface.Canvas;
var scale = Resources.DisplayMetrics.Density;
canvas.Scale(scale);
if (_skBitmap != null)
{
var factor = scaledSize.Height / _skBitmap.Height;
var nw = _skBitmap.Width * factor;
var offset = (scaledSize.Width - nw) / 2;
var sr = new SKRect(offset, 0, nw + offset, scaledSize.Height);
canvas.DrawBitmap(_skBitmap, sr);
}
}

Why does PDFRenderer creates black borders?

I try to generate a bitmap from this PDF file.
My code is the following one:
mFileDescriptor = ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (mFileDescriptor != null) {
mPdfRenderer = new PdfRenderer(mFileDescriptor);
}
if (mPdfRenderer != null) {
for (int i = 0; i < mPdfRenderer.getPageCount(); i++) {
printPage(i);
}
}
....
private void printPage(int index) {
byte[] img;
if (mPdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != mCurrentPage) {
mCurrentPage.close();
}
// Use `openPage` to open a specific page in PDF.
mCurrentPage = mPdfRenderer.openPage(index);
int width = (int)(203.0 / 72.0 * mCurrentPage.getWidth() + 0.5);
int height = (int)(203.0 / 72.0 * mCurrentPage.getHeight() + 0.5);
// Important: the destination bitmap must be ARGB (not RGB).
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
try {
sendImageToPrinter(PrinterEventsProto.Image.parseFrom(bitmap), getApplicationContext());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
And the correspdonding bitmap is this one where I don't understand where this black border comes from. Any idea ?
This is most likely because your width and height of your bitmap do not match the width and height of the screen (the activity window).
Don't set your bitmap height and width to arbitrary values like you're doing here: int width = (int)(203.0 / 72.0 * mCurrentPage.getWidth() + 0.5)
You could try setting the width of the bitmap to mCurrentPage.getWidth() and the height to mCurrentPage.getHeight(). Then, if you set the scale type of the ImageView that you're displaying to fit, it should display to the full page width and height.
Or if you're sending it to a printer, it should print the full page and not cut anything off. Although, you may need to change the height and width of the bitmap to fit on the type of paper you're printing. In that instance, use this info to produce a properly scaled bitmap for A4 paper:
8.27" x 11.69" Equivalent A4 paper dimensions in pixels at 300 DPI and 72 DPI respectively are: 2480 pixels x 3508 pixels (print resolution)
595 pixels x 842 pixels (screen resolution)
http://www.graphic-design-employment.com/a4-paper-dimensions.html

composing canvas with Images works on Android but fails silently on IOS

I have the following code which fails on IOS but works on Android (using ionic/cordova). What am I missing (maybe I am being lucky with Android!) ? On Androids I get a seamless vertical stacking of image(s), whereas on IOS I get a blank look. It fails on IOS whether I am stacking one SVG or many.
The SVG elements by themselves show up fine on the page, and in debugger I can see their complete markup.
function _appendImgToCanvas(canvas, image, first_image) {
// image contents are -- {id, h, w}
var ctx = canvas.getContext("2d");
var img_type = "data:image/svg+xml;charset=utf-8";
try {
var img_el = document.getElementById(image.id).getElementsByTagName("svg")[0];
var img_src = new XMLSerializer().serializeToString(img_el); // thx Kaiido
var img = new Image();
img.src = img_type + "," + img_src;
var h = image.h, w = image.w; // is in CSS pixels
var old_h = canvas.height, old_w = canvas.width;
var old_image;
if (first_image) {
ctx.clearRect(0, 0, old_w, old_h);
old_h = old_w = 0; // it's a new beginning
} else {
old_image = canvas.toDataURL("image/png"); // Android appears to wipe out image on resizing
}
// update canvas dims, and update its CSS style too
canvas.setAttribute("height", old_h + h);
canvas.setAttribute("width", Math.max(w, old_w));
canvas.style.height = canvas.height + "px";
canvas.style.width = canvas.width + "px";
// retrieve any old image into the resized canvas
if (old_image) {
var x = new Image();
x.src = old_image;
ctx.drawImage(x,0,0);
}
// add the given image
ctx.drawImage(img, 0, old_h);
$log.debug("IMG#" + image.id, w,"x",h, "appended at h=", old_h, "new dim=", canvas.width, "x", canvas.height);
} catch(e){$log.error("IMG#" + image.id, "ERROR in appending", e);
}
}
You have to wait for your images has loaded, add the drawing operations into their onload handler.
Also, for converting your svg element to a dataURL, use encodeURIComponent(new XMLSerializer().serializeToString(yourSVGElement)) method instead of outerHTML/innerHTML, you will avoid encoding issues and this if/else //probably ios..

Categories

Resources