How to Reduce PDF size in Android Studio - android-studio

In my app, I just want to print Bitmaps on PDF document and save it.
I can did that without any error.
But the thing is file size is too large like 20/30 MB.
Therefore I just try with Grayscale Bitmaps. After that file size is reduce somewhat (10 MB), but still it's very large.
My problem is how I can reduce the PDF File size in Android Studio.
if (img_SetImage) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false;
Bitmap bmp = BitmapFactory.decodeFile(img_Uri.getPath(), opt);
int[] xyImg = xy(bmp.getWidth(), bmp.getHeight(), 298, 175);
PdfDocument.PageInfo myPageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create();
PdfDocument.Page myPage = myPDFDoc.startPage(myPageInfo);
Canvas myCanvas = myPage.getCanvas();
Paint paint = new Paint();
paint.setAntiAlias(true);
float wScale, hScale, scaleFactor;
wScale = xyImg[0] / (float) bmp.getWidth();
hScale = xyImg[1] / (float) bmp.getHeight();
if (wScale >= hScale) {
scaleFactor = hScale;
} else {
scaleFactor = wScale;
}
myCanvas.scale(scaleFactor, scaleFactor);
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
myCanvas.drawBitmap(bmp, xyImg[2]/scaleFactor, xyImg[3]/scaleFactor, paint);
myPDFDoc.finishPage(myPage);
bmp.recycle();
}
private int[] xy(float width, float height, float left, float top) {
int finalWidth, finalHeight, finalLeft, finalTop;
float wScale, hScale, scaleFactor;
wScale = (436 / width);
hScale = (270 / height);
if (wScale >= hScale) {
scaleFactor = hScale;
} else {
scaleFactor = wScale;
}
finalWidth = (int) (width * scaleFactor);
finalHeight = (int) (height * scaleFactor);
finalLeft = (int) (left - (finalWidth / 2));
finalTop = (int) (top - (finalHeight / 2));
int[] returnValues = {finalWidth, finalHeight, finalLeft, finalTop};
return returnValues;
}

Related

at::Tensor to UIImage

I have a PyTorch model and try run it on iOS. I have the next code:
at::Tensor tensor2 = torch::from_blob(imageBuffer2, {1, 1, 256, 256}, at::kFloat);
c10::InferenceMode guard;
auto output = _impl.forward({tensor1, tensor2});
torch::Tensor tensor_img = output.toTuple()->elements()[0].toTensor();
My question is "How I can convert tensor_img to UIImage?"
I found that functions in PyTorch documentation:
- (UIImage*)convertRGBBufferToUIImage:(unsigned char*)buffer
withWidth:(int)width
withHeight:(int)height {
char* rgba = (char*)malloc(width * height * 4);
for (int i = 0; i < width * height; ++i) {
rgba[4 * i] = buffer[3 * i];
rgba[4 * i + 1] = buffer[3 * i + 1];
rgba[4 * i + 2] = buffer[3 * i + 2];
rgba[4 * i + 3] = 255;
}
size_t bufferLength = width * height * 4;
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, rgba, bufferLength, NULL);
size_t bitsPerComponent = 8;
size_t bitsPerPixel = 32;
size_t bytesPerRow = 4 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
if (colorSpaceRef == NULL) {
NSLog(#"Error allocating color space");
CGDataProviderRelease(provider);
return nil;
}
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorSpaceRef,
bitmapInfo,
provider,
NULL,
YES,
renderingIntent);
uint32_t* pixels = (uint32_t*)malloc(bufferLength);
if (pixels == NULL) {
NSLog(#"Error: Memory not allocated for bitmap");
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(iref);
return nil;
}
CGContextRef context = CGBitmapContextCreate(pixels,
width,
height,
bitsPerComponent,
bytesPerRow,
colorSpaceRef,
bitmapInfo);
if (context == NULL) {
NSLog(#"Error context not created");
free(pixels);
}
UIImage* image = nil;
if (context) {
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
if ([UIImage respondsToSelector:#selector(imageWithCGImage:scale:orientation:)]) {
float scale = [[UIScreen mainScreen] scale];
image = [UIImage imageWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
} else {
image = [UIImage imageWithCGImage:imageRef];
}
CGImageRelease(imageRef);
CGContextRelease(context);
}
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(iref);
CGDataProviderRelease(provider);
if (pixels) {
free(pixels);
}
return image;
}
#end
If I correctly understand, that function can convert unsigned char * to UIImage. I think that I need convert my tensor_img to unsigned char*, but I don't understand how I can do it.
The 1st code its a torch bridge and 2nd code is UIImage helper which I run from Swift. Anyway, I resolve that issue, we can close it. Code example:
for (int i = 0; i < 3 * width * height; i++) {
[results addObject:#(floatBuffer[i])];
}
NSMutableData* data = [NSMutableData dataWithLength:sizeof(float) * 3 * width * height];
float* buffer = (float*)[data mutableBytes];
for (int j = 0; j < 3 * width * height; j++) {
buffer[j] = [results[j] floatValue];
}
return buffer;

I am using following code of Scaling image in monotouch but it is not maintaining quality of image

public static class ImageHelper
{
public static UIImage Scale (UIImage source, SizeF newSize)
{
UIGraphics.BeginImageContext (newSize);
var context = UIGraphics.GetCurrentContext ();
context.InterpolationQuality=CGInterpolationQuality.High;
context.TranslateCTM (0, newSize.Height);
context.ScaleCTM (1f, -1f);
context.DrawImage (new RectangleF (0, 0, newSize.Width, newSize.Height), source.CGImage);
var scaledImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return scaledImage;
}
public static UIImage Rotate (UIImage image)
{
UIImage res;
using (CGImage imageRef = image.CGImage) {
CGImageAlphaInfo alphaInfo = imageRef.AlphaInfo;
CGColorSpace colorSpaceInfo = CGColorSpace.CreateDeviceRGB ();
if (alphaInfo == CGImageAlphaInfo.None) {
alphaInfo = CGImageAlphaInfo.NoneSkipLast;
}
int width, height;
width = imageRef.Width;
height = imageRef.Height;
int maxSize = Math.Max (width, height);
if (height >= width) {
width = (int)Math.Floor ((double)width * ((double)maxSize / (double)height));
height = maxSize;
} else {
height = (int)Math.Floor ((double)height * ((double)maxSize / (double)width));
width = maxSize;
}
CGBitmapContext bitmap;
if (image.Orientation == UIImageOrientation.Up || image.Orientation == UIImageOrientation.Down) {
bitmap = new CGBitmapContext (IntPtr.Zero, width, height, imageRef.BitsPerComponent, imageRef.BytesPerRow, colorSpaceInfo, alphaInfo);
} else {
bitmap = new CGBitmapContext (IntPtr.Zero, height, width, imageRef.BitsPerComponent, imageRef.BytesPerRow, colorSpaceInfo, alphaInfo);
}
switch (image.Orientation) {
case UIImageOrientation.Left:
bitmap.RotateCTM ((float)Math.PI / 2);
bitmap.TranslateCTM (0, -height);
break;
case UIImageOrientation.Right:
bitmap.RotateCTM (-((float)Math.PI / 2));
bitmap.TranslateCTM (-width, 0);
break;
case UIImageOrientation.Up:
break;
case UIImageOrientation.Down:
bitmap.TranslateCTM (width, height);
bitmap.RotateCTM (-(float)Math.PI);
break;
}
bitmap.DrawImage (new Rectangle (0, 0, width, height), imageRef);
res = UIImage.FromImage (bitmap.ToImage ());
bitmap = null;
}
return res;
}
}
Calling method=> UIImage ScaledImage =ImageHelper.Scale (ImageHelper.Rotate (downloadedImage), new SizeF (270, 260));
Please provide any solution to maintain quality as well as it will scale to required size.
Xamarin's UIImage implementation contains two different Scale() methods
Scale(System.Drawing.SizeF) : UIImage
Scale(System.Drawing.SizeF, float) : UIImage

how to write byte[] to Image with Landscape or Portrait properties?

I have a code which converts byte[] to image but my code always writes in Landscape mode even original image was Portrait. How can I detect original image's Page Orientation and write new Image with this properties? Any suggestions?
public void SendFax(byte[] file, string fileName)
{
try
{
MemoryStream ms = new MemoryStream(file);
Image imgSave = Image.FromStream(ms);
Bitmap bmSave = new Bitmap(imgSave);
Bitmap bmTemp = new Bitmap(bmSave);
Graphics grSave = Graphics.FromImage(bmTemp);
grSave.DrawImage(imgSave, 0, 0, imgSave.Width, imgSave.Height)
//Save Image to physical path
bmTemp.Save("C:/..." + fileName);
imgSave.Dispose();
bmSave.Dispose();
bmTemp.Dispose();
grSave.Dispose();
}
catch (Exception ex)
{
throw ex;
}
}
Try with this. Check for img height and width and based on the comparison decide portrait/landscape
int srcWidth = image.Width;
int srcHeight = image.Height;
int thumbWidth = width;
int thumbHeight;
Bitmap bmp;
if (srcHeight > srcWidth)
{
thumbHeight = (srcHeight / srcWidth) * thumbWidth;
bmp = new Bitmap(thumbWidth, thumbHeight);
}
else
{
thumbHeight = thumbWidth;
thumbWidth = (srcWidth / srcHeight) * thumbHeight;
bmp = new Bitmap(thumbWidth, thumbHeight);
}

resize UIImage in table cell programmatically

how can i resize the UIImage in table cell
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 5.0;
cell.imageView.frame=CGRectMake(0, 0, 20, 30);
cell.imageView.image =[UIImage imageNamed:#"Diseases.png"];
it is not working
Use this method, pass the size and image, and get the image then show in cell
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
You can also make your custom UITableViewCell, and design as you want to look it
This worked for me.
///////////////////////////////// TO RESIZE IMAGE //////////////////////////////////
////////// FIRST WRITE DESIRED SIZE AND CALL BELOW FINCTION ///////
CGSize newSize ;
newSize.width = 30;
newSize.height = 30;
UIImage *imgSelectedNew = [self imageWithImage:savedImage scaledToSize:newSize];
- (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSize:(CGSize)targetSize
{
//UIImage *sourceImage = sourceImage;//= self;
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor < heightFactor)
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor < heightFactor) {
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
} else if (widthFactor > heightFactor) {
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
// this is actually the interesting part:
UIGraphicsBeginImageContext(targetSize);
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if(newImage == nil)
NSLog(#"could not scale image");
return newImage ;
}
well m also n indorian , Gud to see the other one !!! :)

thumbnail, cut resize and upload to DB

I use this code to create thumbnails and then store the original and the thumbnail into a DB. It creates tn that are always of a fixed sized and if the original image is wither than it's higher it is cut and then resized to the fixed size.
The code is working however I would really appreciate some help modifying this code to do the following (I have tried it but didn't succeeded):
Make high-quality thumbnails
cut the height if the image is way taller
than it's width (If the width is
200px and height is 1000px what will
happen?)
Accept png and tiff.
This is the code so far:
public void imgUpload()
{
if (ImgUpload.PostedFile != null)
{
System.Drawing.Image image_file = System.Drawing.Image.FromStream(ImgUpload.PostedFile.InputStream);
string fileName = Server.HtmlEncode(ImgUpload.FileName);
string extension = System.IO.Path.GetExtension(fileName);
bool sizeError = false;
if(image_file.Width < 200)
sizeError = true;
if(image_file.Height < 250)
sizeError = true;
if ((extension.ToUpper() == ".JPG") && !sizeError)
{
//**** Resize image section ****
int image_height = image_file.Height;
int image_width = image_file.Width;
int original_width = image_width;
int original_height = image_height;
int max_height = 250;
int max_width = 200;
Rectangle rect;
if (image_width > image_height)
{
image_width = (image_width * max_height) / image_height;
image_height = max_height;
rect = new Rectangle(((image_width - max_width) / 2), 0, max_width, max_height);
}
else
{
image_height = (image_height * max_width) / image_width;
image_width = max_width;
rect = new Rectangle(0, ((image_height - max_height) / 2), max_width, max_height);
}
Bitmap bitmap_file = new Bitmap(image_file, image_width, image_height);
Bitmap new_bitmap_file = bitmap_file.Clone(rect, bitmap_file.PixelFormat);
System.IO.MemoryStream stream = new System.IO.MemoryStream();
new_bitmap_file.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
byte[] imageThumbnail = new byte[stream.Length + 1];
stream.Read(imageThumbnail, 0, imageThumbnail.Length);
Bitmap Original_bitmap_file = new Bitmap(image_file, original_width, original_height);
System.IO.MemoryStream Original_stream = new System.IO.MemoryStream();
Original_bitmap_file.Save(Original_stream, System.Drawing.Imaging.ImageFormat.Jpeg);
Original_stream.Position = 0;
byte[] imageOriginal = new byte[Original_stream.Length + 1];
Original_stream.Read(imageOriginal, 0, imageOriginal.Length);
//**** End resize image section ****
saveImage(imageThumbnail, imageOriginal, IDTextBox.Text);
lblOutput.Visible = false;
}
else
{
lblOutput.Text = "Please only upload .jpg files and make sure the size is minimum 200x250";
lblOutput.Visible = true;
}
}
else
{
lblOutput.Text = "No file selected";
lblOutput.Visible = true;
}
}
Here is an example of how to scale and crop an image:
Bitmap b = new Bitmap(200, 1000);
using (var g = Graphics.FromImage(b))
{
g.DrawLine(Pens.White, 0, 0, b.Width, b.Height);
}
b.Save("b.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
Bitmap thumb = new Bitmap(100, 100);
using (var g = Graphics.FromImage(thumb))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(b, new Rectangle(0,0,100,100), new Rectangle(0, 400, 200, 200), GraphicsUnit.Pixel);
}
thumb.Save("thumb.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
I think you can adapt the code to all what's and if's about when the ratio height/width is to high, etc.
I use the following code when creating thumbnails for http://www.inventerat.se and a few other sites and it works like a charm:
public static Bitmap WithinMaxSize(Image imgPhoto, int maxWidth, int maxHeight)
{
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int destWidth;
int destHeight;
float sourceAspect = sourceWidth / (sourceHeight * 1.0F);
float maxAspect = maxWidth / (maxHeight * 1.0F);
if (sourceAspect > maxAspect)
{
// Width is limiting.
destWidth = maxWidth;
destHeight = (int)Math.Round(destWidth / sourceAspect);
}
else
{
// Height is limiting.
destHeight = maxHeight;
destWidth = (int)Math.Round(destHeight * sourceAspect);
}
Bitmap bmPhoto = new Bitmap(destWidth, destHeight);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.Clear(Color.White);
grPhoto.CompositingMode = CompositingMode.SourceCopy;
grPhoto.CompositingQuality = CompositingQuality.HighQuality;
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto, 0, 0, destWidth, destHeight);
grPhoto.Dispose();
return bmPhoto;
}
Just don't forget to dispose the Bitmap returned from this method.
It does not work very well if users are uploading very large images (e.g. > 5000 * 5000 pixels) though. If that is a requirement, I would recommend using ImageMagick or a similar imaging package.
To accept png and tiff, just adjust how You check the file extension so that You accept "png", "tif" and "tiff" as well. Support for tiff is a bit sketchy in .NET though since tiff itself is only a container for MANY different encodings.

Resources