Trying to get color value of pixel - macos

I'm trying to read the color value of a pixel in a tif image but I can't fihure out the correct way to do it. I'm using OSX and my approach is as follows:
NSImage *picture = [[NSImage alloc] initWithContentsOfFile:#"bais2.tif"]; //file is located in resoureces folder.
NSBitmapImageRep *imageRep = [[picture representations] objectAtIndex:0];
NSColor* color = [imageRep colorAtX:10 y:10];
NSLog(#"%f %f, %f", [color redComponent], [color blueComponent], [color greenComponent]);
The problem is that for some reason the logged values in NSLog always becomes 0.0000000....
I have also tried to use:
NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithData:[picture TIFFRepresentation]];
instead of [[picture representations] objectAtIndex:0] but the result is the same.
I get no error messages or warnings, but I think there is something wrong when i load the picture?
Please help me, what am i doing wrong? And is there a better way to read pixel color data?

Your error is here:
NSImage *picture = [[NSImage alloc] initWithContentsOfFile:#"bais2.tif"];
-------------------------------------------------------------------^^^^
You can use:
NSImage *picture= [NSImage imageNamed:#"bais2.tiff"];
Or :
NSImage *picture = [[NSImage alloc] initWithContentsOfFile:#"bais2.tiff"];

NSData *someNSData = [Image TIFFRepresentation];
NSBitmapImageRep *someNSBitmapImageRepData = [[NSBitmapImageRep alloc] initWithData:someNSData];
NSSize imageSizee = [someNSBitmapImageRepData size];
CGFloat y = imageSize.height - 100.0;
NSColor* color = [someNSBitmapImageRepData colorAtX:100.0 y:y];
NSLog(#"color = %#",color);
output : color = NSCalibratedRGBColorSpace 1 1 1 1

Related

Centering text in OS X Screensaver

I'm working on implementing a (very) simple screensaver using the Screensaver framework in OS X 10.10. Positioning on the center of the screen and displaying a two-line text works without problem, but setting the alignment to NSCenterTextAlignment somehow doesn't (the text is always displayed left-aligned).
- (void)animateOneFrame
{
// calculate font size based on screen
NSSize size = [self bounds].size;
CGFloat fontsize = size.height / 11;
// set text
NSMutableParagraphStyle *centredStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[centredStyle setAlignment:NSCenterTextAlignment];
NSDictionary *textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:#"Futura" size:fontsize], NSFontAttributeName,
[NSColor orangeColor], NSForegroundColorAttributeName,
centredStyle, NSParagraphStyleAttributeName,
nil];
NSString *theText = #"Simple text spanning\ntwo lines";
// position text on screen
NSRect boundingRect = [theText boundingRectWithSize:size options:0 attributes:textAttributes];
NSPoint point = NSMakePoint((size.width - boundingRect.size.width) / 2.0,
(size.height - boundingRect.size.height) / 2.0);
[theText drawAtPoint: point withAttributes: textAttributes];
}
Any pointers on how to solve this are appreciated.
PS: I know that I don't need to put everything into animateOneFrame but for the moment the goal is to get it working at all:-)

What is the best way to display a single-paged pdf as an image?

I would like to display in an NSView a single-paged PDF.
So far, I have two solutions but they both have downsides. Can anyone help me with any of these downsides?
First solution: with NSImage and NSImageView
NSString *path= [[NSBundle mainBundle] pathForResource:name ofType:#"pdf"];
NSImage * image = [[NSImage alloc] initWithContentsOfFile:path] ;
NSImageView * imageView = [[NSImageView alloc] init] ;
imageView.frame = NSMakeRect(0, 0, 2*image.size.width, 2*image.size.height) ;
imageView.image = image ;
imageView.imageScaling = NSImageScaleAxesIndependently ;
return imageView
Downsides:
the image is not anti-aliased
I don't understand why the factor 2 is needed. Why does my PDF is displayed smaller in an NSView than it is with the Finder?
Second solution: with PDFDocument and PDFView
NSString *path= [[NSBundle mainBundle] pathForResource:name ofType:#"pdf"];
NSURL *urlPDF = [NSURL fileURLWithPath:path] ;
PDFDocument * myPDFDocument = [[PDFDocument alloc] initWithURL:urlPDF] ;
PDFView *myPDFView = [[PDFView alloc] init] ;
myPDFView.document = myPDFDocument ;
PDFPage * firstPage = [myPDFDocument pageAtIndex:0] ;
NSRect myBounds = [firstPage boundsForBox:kPDFDisplayBoxMediaBox] ;
NSRect myNewBounds = NSMakeRect(0, 0, myBounds.size.width*2, myBounds.size.height*2+5) ;
myPDFView.frame = myNewBounds ;
myPDFView.autoScales = YES ;
return myPDFView ;
Downsides:
I am able to select the text of my pdf, I can zoom in or zoom out. But I would like my PDF document to be displayed as an image, without these possibilities
I don't understand why the factor 2 is needed. Why is my PDF displayed smaller in an NSView than it is with the Finder?
There are some margins around my image
I'm not seeing the problems you describe with NSImageView. I implemented a nib-based window and NSImageView. In my case I have an overlapping sibling view, so I turned CALayers turned on in the nib. I'm on 10.9.2. Sizing is normal (1x) and the text in my PDF is anti-aliased (sub-pixel I think, since I see colors when I blow it up). I do have scaling NONE - maybe scaling is preventing anti-aliased text?
Otherwise my guess is there's something different about your views or or PDF content. Try a simpler PDF and/or a nib-based view and if it works, you can look for differences.

How to draw both stroked and filled text in drawLayer:inContext delegate

this is my drawLayer method in a CALayer's delegate.
it's only responsible for drawing a string with length = 1.
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
CGRect boundingBox = CGContextGetClipBoundingBox(ctx);
NSAttributedString *string = [[NSAttributedString alloc] initWithString:self.letter attributes:[self attrs]];
CGContextSaveGState(ctx);
CGContextSetShadowWithColor(ctx, CGSizeZero, 3.0, CGColorCreateGenericRGB(1.0, 1.0, 0.922, 1.0));
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)string);
CGRect rect = CTLineGetImageBounds(line, ctx);
CGFloat xOffset = CGRectGetMidX(rect);
CGFloat yOffset = CGRectGetMidY(rect);
CGPoint pos = CGPointMake(CGRectGetMidX(boundingBox) - xOffset, CGRectGetMidY(boundingBox)- yOffset);
CGContextSetTextPosition(ctx, pos.x, pos.y);
CTLineDraw(line, ctx);
CGContextRestoreGState(ctx);
}
here's the attributes dictionary:
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:#"GillSans-Bold" size:72.0], NSFontAttributeName,
[NSColor blackColor], NSForegroundColorAttributeName,
[NSNumber numberWithFloat:1.0], NSStrokeWidthAttributeName,
[NSColor blackColor], NSStrokeColorAttributeName,
style, NSParagraphStyleAttributeName, nil];
as is, the stroke does not draw, but the fill does.
if i comment out the stroke attributes in the dictionary, the fill draws.
i know this can't be right, but i can't find any reference to this problem.
is this a known issue when drawing text with a delegate ?
as the string is one character, i was following the doc example not using any framesetter machinery, but tried that anyway as a fix attempt without success.
in reading this question's answer, i realized that i needed to be using a negative number for the stroke value. i was thinking of the stroke being applied to the outside of the letter drawn by CTLineDraw, rather then inside the text shape.
i'm answering my own question, in case this should help anyone else with this misunderstanding, as i didn't see the referenced doc covering this.

Draw NSBitmapImageRep in NSImageView

How can I draw a NSBitmapImageRep in a NSImageView?
NSImage *im = [[[NSImage alloc] init] autorelease];
[im addRepresentation:bitmapRep];
[imageView setImage:im];
Pretty easy:
NSImage *image = [[NSImage alloc] initWithCGImage:[bitmapRep CGImage] size:NSMakeSize(width,height)];
Then:
[imageView setImage:image];
Another possibility is by turning it into a TIFF ( - (NSData *)TIFFRepresentation ) and using that to create the NSImage object, but that could create quite some overhead.
Also keep in mind that the method of NSBitmapImageRep - (CGImageRef)CGImage is 10.5 or higher.
Edit:
For a cleaner solution look at #Ken's answer.

Printing an NSImage

I'm migrating Cocoa-Java code to Cocoa + JNI since Cocoa-Java is deprecated. The code prints an image stored in a file. The new Cocoa code is basically:
NSImage *image = [[NSImage alloc] initWithContentsOfFile:spoolFile];
if ( [image isValid] ) {
NSImageView *view = [[NSImageView alloc] init];
[view setImage:image];
[view setImageScaling:NSScaleProportionally];
NSPoint p;
NSSize s;
p.x = static_cast<float>( boundsX );
p.y = static_cast<float>( boundsY );
[view setBoundsOrigin:p];
s.width = static_cast<float>( boundsWidth );
s.height = static_cast<float>( boundsHeight );
[view setBoundsSize:s];
NSPrintInfo *info = [NSPrintInfo sharedPrintInfo];
[info setHorizontalPagination:NSClipPagination];
[info setVerticalPagination:NSClipPagination];
[info setHorizontallyCentered:NO];
[info setVerticallyCentered:NO];
p.x = static_cast<float>( boundsX );
p.y = static_cast<float>( [info paperSize].height - boundsHeight - boundsY );
[view translateOriginToPoint:p];
NSPrintOperation *printOp =
[NSPrintOperation printOperationWithView:view printInfo:info];
[printOp setShowsPrintPanel:NO];
[printOp runOperation];
}
Running this code eventually crashes with:
Thread 0 Crashed:
0 com.apple.AppKit 0x9484ac75 -[NSConcretePrintOperation(NSInternal) _tryToSetCurrentPageNumber:] + 345
1 com.apple.AppKit 0x948d88cf -[NSView(NSPrintingInternal) _printForCurrentOperation] + 524
2 com.apple.AppKit 0x948d85c5 -[NSConcretePrintOperation _renderView] + 358
3 com.apple.AppKit 0x9491f0c0 -[NSConcretePrintOperation runOperation] + 362
Why? How can I simply print an image that's stored in a file?
NSImageView *view = [[NSImageView alloc] init];
That's invalid. You need to use initWithFrame: to initialize a view. You'll probably want to pass a frame consisting of NSZeroPoint and the image's size.
As for the use of setBoundsOrigin: and setBoundsSize:: I'm not sure those will work, assuming you mean to crop the image. You can try them (after fixing the above problem), but I would feel safer to create a new image from the desired section of the old one. You would do this by creating an empty image of the desired size, locking focus on it, drawing the correct section of the old image at the origin in the new image, and unlocking focus on the new image, then giving the new image instead of the old to the image view.
Is that a typo the second time you assign to p.y? It doesn't look like you define info until 2 lines later...
Also, wouldn't it be simpler to use NSMakePoint() and NSMakeSize() by passing ints, instead of constructing them by hand and using static_cast<float>? That seems like a very C++ approach...
For example, something like this could work?
NSImage *image = [[NSImage alloc] initWithContentsOfFile:spoolFile];
if ([image isValid]) {
NSPrintInfo *info = [NSPrintInfo sharedPrintInfo];
[info setHorizontalPagination:NSClipPagination];
[info setVerticalPagination:NSClipPagination];
[info setHorizontallyCentered:NO];
[info setVerticallyCentered:NO];
NSImageView *view = [[NSImageView alloc] init];
[view setImage:image];
[view setImageScaling:NSScaleProportionally];
[view setBoundsOrigin:NSMakePoint(boundsX, boundsY)];
[view setBoundsSize:NSMakeSize(boundsWidth, boundsHeight)];
[view translateOriginToPoint:NSMakePoint(boundsX, [info paperSize].height -
boundsHeight - boundsY)];
NSPrintOperation *printOp = [NSPrintOperation printOperationWithView:view printInfo:info];
[printOp setShowsPrintPanel:NO];
[printOp runOperation];
}

Resources