Creating a template image dynamically for OSX menu bar - macos

I'm having trouble creating a template image for the OSX menu bar. As far as I can tell, it has to be a PDF image. To that end, I have:
var pageRect: CGRect = CGRectMake(0, 0, CGFloat(10), CGFloat(barHeight))
let pdfData: NSMutableData = CFDataCreateMutable(nil, 0)
let pdfConsumer = CGDataConsumerCreateWithCFData(pdfData as CFMutableDataRef)
let pdfContext = CGPDFContextCreate(pdfConsumer, &pageRect, nil)
Then I draw into the PDF:
CGPDFContextBeginPage(pdfContext, nil)
CGContextSetRGBFillColor (pdfContext, 1, 0, 0, 1)
CGContextFillRect (pdfContext, CGRectMake (0, 0, 200, 100 ))
CGPDFContextEndPage(pdfContext)
Then I try to create an NSImage:
let image = NSImage(data: pdfData)
And add it to the status item's image property:
button.image = image
However, this just isn't working. I have tried saving the image to disk and opening it, but get the message that the image is corrupted, so I suspect the error is in converting the pdfData into an NSImage, though I'm not totally confident of that. Anyway, any help would be appreciated.

A template image does not have to be a PDF. To make an instance of NSImage a template image, simply set its template property to true.
No matter the nature of the image (bitmap, PDF, whatever), the system will only make use of its alpha channel when it's a template image. The color channels are ignored.
The system will automatically mark an image loaded from a file as a template image if its filename-minus-extension ends with "Template". So, for example, fooTemplate.png or barTemplate.pdf.

Related

How to use gif with UIImageView in Xamarin.iOS without using third party library?

I want to load gif image in UIImageView. I've try to use it wih FLAnimatedImage but it not worked. I have taken imageview in storyboard and added gif to resources.
If you want to load gif image with UIImageView, I find one article that you can take a look:
https://montemagno.com/animated-gif-uiimageview-in-xamarinios/
If you try to create the gif using individual images, it will be easier, as you can see here. When you convert the native code from here to C#, you get this
UIImageView gifView = new UIImageView();
gifView.AnimationImages = new UIImage[] {
UIImage.FromBundle("Image1.png"),
UIImage.FromBundle("Image2.png"),
UIImage.FromBundle("Image3.png"),
UIImage.FromBundle("Image4.png")
};
gifView.AnimationRepeatCount = 0; // Repeat forever.
gifView.AnimationDuration = 1.0; // Every 1s.
gifView.StartAnimating();
gifView.View.Frame = new CoreGraphics.CGRect(0, 20, this.View.Bounds.Size.Width, 180); // size of the animation
this.View.AddSubview(gifView);

Display an Image in an Imageview in OS X Swift

I have a image view box and I want to display an image in it. I know how to do it without writing a line of code but I want to put an image in an image view with code. I've seen many examples online on how to do it in iOS, but I need to know how to do it in OS X. Any help would be appreciated.
Create NSImageView object
NSImageView has property 'image'.you can just assign to it.
Ex:
let imgView = NSImageView(frame:NSRect(x: 0, y: 0, width: 300, height: 300))
imgView.image = NSImage(named:"test")
self.view.addSubview(imgView)

Custom Core Image Filter produces image of undefined size - FIXED

I am developing an OS X app that uses custom Core Image filters to attain a particular effect: Set one image's luminance as another image's alpha channel. There are filters to use an image as a mask for another but they require a third -background- image; I need to output an image with transparent parts, no background set.
As explained in Apple's documentation, I wrote the kernel code and tested it in QuartzComposer; it works as expected.
The kernel code is:
kernel vec4 setMask(sampler src, sampler mask)
{
vec4 color = sample(src, samplerCoord(src));
vec4 alpha = sample(mask, samplerCoord(mask));
color.a = alpha.r;
// (mask image is grayscale; any channel colour will do)
return color;
}
But when I try to use the filter from my code (either packaging it as an image unit or directly from the app source), the output image turns out to have the following 'undefined'(?) extent:
extent CGRect origin=(x=-8.988465674311579E+307, y=-8.988465674311579E+307) size=(width=1.797693134862316E+308, height=1.797693134862316E+308)
and further processing (convert to NSImage bitmap representation, write to file, etc.) fails. The filter itself loads perfectly (not nil) and the output image it produces isn't nil either, just has an invalid rect.
EDIT: Also, I copied the exported image unit (plugin), to both /Library/Graphics/Image Units and ~/Library/Graphics/Image Units, so that it appears in QuartzComposer's Patch Library, but when I connect it to the source images and Billboard renderer, nothing is drawn (transparent background).
Am I missing something?
EDIT: Looks like I assumed to much about the default behaviour of -[CIFilter apply:].
My filter subclass code's -outputImage implementation was this:
- (CIImage*) outputImage
{
CISampler* src = [CISampler samplerWithImage:inputImage];
CISampler* mask = [CISampler samplerWithImage:inputMaskImage];
return [self apply:setMaskKernel, src, mask, nil];
}
So I tried and changed it to this:
- (CIImage*) outputImage
{
CISampler* src = [CISampler samplerWithImage:inputImage];
CISampler* mask = [CISampler samplerWithImage:inputMaskImage];
CGRect extent = [inputImage extent];
NSDictionary* options = #{ kCIApplyOptionExtent: #[#(extent.origin.x),
#(extent.origin.y),
#(extent.size.width),
#(extent.size.height)],
kCIApplyOptionDefinition: #[#(extent.origin.x),
#(extent.origin.y),
#(extent.size.width),
#(extent.size.height)]
};
return [self apply:setMaskKernel arguments:#[src, mask] options:options];
}
...and now it works!
How are you drawing it? And what does your CIFilter code look like? You'll need to provide a kCIApplyOptionDefinition most likely when you call apply: in outputImage.
Alternatively, you can also change how you are drawing the image, using CIContext's drawImage:inRect:fromRect.

NSImage lockFocus unlockFocus image bomes blurry

I load an image (NSImage) from the disk, and draw it to an NSImageView on MAC, No problem image looks fine and clear.
After drawing it to the NSImageView, I call the function below with the same image, then draw the returned value to the same NSImageView. The resulting image is extremly blurry, even if all I do is lockFocus and UnlockFocus without doing anything else.
-(NSImage*)addTarget:(NSImage*)image
{
[image lockFocus]; // this image is sharp and clear
[image unlockFocus];
return image; // this image is extremely blurry
}
Anybody knows why or how to fix that?
thanks
rough
So as doing some research I realized that this is related to Retina displays. I guess locking focus will always draw at bestRepresentation which if there is a retina display attached anywhere to the computer, it will render based on that scale factor. So in order to get this to maintain proper dimensions and DPI I created a method that iterates through all screens and returns the largest backingScaleFactor
func maximumScaleFactor(screen: NSScreen) -> CGFloat {
var max: CGFloat = 0
for s in NSScreen.screens()! {
if s.backingScaleFactor > max { max = s.backingScaleFactor }
}
return max / screen.backingScaleFactor
}
Then for the 'NSImage' I did the following
-(NSImage*)addTarget:(NSImage*)image
let scale = self.maximumScaleFactor(currentScreen)
let originalSize = image.size
//cut the image size in half
var size = image.size
size.x /= scale
size.y /= scale
image.lockFocus()
//do whatever drawing you need here
image.unlockFocus()
//set the image back to its original size
image.size = originalSize
return image
}
So far this has worked well for me and the image quality subjectively appears the same to me.
To fix your problem is difficult because you don't say what you want to achieve. Why did you write that method, why do you call it, what do you expect this method does? You said: all I do is lockFocus and UnlockFocus without doing anything else. Indeed it looks like calling lockFocus unlockFocus (and nothing between) does nothing. But that is wrong. [image lockFocus] alone changes image dramatically. An NSImage object contains zero, one (in most cases) or more (icon or some TIFFs) object of class NSImageRep. A call of lockFocus on this image selects an NSImageRep, that is best suited for depicting on the screen. Then it computes how many pixels (but now for a screen) it needs to render the image with the given size but with a resolution of only 72 dpi (or 144 dpi for retina screens). And then removes the NSImageRep from the list of representations and creates instead a new NSImageRep. In former OS-versions (before 10.6) an NSCachedImageRep was created. But now an NSCGImageSnapshotRep is created which under the hood is a CGImage. Make a
NSLog(#" image is:\n%#", image );
before lockFocus and one after the call of unlockFocus and the you will see what happens: for a high resolution image the number of pixels will go down, which is a nothing else than a reduction in quality. And that makes your image blurry.

HTML5 canvas - Rescale images on load?

Ok, so I'm doing an html5 canvas game, and I need to draw resized images all the time (it's all pixel-art). Unfortunately, doing the resizing on drawImage makes current browsers quite sluggish, so I'm trying to do the resizing on load, and then just draw the pre-resized image.
I've tried to draw the resized images to a hidden context and then do a ctx.getImageData, but then I'm stuck with a byte array and there's no way to convert to an image. I can do a putImageData to push it to the final context, but that's slow and I apparently lose the alpha channel.
Another option could be to pre-scale things in the server, but I'd like to avoid that if at all possible.
Any ideas?
There is a method on the canvas object (not the context) called toDataURL(string mimeType), this will convert the canvas contents to a base64-encoded binary string of an image. You can use this as the src attribute of any image element.
ctx.drawImage(originalImage, 0, 0, originalImage.width, originalImage.height, 0, 0, 200, 200);
var scaledImage = new Image();
scaledImage.onload = ...;
scaledImage.src = canvas.toDataURL("image/png");
Now you can draw your scaled image normaly.

Resources