use of escape sequence - objective-c

i want to show image height and width in a format a*b.for that i am using following code.problem is that label not show proper value where as height and ImagesizeWidth variable show correct value.
UIImage *newImage = image;
NSString *c= #"*";
int height = image.size.height;
int ImageSizeWidth = image.size.width;
//int size = image.size.height * image.size.width;
pixelInformation.text = [NSString stringWithFormat:#"%d%a%d",ImageSizeWidth,c,height];
can anyone help me. thanks in advance.

You should use the %# format specifier of Objective-C objects. They need to have description implemented.
So the last line should be,
pixelInformation.text = [NSString stringWithFormat:#"%d%#%d",ImageSizeWidth,c,height];
It's not %a. And you can directly put a * in the string though.
pixelInformation.text = [NSString stringWithFormat:#"%d*%d",ImageSizeWidth,height];

Related

Saving NSBitmapImageRep as image

I've done an exhaustive search on this and I know similar questions have been posted before about NSBitmapImageRep, but none of them seem specific to what I'm trying to do which is simply:
Read in an image from the desktop (but NOT display it)
Create an NSBitmap representation of that image
Iterate through the pixels to change some colours
Save the modified bitmap representation as a separate file
Since I've never worked with bitmaps before I thought I'd just try to create and save one first, and worry about modifying pixels later. That seemed really straightforward, but I just can't get it to work. Apart from the file saving aspect, most of the code is borrowed from another answer found on StackOverflow and shown below:
-(void)processBitmapImage:(NSString*)aFilepath
{
NSImage *theImage = [[NSImage alloc] initWithContentsOfFile:aFilepath];
if (theImage)
{
CGImageRef CGImage = [theImage CGImageForProposedRect:nil context:nil hints:nil];
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:CGImage];
NSInteger width = [imageRep pixelsWide];
NSInteger height = [imageRep pixelsHigh];
long rowBytes = [imageRep bytesPerRow];
// above matches the original size indicating NSBitmapImageRep was created successfully
printf("WIDE pix = %ld\n", width);
printf("HIGH pix = %ld\n", height);
printf("Row bytes = %ld\n", rowBytes);
// We'll worry about this part later...
/*
unsigned char* pixels = [imageRep bitmapData];
int row, col;
for (row=0; row < height; row++)
{
// etc ...
for (col=0; col < width; col++)
{
// etc...
}
}
*/
// So, let's see if we can just SAVE the (unmodified) bitmap first ...
NSData *pngData = [imageRep representationUsingType: NSPNGFileType properties: nil];
NSString *destinationStr = [self pathForDataFile];
BOOL returnVal = [pngData writeToFile:destinationStr atomically: NO];
NSLog(#"did we succeed?:%#", (returnVal ? #"YES": #"NO")); // the writeToFile call FAILS!
[imageRep release];
}
[theImage release];
}
While I like this code for its simplicity, another potential issue down the road might be that Apple docs advise us treat bitmaps returned with 'initWithCGImage' as read-only objects…
Can anyone please tell me where I'm going wrong with this code, and how I could modify it to work. While the overall concept looks okay to my non-expert eye, I suspect I'm making a dumb mistake and overlooking something quite basic. Thanks in advance :-)
That's a fairly roundabout way to create the NSBitmapImageRep. Try creating it like this:
NSBitmapImageRep* imageRep = [NSBitmapImageRep imageRepWithContentsOfFile:aFilepath];
Of course, the above does not give you ownership of the image rep object, so don't release it at the end.

NSImage -initWithContentsOfFile returns an image of size zero (0)

To load icon images, I have the below code in one of the methods:
NSLog(#"icon path: %#", iconPath);
NSImage *iconImage = [[NSImage alloc] initWithContentsOfFile:iconPath];
return iconImage;
From the log output, it is clear that image resources are being opened from the correct location. I don't see errors. Yet, tif files that I open are shown to have empty NSSize (width=0, height=0) in debugger, and displayed on the screen as if I am pointing to some runaway memory segment.
Flags are mainly set to 0. The exceptions are colorMatchPreferred and multipleResolutionMatching set to 1.
Reps points to an array (NSArrayM *) containing two (2) bitmap representations (NSBitmapImageRep entries).
Please advise what am I doing wrong!
Thank you
//to get image original size use this code
NSArray * imageReps = [NSBitmapImageRep imageRepsWithContentsOfFile:fileUrl];
NSInteger width = 0;
NSInteger height = 0;
for (NSImageRep * imageRep in imageReps)
{
if ([imageRep pixelsWide] > width)
width = [imageRep pixelsWide];
if ([imageRep pixelsHigh] > height)
height = [imageRep pixelsHigh];
}

How To Get UIView Height Only?

I have this code :
_width.text = NSStringFromCGRect(_screen.frame);
and it gives me on my iPod 5:
{{0,20}, {320,548}}
how to get only height value = 548 so that I can use it to calculate another components.
thank you.
I guess you want a CGFloat, not a NSString if you want to calculate other components.
CGFloat height = _screen.frame.size.height;
Or if you want a string after all:
_width.text = [NSString stringWithFormat:#"%f", _screen.frame.size.height];
The frame property of UIView is a CGRect struct. To learn about CGRect go take a look at the documentation.
I would encourage you to use CGGeometry check the documentation, in your case use CGRectGetHeight().
CGFloat height = CGRectGetHeight(_screen.frame);
Try to use like this...
You can get Height Like this...
CGFloat height = _screen.frame.size.height;
_width.text = [NSString stringWithFormat:#"%f",height];
You can get Width Like this...
CGFloat width = _screen.frame.size.width;
_width.text = [NSString stringWithFormat:#"%f",width];
You can get x coordinate Like this Like this...
CGFloat x = _screen.frame.origin.x;
You can get y coordinate Like this Like this...
CGFloat y = _screen.frame.origin.y;
_screen.frame is a struct with a CGSize and a CGPoint.
CGPoint origin = _screen.frame.origin;
CGSize size = _screen.frame.size;
The struct CGPoint has the members x and y
CGFloat x = origin.x; // float on 32bit and double on 64bit
CGFloat y = origin.y;
The struct CGSize has the members width and height
CGFloat width = size.width;
CGFloat height = size.height;
You can print a message with a formatted NSString or C-String with the format specifier %
NSString *output = [NSString stringWithFormat:#"My screen height is: %f", height];
If you want to show the height as 543 not as 543.0, then use the float string specifier in the NSString creation method
NSString *string = [NSString stringWithFormat:#"Integer height is: %.0f", height];
// even with values like 0.9999 the output would be "Integer height is: 0"
If the property _width.text is a NSString.
_width.text = output;

NSString font size specific to frame width

I am using drawRect for a text display, calling NSString. I am trying to implement using sizeWithFont to auto resizing font (shrinking) with default font size of 17 and using a loop to reduce the font size by 1 if it does not fit the size of width. Can anyone help me how to implement this? Example would be nice right now I just have the font size set to 17.0
[[self.string displayName] drawAtPoint:CGPointMake(xcoord, ycoord) withFont:[UIFont boldSystemFontOfSize:17.0]];
CGSize size = [[self.patient displayName] sizeWithFont:[UIFont boldSystemFontOfSize:17.0]];
max_current_y = size.height > max_current_y ? size.height : max_current_y;
xcoord = xcoord + 3.0f + size.width;
OK never mind. Here's modified version of the same method that takes NSString for which to return a font:
-(UIFont*)getFontForString:(NSString*)string
toFitInRect:(CGRect)rect
seedFont:(UIFont*)seedFont{
UIFont* returnFont = seedFont;
CGSize stringSize = [string sizeWithAttributes:#{NSFontAttributeName : seedFont}];
while(stringSize.width > rect.size.width){
returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
stringSize = [string sizeWithAttributes:#{NSFontAttributeName : returnFont}];
}
return returnFont;
}
Here's how to call it:
NSString* stringToDraw = #"Test 123";
CGRect rect = CGRectMake(100., 100., 100., 200.);
UIFont* font = [self getFontForString:stringToDraw toFitInRect:rect seedFont:[UIFont systemFontOfSize:20]];
[stringToDraw drawInRect:rect withFont:font];
Code is for iOS7+
Trying font sizes with step 1.0 may be very slow. You can tremendously improve the algorithm by making two measures for two different sizes, then using linear approximation to guess the size that will be very close to the right one.
If it turns out not close enough, repeat the calculation using the guessed size instead of one of the previous two until it is good enough or stops changing:
// any values will do, prefer those near expected min and max
CGFloat size1 = 12.0, size2 = 56.0;
CGFloat width1 = measure_for_size(size1);
CGFloat width2 = measure_for_size(size2);
while (1) {
CGFloat guessed_size = size1 + (required_width - width1) * (size2 - size1) / (width2 - width1);
width2 = measure_for_size(guessed_size);
if ( fabs(guessed_size-size2) < some_epsilon || !is_close_enough(width2, required_width) ) {
size2 = guessed_size;
continue;
}
// round down to integer and clamp guessed_size as appropriate for your design
return floor(clamp(guessed_size, 6.0, 24.0));
}
is_close_enough() implementation is completely up to you. Given that text width grows almost linearly of font size, you can simply drop it and just do 2-4 iterations which should be enough.
I wanted to try to make a version that didn't have to repeatedly check font sizes using a do...while loop. Instead, I assumed that font point sizes were a linear scale, then worked out the size difference between the required frame width and the actual frame width, then adjusted the font size accordingly. Therefore, I ended up with this function:
+ (CGFloat)fontSizeToFitString:(NSString *)string inWidth:(float)width withFont:(UIFont *)font
{
UILabel *label = [UILabel new];
label.font = font;
label.text = string;
[label sizeToFit];
float ratio = width / label.frame.size.width;
return font.pointSize * ratio;
}
Pass in a font of any size, as well as the string and the required width, and it will return you the point size for that font.
I also wanted to take it a bit further and find out the font size for a multi-line string, so that the longest line would fit without a line break:
+ (CGFloat)fontSizeToFitLongestLineOfString:(NSString *)string inWidth:(float)width withFont:(UIFont *)font
{
NSArray *stringLines = [string componentsSeparatedByString:#"\n"];
UILabel *label = [UILabel new];
label.font = font;
float maxWidth = 0;
for(NSString *line in stringLines)
{
label.text = line;
[label sizeToFit];
maxWidth = MAX(maxWidth, label.frame.size.width);
}
float ratio = width / maxWidth;
return font.pointSize * ratio;
}
Seems to work perfectly fine for me. Hope it helps someone else.
Original poster didn't specify what platform he was working on, but for OSX developers on Mavericks, sizeWithFont: doesn't exist and one should use sizeWithAttributes :
NSSize newSize = [aString sizeWithAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:#"Arial Rounded MT Bold" size:53.0],NSFontAttributeName,nil
]];
Here's a method which can return you font that will fit in a rect:
-(UIFont*)getFontToFitInRect:(CGRect)rect seedFont:(UIFont*)seedFont{
UIFont* returnFont = seedFont;
CGSize stringSize = [self sizeWithFont:returnFont];
while(stringSize.width > rect.size.width){
returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
stringSize = [self sizeWithFont:returnFont];
}
return returnFont;
}
You can add this method to a NSString category. You can find more about how to add a category here: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW2
If you don't want to create a category, you can add this method to one of your utility classes and pass in the string for which you want the font to be returned.
Here is another method, inspired by #puru020 & #jowie answers. Hope it helps someone
-(UIFont *) adjustedFontSizeForString:(NSString *)string forWidth:(float)originalWidth forFont:(UIFont *)font
{
CGSize stringSize = [string sizeWithFont:font];
if(stringSize.width <= originalWidth)
{
return font;
}
float ratio = originalWidth / stringSize.width;
float fontSize = font.pointSize * ratio;
return [font fontWithSize:fontSize];
}
I modified a bit the solution of #puru020 , added the support for attributes, and improved a bit:
Note: The method should be wrapped in a NSString Category
- (UIFont*)requiredFontToFitInSize:(CGSize)size seedFont:(UIFont*)seedFont attributes:(NSDictionary*)attributes{
UIFont *returnFont = [UIFont systemFontOfSize:seedFont.pointSize +1];
NSMutableDictionary *mutableAttributes = attributes.mutableCopy;
CGSize stringSize;
do {
returnFont = [UIFont systemFontOfSize:returnFont.pointSize -1];
[mutableAttributes setObject:returnFont forKey:NSFontAttributeName];
stringSize = [self sizeWithAttributes:mutableAttributes];
} while (stringSize.width > size.width);
return returnFont;
}

NSImage acting weird

Why is this code setting artistImage to an image with 0 width and 0 height?
NSURL *artistImageURL = [NSURL URLWithString:#"http://userserve-ak.last.fm/serve/252/8581581.jpg"];
NSImage *artistImage = [[NSImage alloc] initWithContentsOfURL:artistImageURL];
As Ken wrote, the DPI is messed up in this image. If you want to force NSImage to set the real image size (ignoring the DPI), use the method described at http://borkware.com/quickies/one?topic=NSImage:
NSBitmapImageRep *rep = [[image representations] objectAtIndex: 0];
NSSize size = NSMakeSize([rep pixelsWide], [rep pixelsHigh]);
[image setSize: size];
NSImage does load this fine for me, but that particular image has corrupt metadata. Its resolution according to the exif data is 7.1999997999228071e-06 dpi.
NSImage respects the DPI info in the file, so if you try to draw the image at its natural size, you'll get something 2520000070 pixels across.
Last I checked, NSImage's -initWithContentsOfURL: only works with file URLs. You'll need to retrieve the URL first, and then use -initWithData:
It is more or less guaranteed that .representations contains NSImageRep* (of course not always NSBitmapImageRep). To be on a safe side for future extensions one can write something like code below. And it also takes into account multiple representation (like in some .icns and .tiff files).
#implementation NSImage (Extension)
- (void) makePixelSized {
NSSize max = NSZeroSize;
for (NSObject* o in self.representations) {
if ([o isKindOfClass: NSImageRep.class]) {
NSImageRep* r = (NSImageRep*)o;
if (r.pixelsWide != NSImageRepMatchesDevice && r.pixelsHigh != NSImageRepMatchesDevice) {
max.width = MAX(max.width, r.pixelsWide);
max.height = MAX(max.height, r.pixelsHigh);
}
}
}
if (max.width > 0 && max.height > 0) {
self.size = max;
}
}
#end