FineUploader.js how to conditionally rescale and compress images? - image-uploading

This part of the documentation is relevant to what I want to do, but it looks hard-coded:
var uploader = new qq.FineUploader({
...
scaling: {
sizes: [
{name: "small", maxSize: 100},
{name: "medium", maxSize: 300}
]
}
});
I would like the rescaling to be done conditionally to images that aren't already compressed by the user.
Here is some pseudocode of what I want to accomplish:
if ((filesize < 1 megabytes) and (image.width*image.height > 1 megapixels)) {
Keep the original image without manipulating it in any way
} else {
Rescale image longest side to maximum of 1600 pixels
Compress the image to 60% quality
if (filesize still > 1mb) {
Keep compressing with more jpeg until it's under 800kb
}
}
I don't know if fine-uploader has the jpeg compression functioniality in-built (or if it's only rescaling), if it doesn't then perhaps J-I-C could be used.
If this conditional rescaling and compression can be accomplished with fine-uploader, how should it be done? If not, what other paths should I consider?

If you would like to "conditionally" scale images, you will need to implement this logic yourself using the scaleImage API method.
Construct a Fine Uploader instance. Do not include scaling options.
Contribute an onSubmitted callback handler. There, you can check the file using the getFile API method, and use this to determine if the file should be scaled.
If the file should be scaled, create a scaled Blob using scaleImage, and then submit the scaled Blob to Fine Uploader via the addFiles API method.

Related

How to shrink or manage an image's size in bytes

Python 3.6.6, Pillow 5.2.0
The Google Vision API has a size limit of 10485760 bytes.
When I'm working with a PIL Image, and save it to Bytes, it is hard to predict what the size will be. Sometimes when I try to resize it to have smaller height and width, the image size as bytes gets bigger.
I've tried experimenting with modes and formats, to understand their impact on size, but I'm not having much luck getting consistent results.
So I start out with a rawImage that is Bytes obtained from some user uploading an image (meaning I don't know much about what I'm working with yet).
rawImageSize = sys.getsizeof(rawImage)
if rawImageSize >= 10485760:
imageToShrink = Image.open(io.BytesIO(rawImage))
## do something to the image here to shrink it
# ... mystery code ...
## ideally, the minimum amount of shrinkage necessary to get it under 10485760
rawBuffer = io.BytesIO()
# possibly convert to RGB first
shrunkImage.save(rawBuffer, format='JPEG') # PNG files end up bigger after this resizing (!?)
rawImage = rawBuffer.getvalue()
print(sys.getsizeof(rawImage))
To shrink it I've tried getting a shrink ratio and then simply resizing it:
shrinkRatio = 10485760.0 / float(rawImageSize)
imageWidth, imageHeight = pilImage.size
shrunkImage = imageToShrink.resize((int(imageWidth * shrinkRatio),
int(imageHeight * shrinkRatio)), Image.LANCZOS)
Of course I could use a sufficiently small and somewhat arbitrary thumbnail size instead. I've thought about iterating thumbnail sizes until a combination takes me below the maximum bytes size threshold. I'm guessing the bytes size varies based on the color depth and mode and (?) I got from the end user that uploaded the original image. And that brings me to my questions:
Can I predict the size in bytes a PIL Image will be before I convert it for consumption by Google Vision? What is the best way to manage that size in bytes before I convert it?
First all, you probably don't need to maximize to the 10M limit posed by Google Vision API. In most case, a much smaller file will be just fine, and faster.
In addition to that, you may want to keep in mind that the aspect ratio might lead to different result. See this, https://www.mlreader.com/prepare-image-for-google-vision-api

How to smooth and extract an object from depth Image

I am using a dataset which provides depth images of human, I need to extract the object from this image or at least remove the other distortion in the image that not belong to the human body In Matlab.
a sample of images is shown below:
This is the output when I used
I = imread ('39.jpg');
human = sum(I,3)>10+10;
human
Any way to do that please?
thanks in Advance
For the image you show, where everything is grayscale but something is red, then just do:
so=imread('https://i.stack.imgur.com/hZOQv.jpg');
human=sum(abs(diff(single(so),1,3)),3)>20;
This essentially compares the difference in RGB values of the pixels, and gets the one above a threshold. If you have proper pngs, then the threshold should just be 1, however with jpg artifacts you may need a higher value, for this image 20 does the job.
There are some tiny artefacts in the result image, very likely due to jpg. When you do science, you need to store in png. If you have absolutely no other choice than jpg, then you may have artefacts.

Set quality for PNG images in MATLAB

I have a matlab code and it generates a .png image of 1024*768 resolution. The images are about 450KB in size and I need to know how to optimise and compress these images using matlab.
Can't I play with the quality as in JPEG ?
I read the imwrite manual and don`t seem to find a good way to do this.
Is there any way to achieve it in matlab ?
By design PNG files are lossless - there is no 'quality' to be adjusted (it's probably why a mod changed your question title).
You can reduce the number of colors in the image (the color depth) which will in turn reduce filesize (PNG-8 instead of PNG-24, for example), but the whole point of PNG is it produces lossless images, so there is simple no quality value a la JPEG.
Taken from the manual :
A parameter of input in case it is JPEG:
'Quality' - A number between 0 and 100; higher numbers mean higher quality (less image degradation due to compression), but the resulting file size is larger.
imwrite(x,'c:\1.jpg','Quality',10)
edit: Sorry, I answered this one while the title was JPEG and not PNG.
PNG doesn't support any quality settings - it is a lossless format. The compression it applies is generally as good as possible.

How to work with images(png's) of size 2-4Mb

I am working with images of size 2 to 4MB. I am working with images of resolution 1200x1600 by performing scaling, translation and rotation operations. I want to add another image on that and save it to photo album. My app is crashing after i successfully edit one image and save to photos. Its happening because of images size i think. I want to maintain the 90% of resolution of the images.
I am releasing some images when i get memory warning. But still it crashes as i am working with 2 images of size 3MB each and context of size 1200x1600 and getting a image from the context at the same time.
Is there any way to compress images and work with it?
I doubt it. Even compressing and decompressing an image without doing anything to it loses information. I suspect that any algorithms to manipulate compressed images would be hopelessly lossy.
Having said that, it may be technically possible. For instance, rotating a Fourier transform also rotates the original image. But practical image compression isn't usually as simple as just computing a Fourier transform.
Alternatively, you could write piecemeal algorithms that chop the image up into bite-sized pieces, transform the pieces and reassemble them afterwards. You might also provide a real-time view of the process by applying the same transform to a smaller version of the full image.
The key will be never to full decode the entire image into memory at full size.
If you need to display the image, there's no reason to do that at full size -- the display on the iPhone is too small to take advantage of that. For image objects that are for display, decode the image in scaled down form.
For processing, you will need to write custom code that works on a stream of pixels rather than an in-memory array. I don't know if this is available on the iPhone already, but you can write it yourself by writing to the libpng library API directly.
For example, your code right now probably looks something like this (pseudo code)
img = ReadImageFromFile("image.png")
img2 = RotateImage(img, 90)
SaveImage(img2, "image2.png")
The key thing to understand, is that in this case, img is not the data in the PNG file (2MB), but the fully uncompressed image (~6mb). RotateImage (or whatever it's called) returns another image of about this same size. If you are scaling up, it's even worse.
You want code that looks more like this (but there might not be any API's for you to do it -- you might have to write it yourself)
imgPixelGetter = PixelDecoderFromFile("image.png")
imgPixelSaver = OpenImageForAppending("image2.png")
w = imgPixelGetter.Width
h = imgPixelGetter.Height
// set up a 90 degree rotate
imgPixelSaver.Width = h
imgPixelSaver.Height = w
// read each vertical scanline of pixels
for (x = 0; x < w; ++x) {
pixelRect = imgPixelGetter.ReadRect(x, 0, 1, h) // x, y, w, h
pixelRect.Rotate(90); // it's now got a width of h and a height of 1
imgPixelSaver.AppendScanLine(pixelRect)
}
In this algorithm, you never had the entire image in memory at once -- you read it out piece by piece and saved it. You can write similar algorithms for scaling and cropping.
The tradeoff is that it will be slower than just decoding it into memory -- it depends on the image format and the code that's doing the ReadRect(). Unfortunately, PNG is not designed for this kind of access to the pixels.

Reduce UIImage size to a manageable size (reduce bytes)

I want to reduce the number of bytes of an image captured by the device, since i believe the _imageScaledToSize does not reduce the number of bytes of the picture (or does it?) - i want to store a thumbnail of the image in a local dictionary object and can't afford to put full size images in the dictionary. Any idea?
If you wish to simply compress your UIImage, you can use
NSData *dataForPNGFile = UIImagePNGRepresentation(yourImage);
to generate an NSData version of your image encoded as a PNG (easily inserted into an NSDictionary or written to disk), or you can use
NSData *dataForPNGFile = UIImageJPEGRepresentation(yourImage, 0.9f);
to do the same, only in a JPEG format. The second parameter is the image quality of the JPEG. Both of these should produce images that are smaller, memory-wise, than your UIImage.
Resizing a UIImage to create a smaller thumbnail (pixels-wise) using published methods is a little trickier. _imageScaledToSize is from the private API, and I'd highly recommend you not use it. For a means that works within the documented methods, see this post.
I ran into this problem the other day and did quite a bit of research. I found an awesome solution complete with code here:
http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/
You need to draw the image into a graphics context at a smaller size. Then, release the original image.
When you say 'physical size', are you talking about a print? Because you can just change the printer page size.
Are you talking about the number of pixels used to capture the image? As in, if you have a pixel array of 3000x2000, and you only want 150x150, then you can crop the images. At the time of capture, if you have a scientific imager, then you can just set the area that will be captured. The camera driver would include instructions for that. If you want to capture 3000x2000 in 1500x1000, you can try to bin the image, if that's what you need.
Or, you can use resampling post-capture in order to make the image smaller. One such algorithm is bicubic resampling, also linear resampling-- there are many variations.
I'm thinking this last is what you're most interested in... in which case, check out this Wikipedia page on the algorithm. Or, you can go to FreeImage and get a library that will read in the image and can also resize images.
UIImageJPEGRepresentation does the trick but I find that using the ImageIO framework often gets significantly better compression results for the same quality setting. It may be slower, but depending on your use case this may not be an issue.
(Code adapted for NSData from this blog post by Zachary West).
#import <MobileCoreServices/MobileCoreServices.h>
#import <ImageIO/ImageIO.h>
...
+ (NSData*)JPEGDataFromImage:(UIImage*)image quality:(double)quality
{
CFMutableDataRef outputImageDataRef = CFDataCreateMutable(kCFAllocatorDefault, 0);
CGImageDestinationRef imageDestinationRef = CGImageDestinationCreateWithData(outputImageDataRef, kUTTypeJPEG, 1, NULL);
NSDictionary* properties = #{
(__bridge NSString*)kCGImageDestinationLossyCompressionQuality: #(quality)
};
CGImageDestinationSetProperties(imageDestinationRef, (__bridge CFDictionaryRef)properties);
CGImageDestinationAddImage(imageDestinationRef, image.CGImage, NULL);
CGImageDestinationFinalize(imageDestinationRef);
CFRelease(imageDestinationRef);
NSData* imageData = CFBridgingRelease(outputImageDataRef);
return imageData;
}