Image quality of socially shared image - ios

Problem Resume:
I take a photo with camera or chose one from the library, then add some UITextFields to it (next to UIImageView with the chosen picture), create one UIImage of it all, and then I want to share this, particularly on Facebook and on Twitter. I am able to do this, however the quality of the image drops significantly. How can I adjust the code so that the quality stays on top?
Long description with code and images
First of all, I chose between camera and library. Then, after I pick an image in some way, I get it with
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
method, where I assign the image to my global UIImage *chosenImage, with which I use it afterwards.
Then, I add the chosenImage to the UIImageView, and as a sibling, I add an UITextField, like this:
UIImageView *chosenImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, actualHeight - 50)];
[chosenImageView setBackgroundColor:[UIColor clearColor]];
[chosenImageView setContentMode:UIViewContentModeScaleAspectFill];
[chosenImageView setClipsToBounds:YES];
[chosenImageView setImage:chosenImage];
UITextField *textFieldName = [[UITextField alloc] initWithFrame:CGRectMake(15, 15, 290, 30)];
[textFieldName setBackgroundColor:[UIColor blueColor]];
[textFieldName setDelegate:self];
[textFieldName setTag:-1];
[textFieldName setText:textName];
[textFieldName sizeToFit];
[textFieldName setContentScaleFactor:2.0];
[pageView addSubview:textFieldName];
[pageView addSubview:chosenImageView];
After this, I have a 'share this!' button which, after clicked, presents the possibility to share the image to Facebook and Twitter. I then get the UIImage *imageToShare with this method to convert the UIView to UIImage (which seems to be working alright, imho):
- (UIImage *)changeViewToImage:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions([view bounds].size, NO, 0);
[[view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
It seems that the quality of the shared picture is the same for Facebook and Twitter, and the same in this case means really bad.
the code I use for twitter sharing:
SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#""];
[tweetSheet addImage:imageToShare];
[tweetSheet setCompletionHandler:^(SLComposeViewControllerResult result) {
[self dismissViewControllerAnimated:YES completion:nil];
}];
[self presentViewController:tweetSheet animated:YES completion:nil];
and the code I use for Facebook share:
NSDictionary *params = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:UIImagePNGRepresentation(imageToShare), imageDescription, nil] forKeys:[NSArray arrayWithObjects:#"source", #"message", nil]];
[FBRequestConnection startWithGraphPath:#"me/photos" parameters:params HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
[[[UIAlertView alloc] initWithTitle:#"Success!" message:#"Your photo was successfully posted to your Facebook Wall" delegate:nil cancelButtonTitle:#"Ok :)" otherButtonTitles:nil, nil] show];
[self returnFromShareView];
}];
However, I've added some code to save the imageToShare to the documents:
NSData *data = UIImagePNGRepresentation(imageToShare);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"currentImage.png"]; //Add the file name
[data writeToFile:filePath atomically:YES]; //Write the file
and when I look it up there, it looks fairly fine! Which really makes me wonder why I don't use an envelope with printed picture (the one saved to the documents, of course!), and don't send it to Menlo Park, CA and South of Market, CA instead of trying to solve this ridiculous issue.
Now come the pictures!
umh.. So after I tried to upload the images here, the uploading thingy turned the .png image to horrible quality as well!!! Aagh, I thought stackOverflow is with me!
Anyways, here are the pictures (uploaded here), and corresponding links, which shows the actual images, on my server (which I hope won't destroy them as well)
Picture uploaded to Facebook: Facebook image on my server
Picture uploaded to Twitter: Twitter image on my server
Picture from the documents: Picture from the documents on my server (there is a huge difference!)
So, does anybody know what settings should I chose for the image in the code to make the quality (even after .jpg compression, which is done everywhere it seems, even here) at least somehow better? And as it seems to me, it happens only on the solid background with text on it (when I tried to upload an image without the background, it looked better, but there must be a way how to make it look better with background as well)
Thanks!
EDIT
As it turns out, the problem might not be with the sharing stuff, but with the jpeg compression itself. As it states here in the answer: Facebook: Ways to preserve image quality of uploaded images?,
"JPEG is not suitable for images with text, large blocks of color, or simple shapes, because crisp lines will blur and colors can shift. http://graphicssoft.about.com/od/graphicformats/f/summary.htm "
So I guess there is no solution, as Facebook, Twitter and even stack.imgur use jpeg compression, and as long as there will be an 'image with text, large blocks of color, or simple shapes', it'll come badly. Too bad.

JPEG compression works best for continuous tone imagery such as photos. It dos not work well with areas of solid color and sharp traditions such as text. Png/Gif works much better. There are some formats that deal with this better such as Google WebP which Facebook considered using but abandoned.
You best best is to stick with JPEG and play with the JPEG encoding setting but there are a few things you can do. Adjust your font either with the built in iOS fonts or use your own custom font. Since sharp transition of solid color cause a problem, avoid using Serif fonts. Also the fatter the font and larger it is the better. IOS supports custom fonts so play around with different open source fonts and find one at the biggest size you can accept. Follow this article
http://codewithchris.com/common-mistakes-with-adding-custom-fonts-to-your-ios-app/.
Another thing that help is anti aliasing. This is where the edge colors are blurred making the text seem more readable(over simplification). The text will not be anti aliased and you can not easily force anti aliasing but you could fake it. Create the text at a larger size (2 to 3x) in a separate image with transparency and scale it down before adding it over the picture. The image interpolation will blur the images giving you a poor mans anti aliasing.

Related

UIActivityViewController share to Facebook

I want to use UIActivityViewController to share something to Facebook, and I want to customize my "image card space", So I can click the blue area and direct to other website
the image is from Facebook, and it say the blue area is image card space
this is a screen shot from other app, this app use UIActivityViewController too, so I believe it can be done, I try to search the information about how to implement, but it fail, maybe I use the wrong key word
this is my code
UIImage *Img = [UIImage imageNamed:#"myImg.png"];
NSString *myString = #"hi, I am strign";
NSURL *myUrl = [NSURL URLWithString:#"www.google.com"];
NSArray *items = #[myString, Img, myUrl];
UIActivityViewController *avc = [[UIUIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
self presentViewController:avc animated:YES completion:nil];
and this is what I get
just Image appear
myString does not appear, I guess this is because,it will appear in"user message field", and this is illegal(the first image), so iOS delete it
but where is my URL? if I post this to Facebook, it just a Image, I can't direct to other website
Is anyone know how to customize image card space?
=====================edit==================
ok, i think i got it
the app not customize the area
it just put the url
and iOS get the data automatly, and display it
so, just put url to UIActivityViewController
if anything wrong please re correct me

How can parse all the images form Website in IOS SDK

I like to implement image upload functionality in my app.For that I like to give some option for user to choose image.
One of the option is choose image from website.
If the user enter an url link in the text box and click the get images button means. I like to display all the images in that particular link
But I am not having any idea about this.
I have explain my requirement below
1)Enter the url in a text box
2)Click the get images button
3)Parse all the images from that particular url
4)Display all the images in the Imageview
And also to illustrate my requirement I have attached the screenshot below
If anybody work around this functionality means please suggest me some idea
Thanks
Like this ?
- (IBAction)buttonClicked:(id)sender
{
NSURL *url = [NSURL URLWithString:#"http://www.yourwebvsite.com/image.png"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData: data];
UIImageView *displayImageView = [[UIImageView alloc] initWithImage:image];
[displayImageView setFrame:CGRectMake(0, 0, 300, 300)];
[displayImageView setContentMode:UIViewContentModeScaleAspectFit];
[self.view addSubview:displayImageView];
}
Or if you want all the images from a web directory. See here and save all the images in an array then display the images in a UIImageView like my code above.

UIImageView stops displaying images after a specific amount of loop iterations

My iOS app utilizes a loop to cycle through images in a folder.
My application is supposed to loop through a total of 2031 images (sized 1200x900) inside a folder. The images were taken at 8fps and each image will be displayed as the loop continues to simulate a video clip. After the 696th picture, the images will cease to be displayed in the UIImageView although the app will continue looping.
I tested to see if the disconnect was because of the picture not existing
I started the loop at picture 200, but after picture 896 the UIImageView stop displaying the pictures.
The Code:
imgName = [NSString stringWithFormat:#"subject_basline_mat k (%d).png",jojo];
jojo++;
imageToCrop.image = [UIImage imageNamed:imgName]; //imageToCrop is the name of the UIImageView image and it is set to the image file here
imageToCrop.image = [self imageWithImage:imageToCrop.image convertToSize:self.imageToCrop.frame.size]; //Here the image is converted to fit the bounds of the simulator which is 320x240
The code loops due to a timer that loops it about once every 0.8 seconds.
I ran my code with instruments to see if there was a memory problem occurring,and instruments is very heavy on my computer. As such, my application ran quite slowly. However, when I arrived at the 696th picture, the pictures kept displaying themselves. It was almost as if my application running too quickly caused the picture to not be displayed... which I don't really understand.
The only memory heavy part of the image switching seems to be the size conversion step which is called by the line imageToCrop.image = [self imageWithImage:imageToCrop.image convertToSize:self.imageToCrop.frame.size];
imageToCrop.image = [self imageWithImage:imageToCrop.image convertToSize:self.imageToCrop.frame.size];
The method "imageWithImage" is here:
- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size {
#autoreleasepool {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return destImage;
}
And the line [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; uses around up the most memory out of all the image management in the app.
Any Ideas as to why my app will only display a certain amount of images?
Try loading the full-size images from the app bundle by URL. For example:
#autoreleasepool {
NSString *imgName = [NSString stringWithFormat:#"subject_basline_mat k (%d)",jojo];
NSURL *imageURL = [[NSBundle mainBundle] URLForResource:imgName withExtension:#"png"];
UIImage *image = [UIImage imageWithContentsOfFile:[imageURL path]];
imageToCrop.image = [self imageWithImage:image convertToSize:self.imageToCrop.frame.size];
}
Almost for sure your problem is [UIImage imageNamed:imgName]. There are hundreds of posts here on the pitfalls of using it. The issue is that it caches the images - its real purpose is for some small number of images in your bundle.
If you have oodles of images, get the path to the image, then get the image through a URL or file pointer. That way its not cached. Note that when you do this, you lose the automatic "get-retina-image-automatically", and so you will need to grab the appropriately sized image depending on whether the device is retina or not.

How to have an animated background iOS

I want to place an animated background on my app. I have looked into the UIMotionEffect class and yes that does seem beneficial. However, what I am really looking for is something like the dynamic wallpapers provided in iOS settings. The way those colored circles move around is exactly what I am looking for.
I've tried this with no luck:
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"circle"]];
[UIView animateWithDuration:5.0 animations:^{
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"circle"]];
}];
My only problem is I have no idea where to start. I looked into OpenGL. I assume it could be done that way, but it seems like a possible rabbit trail that I might not need to take. I also found some videos on YouTube but they involve Adobe Flash, which I do not have. Any suggestions on where to venture for this?
If it's a simple GIF you don't need to get fancy. Just separate the images (many tools to do that) and use the following code (might be some typos):
NSArray *array = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
........,
nil];
UIImage *image = [UIImage animatedImageWithImages:array duration:6.0f];
[image startAnimating];

How do I display a progressive JPEG in an UIImageView while it is being downloaded?

Downloading an image from the net and showing it in an UIImageView is fairly easy. However, this requires the image to be completely downloaded before it is shown to the user, completely defeating progressive JPEG (and PNG) images.
How can I render the partially downloaded images while the transfer is being done? I would imagine the SDK to have some callback function which would update the image, but I can't find such a function. Is it possible at all with the current iOS SDK?
I know this post has about 1 year, but just in case anyone is looking for it, there is a project called NYXImagesKit that does what you are looking for.
It has a class named NYXProgressiveImageView that is a subclass of UIImageView.
All you have to do is:
NYXProgressiveImageView * imgv = [[NYXProgressiveImageView alloc] init];
imgv.frame = CGRectMake(0, 0, 320, 480);
[imgv loadImageAtURL:[NSURL URLWithString:#"http://yourimage"]];
[self.view addSubview:imgv];
[imgv release];
Also, a good option is to save your images as interlaced so that it loads with low quality and improve with the download. If the image is not interlaced it is loaded from top to bottom.
There is now a small open-source library on top of libjpeg-turbo which allows decoding and displaying progressive JPEGs easily:
let imageView = CCBufferedImageView(frame: ...)
if let url = NSURL(string: "http://example.com/yolo.jpg") {
imageView.load(url)
}
see https://github.com/contentful-labs/Concorde
Did you try to render the UIImage partially as didReceiveData gets called … ? Something like …
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//TODO: add some error handling in case the image could not be created
UIImage *img=[UIImage imageWithData:data];
if (img) {
self.imageView.image=img;
}
}

Resources