How can I pick images directly as jpg or png on iOS?
If this feature isn't available: How can I convert it very fast and don't have to wait a long time?
Edit: I want to prevent picking .heic because I have to send it to an server, which handles jpg and png and not .heic
Thanks to Mohammad Assad Arshad!
It can be solved by pub.dev/packages/file_picker.
An additional explanation:
https://pub.dev/packages/file_picker allows you to pick files/images etc. and the file type of images is .jpg
https://pub.dev/packages/multi_image_picker allows you to pick images too, but takes the original file format; e.g. .heic, .jpg, .png
i select images with filepicker https://pub.dev/packages/file_picker
FilePickerResult result;
try {
result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpeg', 'jpg', 'heic', 'pdf'],
);
} catch (e) {
print('Exep: ****${e}***');
}
now you can check the extention of the file, use the package path.dart as p and package https://pub.dev/packages/heic_to_jpg to convert image to jpeg
File file = File(result.files.first.path);
String fileExtension = p.extension(file.path).replaceAll('.', '');
if (fileExtension == 'heic') {
print('convert to jpeg');
String jpegPath = await HeicToJpg.convert(file.path);
file = File(jpegPath);
fileExtension = 'jpeg';
}
do not forget do the same if you use imagePicker with source camera.
you can use multi_image_picker 4.6.7 to pick image in iOS for HEIC images.
Related
I have a method that copies images and videos the user selected from the iOS photo library to a temporary cache folder (under the app's Documents directory) but image files that are JPEG or TIFF have their creation and modified dates changed to current date when using FileManager.default.copyItem. I noticed this issue only occurs for some image types and for some others (GIF, PNG, ...) the original creation and modified date is retained.
Here's the method I'm using for it. I'm aware copyItem isn't the most optimal to use (non-atomic). Does anyone know a better way to copy files while retaining dates of all supported file types?
public func copyFileToUploadCache(fileURL: URL) -> URL?
{
guard let uploadCacheFolderURL = uploadCacheFolderURL else { return nil }
let temporaryFileURL = uploadCacheFolderURL.appendingPathComponent(fileURL.lastPathComponent)
var result: URL? = nil
do
{
try FileManager.default.copyItem(at: fileURL, to: temporaryFileURL)
result = temporaryFileURL
}
catch
{
print("Error copying file to upload cache: \(error.localizedDescription).")
}
return result
}
I'm trying to copy a GIF image to the UIPasteboard in swift, at the moment it only copies the static version of the image and seems to convert it to PNG looking at the file extension when I upload it somewhere.
Wondered if anyone had any idea how to achieve this? All other soltions I've found only seem to work when getting NSData from a URL rather than from an image in the bundle
For anyone who ever encounters this problem I managed to find a solution
let url: NSURL = NSBundle.mainBundle().URLForResource("\(self.imageNames[indexPath.row])", withExtension: ".gif")!
let data: NSData = NSData(contentsOfURL: url)!
UIPasteboard.generalPasteboard().setData(data, forPasteboardType: "com.compuserve.gif")
As it turns out you do need to use a URL and extract the NSData of the GIF from that URL.
Here I am getting the URL of the GIF that is in my bundle, searching for it using the name and extension of the image. I am then setting the data in the pasteboard and bingo we have an animated GIF when pasting the result from the pasteboard
It doesn't look like the image property on the pasteboard supports the GIF type.
The associated array of representation types is UIPasteboardTypeListImage, which includes types kUTTypePNG and kUTTypeJPEG.
You could probably do this using the NSData from the GIF though:
import MobileCoreServices
// ...
var image = UIImage(...)
let data = NSData(bytes: &image, length: sizeof(UIImage))
UIPasteboard.generalPasteboard().setData(data, forPasteboardType: kUTTypeGIF as String)) // com.compuserve.gif
I am developing a phoneGap application in IOS where I use getPhoto('Camera.PictureSourceType.PHOTOLIBRARY');
to access the photo library and select an image. following is the onPhotoURISuccess method where I need to get the url of the image and pass it to my native plugin to validate it's filesize, resolution and file extension.
this is my getPhoto() method
// A button will call this function
function getPhoto(source)
{
// Retrieve image file location from specified source
navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 100,
destinationType: navigator.camera.DestinationType.NATIVE_URI, sourceType: source });
}
and this is the onPhotoURISuccess method,
// Called when a photo is successfully retrieved
function onPhotoURISuccess(imageURI)
{
img_uri = imageURI;
console.log('NATIVE_URI==>'+img_uri);
// Get image handle
var imgPrev = document.getElementById('imgPreview');
// Unhide image elements
imgPrev.style.display = 'block';
// Show the captured photo
// The inline CSS rules are used to resize the image
imgPrev.src = imageURI;
}
I have three options for this according to the phoneGap documentation. using DATA_URL, FILE_URI or NATIVE_URI.
FILE_URI seems to be hiding underlying data of the image where it always returns me a jpeg image thus the actual extension is hidden
assets-library://asset/asset.JPG?id=5CF16D20-9A80-483A-AC1C-9692123610B1&ext=JPG
I want to know how to get the actual image name along with the extension from this.
I need to get the image name and validate the extension.
someone please do help me with posssible approach for me to follow
thanks in advance
If you could get an url to asset, which is
assets-library://asset/asset.JPG?id=5CF16D20-9A80-483A-AC1C-9692123610B1&ext=JPG
You can get real name of file, by this asset:
NSString* originalFileName = [[yourALAsset defaultRepresentation] filename];
I'm using MonoTouch and I have a UIImage (displayed in a UIImageView and it looks good) and I'm trying to convert it to NSData, but AsJPEG and AsPNG returns null. What can be the problem?
My code looks like this:
NSError err;
NSData imageData = CroppedImageView.Image.AsJPEG(); // imageData is null!
if (!imageData.Save ("tmp.png", true, out err)) {
Console.WriteLine("Saving of file failed: " + err.Description);
}
The AsJPEG method calls UIImageJPEGRepresentation and its return value is documented as:
A data object containing the JPEG data, or nil if there was a problem generating the data. This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format.
The is similar to many API in iOS (and OSX) where exception are not commonly used (and null is used to report some kind of error).
Anyway you should check your image dimensions and properties - they might give you an hint at something that would not translate into a JPEG bitmap.
Also since the NSData can represent a very large amount of memory you should try to limit it's life, e.g.:
using (NSData imageData = CroppedImageView.Image.AsJPEG ()) {
NSError err;
if (!imageData.Save ("tmp.jpg", true, out err)) {
Console.WriteLine("Saving of file failed: " + err.Description);
}
}
It looks like you are writing to a file in the current directory of the app, this is readonly.
You should use:
var path = System.IO.Path.GetTempFilename();
or
var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "tmp.png");
Like you would do on other platforms, and use a file from there.
You can also use Environment.SpecialFolder.MyDocuments.
The AsJPEG returned null because the image size was too big (it was taken with an iPhone 5). After I Scaled it down by 2, it generates the data properly.
I read on the reference that from iOS version 4.+ with the method imageNamed of UIImage object, the file extension is not required.
From UIImage class reference:
Special Considerations.
On iOS 4 and later, the name of the file is not required to specify
the filename extension. Prior to iOS 4, you must specify the filename
extension.
But it seems that this only work with PNG files.
If my code is:
[UIImage imageNamed:#"test"];
The image loads only if the file is test.png
The image doesn't load if it's test.jpg.
For me it is a big problem because I need to maintain a dynamic image loading (I do not know at runtime if the image I want to load is png or jpg).
Please can you help me?
Thanks.
The latest developer reference states the missing piece of information:
Special Considerations
On iOS 4 and later, if the file is in PNG format, it is not necessary to specify the .PNG filename extension. Prior to iOS 4, you must specify the filename extension.
One possible reason that the library gives PNGs special treatment, is that the iOS hardware is optimized for PNGs. PNG images stored in the application bundle are optimized by Xcode, changing the byte order of the PNG images to match the graphics chip of the iPhone device. (see this question: Is PNG preferred over JPEG for all image files on iOS?).
If you know that you will only have a PNG or a JPG, an alternative solution is to create a category on UIImage as per below.
- (UIImage*) jgcLoadPNGorJPGImageWithName:(NSString*)name {
UIImage * value;
if (nil != name) {
value = [UIImage imageNamed:name];
if (nil == value) {
NSString * jpgName = [NSString stringWithFormat:#"%#.jpg", name];
value = [UIImage imageNamed:jpgName];
}
}
return value;
}
If you have these images bundled in your app, you SHOULD know their extensions.
If you're getting them from an online source and you have them as NSData, you can use this code here to determine the type.
+ (NSString *)contentTypeForImageData:(NSData *)data {
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
case 0xFF:
return #"image/jpeg";
case 0x89:
return #"image/png";
case 0x47:
return #"image/gif";
case 0x49:
case 0x4D:
return #"image/tiff";
}
return nil;
}
As per the top answer in this question.