How to avoid image duplication in image gallery of iOS device? - iphone

I want to store the images to photo gallary. But if images are already available at photo gallary then how to distinguish for whether imgaes are already exists or not? I didnt find property like unique identifier or should i compare by taking data in the form of NSdata?
thanks..

You can maintain a dictionary of hashes for each the image in the photo gallery, and then show only additional images who do not hashes are not present in the dictionary
As a reminder, you can check for an object in a dictionary by doing:
if ([myDictionary objectForKey:variableStoringImageHash] == nil) {
//No such image present
}
else {
//image is present
}
For a bit about hashing an image, this might help:
iPhone: fast hash function for storing web images (url) as files (hashed filenames)

I am not sure if what eitan27 says will work so as an alternative I would say that your best hope is comparing NSData objects. But this as you can see will become very tedious as there will be n number of images in library and comparing each one for repetition does't make sense , still if you want to compare data you look at this answer which will give you a fraction of how much the data is matching.

Related

SwiftUI List memory issue, images not deallocating from RAM causing crash

I am loading images into a SwiftUI List. When too many images are scrolled down, RAM skyrockets and crashes app. Why are images not deallocated as user scrolls down past them?
I am loading images as so:
List(allProducts, id: \.self) { product in
Image(uiImage: UIImage(data: dataFromRealmDB[product]))
}
My intuition tells me that there must be something to deallocate it manually from memory, so I am trying the following. Please let me know if you how to fill in the blank.
List(allProducts, id: \.self) { product in
Image(uiImage: UIImage(data: dataFromRealmDB[product])).onDisappear(perform: {
"WHAT SHOULD GO HERE TO MAKE THE IMAGE GET PURGED FROM RAM?"
}
}
If my suggested solution is not possible, please let me know as well.
UPDATE
I have changed the way images are stored. Now they are stored with FileManager instead of saving them to the RealmDB. This is my function to get the image. Still memory usage increase causing a crash, there is no deallocation from SwiftUI.
func getImage(link: String) -> Image? {
let lastPath = URL(string: link)?.lastPathComponent
if let dir = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) {
let image : UIImage? = UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent(lastPath!).path)
if image != nil {
return Image(uiImage: UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent(lastPath!).path)!)
}
}
return Image("noImg")
}
The code in the question is a bit incomplete but the answer really isn't a coding answer, it's more of a overall design answer.
Realm objects are lazily loaded and will essentially never overrun memory if used properly; they are only in memory when in use; e.g. a Realm Results object having 10,000 objects is easily handled, memory is allocated and deallocated automatically.
On that note, if you store Realm objects in other, non-Realm objects like an array, that totally changes the memory impact and can overwhelm the device.
But, and more importantly:
Realm is not a good way to store Blob data (full size pictures). A Realm property has a finite amount of storage of 16Mb and an image can easily go way beyond that.
There are other options for picture storage from MongoDB and Firebase.
See my answer to this question for more details
Lastly, you should be using pagination to control how many images are loaded at a time from whatever source you use; that will allow you to more easily control the memory allocation and UI.
So that last part is important, no matter what the technique is, loading a bunch of images into memory is going to eventually overwhelm the device so as you can see, switching to using FileManger to load the images from disk instead of Realm is not going to be a long term solution; pagination is the way to go.
There are some third party libraries available to help with that and/or you can craft your own. Do a search here on SO for 'image pagination' as it's discussed a lot
Oh - one other thing; please use thumbnails for your UI! You only really need to display full size images if the user taps or selects it - then you can load it from disk. Firebase Storage can actually do that for you; when you upload an full size image, it can (on their server) create a thumbnail for your UI.
Likewise, thumbnails are tiny and Realm can easily handle those; the design would be an object like this
class MyImageObject: Object {
#Persisted var imageURL: //a string or url to where it's stored on disk
#Persisted var thumbnail: Data!
#Persisted var image_name = "" //the image name
}
Are you sure it is not related to the fact you fetch the image raw data from the Database? According this question a SwiftUI List works like a tableview - i.e reusing cells.
I think the fact you are using a data base to hold the raw data of the images causes the spike in memory.
This is kind of an opinion based answer but I’d recommend on either bundling the images in advance in the application (if your business logic supports it), using names in the DB and init them by name.
Or hosting them remotely and fetching on demand.

Lets get the source of the photo using photo ID

I know that I could do something like below and get an array of images
FB.api('/{photo_id}/', function(res) { console.log(res) })
The widest image is just 720px. That's not very good for bigger screen developers and users. Any thoughts on how to get the original uploaded image
For example. Lets refer to the man himself Mar Zuckerberg
Get the cover using api
FB.api('/4/?fields=cover', function(res) { console.log(res) })
Now as you may see the returned cover is so low resolution and no good. Where as this is the result I'm expecting
https://scontent-lax1-1.xx.fbcdn.net/hphotos-frc3/t31.0-8/c0.93.1434.531/1275272_10101026493146301_791186452_o.jpg
Take a look at the images field, this will contain an array of the available sizes, the number and available sizes can vary based on the original size of the image though.
See https://developers.facebook.com/docs/graph-api/reference/photo for more details.

Remove PdfImageOject from a PDF

I have 1000th of PDF generated from emails containing .png (I am not owner of the generator). For some reasons, those PDF are very very slow to render with the Imaging system I am using (I am not the developer of that system and may not change it).
If I use iTextSharp and implement a IRenderListener to count the Images to be rendered, there are thousands per page (99% being 1 or 2 pixels only). But if I count the Images in the resources of the PDF, there are only a few (~tens).
I am counting the images in the resources, per page, with the code here after
var dict = pdfReader.GetPageN(currentPage)
PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(dict.Get(PdfName.RESOURCES));
PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
if (xobj != null)
{
foreach (PdfName name in xobj.Keys)
{
PdfObject obj = xobj.Get(name);
if ((obj.IsIndirect()))
{
PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
PdfName subtype = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
if (PdfName.IMAGE.Equals(subtype))
{
Count++
And my IRenderListener looks like this:
class ImageRenderListener : IRenderListener
{
public void RenderImage(iTextSharp.text.pdf.parser.ImageRenderInfo renderInfo)
{
PdfImageObject image = renderInfo.GetImage();
if (image == null) return;
var refObj = renderInfo.GetRef();
if (refObj == null)
Count++; // but why no ref ??
else
Count++;
}
I just started to learn about PDF specification and iTextSharp this evening, to analyze my PDF and understand what could be wrong... if I am correct, I see that many images to be rendered that are not referencing a resource (refObj == null) and that they are .png (image.streamContentType.FileExtension = "png"). So, I think those are the images making the rendering so slow...
For testing purpose, I would like to delete those images from the PDF but don't find how to proceed.
I only found code samples to remove image that are in the resources... but the images I want to delete are not :/
Is there any code sample somewhere to help me ? I did google on "iTextSharp remove object", etc... but there was nothing similar to my case :(
Let me start with the blunt observation that you have a shitty PDF.
The image you see when opening the PDF in a PDF viewer seems to be composed of several small 1- or 2-pixel images. The drawing operations to show these pixels one by one is suboptimal, no matter which imaging system you use: you are faced with a bad PDF.
In your first snippet, I see that you loop over all of the indirect objects stored in the the XObject resources of each page in search of images. You count these images, resulting in a number of Image XObjects stored in the PDF. If you add up all the Count values for all the pages, this number can be higher than the actual number of Image XObject stored in the PDF as you don't take into account that some images can be reused on different pages.
You do not count the inline images that are stored in the content streams. I'm biased. In the ISO committees for PDF, I'm on the side of the group of people saying that "inline images are evil" and "inline images should die". For now, we didn't succeed in getting rid of inline images, but we introduced some substantial limitations that should reduce the (ab)use of inline images in PDF that conform to ISO-32000-2 (the PDF 2.0 spec that is due in 2016).
You've already discovered that your PDF has inline images. Those are the images where refObj == null. They are not stored as indirect objects; they are stored inline, in the content stream of the page. As you can imagine based on my feelings towards inline images, I consider your PDF being a bad PDF for this reason (although it does conform to ISO-32000-1).
The presence of inline images is a first explanation why you have a different image count: when you loop over the indirect objects you only find part of the images. When you parse the document for images, you also find the inline images.
A second explanation could be the fact that the Image XObject are used more than once. That's the whole point of not using inline images. For instance: if you have an image that represents a logo that needs to be repeated on every page, one could use inline images. That would be a bad idea: the same image bytes would be present in the PDF as many times as there are pages. One should use an Image XObject. In this case, the image bytes of the logo are stored only once in an indirect object. There's a reference to this object from every page, so that the image bytes are stored in the document only once. In a 10-page document, you can see 10 identical images on 10 pages, but when looking inside the document, you'll find only one image that is referenced from every page.
If you remove Image XObjects by removing the indirect objects containing the image stream objects, you have to be very careful: are you sure you're not corrupting your document? Because there's a reference to the Image XObject in the content stream of your page. This reference points to an entry in the /XObjects entry of the page's /Resources. This /XObject references to the stream object with the image bytes. If you remove that indirect object without removing the references (e.g. from the content stream), you break your PDF. Some viewers will ignore those errors, but at some point in time some tool (or some body) is going to complain that your PDF is corrupt.
If you want to remove inline images, you have to parse all the content streams in your PDF: page content streams as well as Form XObject content streams. You have to rewrite all these streams and make sure all inline images are removed. That is: all objects that that start with the BI operator (Begin Image) and end with the EI operator (End Image).
That's a task for a PDF specialist who knows both iTextSharp and ISO-32000-1 inside-out. The solution to your problem probably doesn't fit into an answering window on StackOverflow.
I'm the original author of iText. From a certain point of view, iText is like a sharp knife. A sharp knife is a very good tool that can be used for many good things. However, you can also seriously cut your fingers when you're not using the knife in a correct way. I hope you'll be careful and that you're not going to create a whole series of damaged PDF files.
For instance: you assume that some of the files in the PDF are PNGs because iText suggests to store them as PNGs. However: PNG is not supported by ISO-32000-1, so your assumption that your PDF contains PNGs is wrong. I honestly worry when I see questions like yours.

What will be the size(memory)of NSMutableArray?

I am parsing json data,and i store them into an NSMutableArray.
For each data,parameters are as the following format,
{
"id":"6",
"username":"biju",
"password":"biju123",
"usertype":"2",
"first_name":"biju",
"last_name":null,
"email":"b#b.com",
"blocked":"N",
"created":"2012-11-02 16:03:19",
"image":"http:\/\/192.168.1.254\/eatthos\/assets\/upload\/users\/1351852399_thumb.jpg","thumb_image":"1351852399_thumb.jpg",
"menu_image":"0",
"thumb_menu_image":"0",
"city":"njdfh",
"favorite_food":"kafh",
"favorite_restaurant":"kafdhj",
"phone_number":"0",
"description":"0",
"token":"Dwx0DG",
"fb_unique_id":null,
"account_type":"normal",
"twitter_id":null,
"followers":"5",
"follow":"N"
}
i am parsing about 100K of data,what will be the size(memory) of that array ?
Will it be a memory issue if i use it for an iphone app ?
You can try to find out size of your array with the following piece of code :
size_t total;
id obj;
for (obj in array)
{
total += class_getInstanceSize([obj class]);
}
NSLog(#"Array size : %ld",total); //This will return you size in bytes
you need to do : #import <objc/runtime.h>
The array itself won't take that much space -- it's just a bunch of pointers. An array with tens of thousands of items can still only be a few dozen kilobytes. The space taken by the objects that the array contains is likely to be much more significant. But that is something only you can see -- there is no "size of an object in an array." It's like asking "How big is a ball?" It is possible that your data's space needs are problematic, and it's equally possible that there's no problem at all. As with many programming questions, I think the best answer is to try and see for yourself.
Why can not you download 100 records each time like an apps then are in app store
So, That the app will load quicker that before
If u want to see the flow of the memory you can go through this link http://mobileorchard.com/find-iphone-memory-leaks-a-leaks-tool-tutorial/

how to use "FindBarcodesInUIImage"?

I am developing Barcode scanner application for iPhone.
Library: RedLaser
Just I want to scan the barcode from the existing image, not from camera.
I didn't get any documentation to call FindBarcodesInUIImage method manually.
Can I get any sample code ?
Does this snippet from the documentation help?
This method analyses a given image and returns information on any barcodes discovered in the image. It is intended to be used in cases where the user already has a picture of a barcode (in their photos library, for example) that they want to decode. This method performs a thorough check for all barcode symbologies we support, and is not intended for real-time use.
When scanning barcodes using this method, you cannot (and need not) specify a scan orientation or active scan region; the entire image is scanned in all orientations. Nor can you restrict the scan to particular symbol types. If such a feature is absolutely necessary, you can implement it post-scan by filtering the result set.
FindBarcodesInUIImage operates synchronously, but can be placed in a thread. Depending on image size and processor speed, it can take several seconds to process an image.
void ScanImageForBarcodes(UIImage *inputImage)
{
NSSet *resultSet = FindBarcodesInUIImage(inputImage);
// Print the results
NSLog(#"%#", resultSet);
}
If the SDK did not find any barcodes in the image, the log message will be (null). Otherwise, it will be something like:
{(
(0x19e0660) Code 39: 73250110 -- (1 finds)
)}
This log message indicates a found set containing one item, a Code 39 barcode with the value "73250110".
Remember that the SDK is not guaranteed to find barcodes in an image. Even if an image contains a barcode, the SDK might not be able to read it, and you will receive no results.