I am working on drawing custom buttons/textfields with NSDrawNinePartImage. I slice up an image into nine parts in code and draw it into a rect with NSDrawNinePartImage.
Unfortunately I am getting some gaps in the drawing pattern. I thought it had something to do with my slicing code, but I saved them out as images from where I slice them, and they all look good (I even put them together and they looked good). Some of the cases where I use it to work just fine though despite some using the same images.
I am pretty confident that it comes down to the actual drawing.
Do you know of any NSGraphicsContext or other settings that would affect it or something else that may be causing this?
With gaps
Without gaps
I fixed a similar issue by disable the anti-alias option
NSGraphicsContext* theContext = [NSGraphicsContext currentContext];
[theContext saveGraphicsState];
[theContext setShouldAntialias: NO];
NSDrawNinePartImage(...);
[theContext restoreGraphicsState];
Is it possible that your upper left and lower right images are a pixel too wide?
This function uses the top-left and bottom-right corner images to
determine the widths and heights of the edge areas that need to be
filled. If the width or height of the bottom-left and top-right images
are not sized appropriately, they may be scaled to fill their corner
area. Edge areas between the corners are tiled using the corresponding
image. Similarly, the center area is tiled using the specified center
image.
Use even sizes in images. I did this, and it solved this problem for me.
Related
I'm adding borders to various images in a .pdf document. The borders all have the same width, but in the .pdf the borders have different widths. It is more pronounced as the width of the border increases.
Also, is there a way to move the border outside of the image, so that it is not covering any of the image using the methods of the image class? I realize I can first put a filled rectangle and then add the image on top of the rectangle as an option. Just curious as to if this can be done with methods from the Image class.
Here is the code snippet
magazine.open();
canvas = pdfw.getDirectContent();
image = Image.getInstance("a.JPG");
image.setBorder(Rectangle.BOX);
image.scaleAbsolute(200,200);
image.setBorderWidth(50);
image.setAbsolutePosition(50,10);
//canvas.addImage(image);
magazine.add(image);
image = Image.getInstance("b.jpg");
image.setBorder(Rectangle.BOX);
image.scaleAbsolute(200,200);
image.setBorderWidth(50);
image.setAbsolutePosition(50,230);
//canvas.addImage(image);
magazine.add(image);
I fear you'll have to work with the workaround you described.
There are two ways to define a border for an image:
image.setUseVariableBorders(false);
This is the default. This is what you have (even though you aren't calling the method explicitly).
In this case, the thickness of the border is distributed in a way that half of the line width is inside the rectangle and half of the line width is outside of the rectangle. Maybe that's what's causing the effect that the difference you notice is more pronounced as the border width increases.
Then there is:
image.setUseVariableBorders(true);
Now the borders will be drawn inside the area needed for the image. This is useful for tables (both PdfPCell and Image are subclasses of the Rectangle class where these methods are defined), but I fear it doesn't help you in the case of images.
So your best chance is to add the border using a workaround.
I'm trying to create a graphic in Sketch (a vector-based graphic design application). I export to PDF and this is what my original graphic looks like:
But when I set it as the image of an NSButton, it gets drawn like this:
Why does this occur? The right and bottom edges in particular are altered a lot. I'm not sure if this is a Cocoa drawing issue or an issue with my original graphic.
The problem is with (mis)alignment with the pixel grid and anti-aliasing. It looks like you've scaled the image so that the borders on the left, right, and bottom are roughly one pixel in thickness. However, the right and bottom borders are straddling the boundary between pixels. The result is that they contribute half their "darkness" to the pixel on one side of the boundary and the other half to the pixel on the other side of the boundary.
You should tweak either the proportions of the image or the size at which you're drawing it to avoid that particular alignment. It looks as though it's being rendered as roughly 10.5 pixels wide. You want it to be either 10 pixels or 11 pixels wide, so the right edge corresponds more closely to a pixel column.
I'm trying to draw an image with a certain color. To get this effect, first I draw the image (consisting of mostly white and black), and then I draw a rectangle over it in a specified color (let's say red). There are various compositing options available, but none are exactly what I want.
I want the colors (and alpha values) to be multiplied together. I think this is sometimes called a "Modulate" operation in other graphics systems. So, the white values in the image will be multiplied by the red values in the overlay rectangle to produce red. The black values in the image will be multiplied with black to product black.
In other words, R = S * D (result equals source multiplied by destination).
This is the code I'm working with now:
[image drawInRect:[self bounds] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
NSColor * blend = [NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:1.0];
[blend setFill];
NSRectFillUsingOperation(self.bounds, NSCompositePlusDarker);
NSCompositePlusDarker is NOT what I want, but it's close. (It's addition instead of multiplication).
Is there a way to do this in Quartz? It's very easy to do in OpenGL for instance. I've looked at CIFilter's but they seem a bit cumbersome for this. But if that's the only way, I would appreciate any sample code to get me in the right direction.
Yes.
Note that AppKit compositing operations and Quartz blend modes, though there are quite a few in common, are not interchangeable. kCGBlendModeMultiply has the same numeric value as NSCompositeCopy, so the latter—flat overwriting—is what will happen if you try to pass it to any of AppKit's drawing APIs.
So, you'll need to use Quartz for every part of the fill. You can use NSGraphicsContext to get the CGContext you'll need, and you can ask your NSColor for its CGColor.
I'm trying to draw some of my UI elements in Cocoa, mainly icons for buttons, but I'm having great difficulty getting the kind of precision I'd like.
I'm using super simple code like this to draw rectangles:
[[NSColor redColor] set];
[NSBezierPath strokeRect:myRect];
But what I'm seeing is the red rectangle line is always faded.
What am I missing here?
The Cocoa coordinates actually specify the center of the pixel you want to draw. This means, for example, if you want to draw on the bottom left pixel, you should use the coordinates (0.5,0.5).
Add/Subtract half a pixel to your coordinates and they should be pixel-perfect.
You can disable antialiasing for your graphics context like this:
[[NSGraphicsContext currentContext] setShouldAntialias:NO];
Or you could use NSFrameRect instead of a bezier path, and that would get the precision you want, while keeping antialiasing on:
NSFrameRect(myRect);
I am using pygtk and cairo (...wonderful stuff I must say. Thanks to all)
I am wondering how to present parts of images on my my cairo surface on a large drawingarea.
I would like to have areas within the displayed surface that appear to act clipped so I can scroll images through these areas without disturbing the surrounding drawn items.
Can I cut images for part drawing onto a surface or must I just get the drawing sequence in the proper order so that the images needing to be clipped are overlain and so part hidden as required and appear clipped?
thanks for any pointers
nick
Cairo is indeed wonderful! ctx.clip() is one way to do it, using a clipping path (shown below in just pycairo, where the final draw rectangle only hits the triangular clipped area).
You could also use a transfer mode of CAIRO_OPERATOR_OUT (I think), but I'm less familiar with the transfer modes. And that would only work on the first draw, since your content would fill the alpha a bit.
(Your suggestion of "Painting Order" will work fine, too, of course!)
import cairo
WIDTH, HEIGHT = 256, 256
surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
ctx = cairo.Context (surface)
ctx.rectangle(0,0,300,300)
ctx.set_source_rgb(0,0,0)
ctx.fill()
ctx.move_to(0,0)
ctx.line_to(200,90)
ctx.line_to(90,200)
ctx.line_to(0,0)
ctx.close_path()
ctx.clip()
ctx.rectangle(0,0,300,300)
ctx.set_source_rgb(1,1,0)
ctx.fill()
surface.write_to_png("clipped.png")