I am saving a PDF from an NSTextview and putting a logo in the header. I overrode pageHeader and the logo appears but it is clipped.
Is it possible to change the header height of an NSTextView?
Thanks!
Partial code:
-(IBAction)impLaudo:(id)sender
{
NSPrintInfo *printInfo;
NSPrintInfo *sharedInfo;
NSPrintOperation *printOp;
NSMutableDictionary *printInfoDict;
NSMutableDictionary *sharedDict;
sharedInfo = [NSPrintInfo sharedPrintInfo];
sharedDict = [sharedInfo dictionary];
printInfoDict = [NSMutableDictionary dictionaryWithDictionary:sharedDict];
[printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];
[printInfoDict setObject:[[dirLaudos stringByAppendingString:[estudo stringValue]] stringByAppendingString:#".pdf"] forKey:NSPrintSavePath];
printInfo = [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
[printInfo setHorizontalPagination: NSClipPagination];
[printInfo setVerticalPagination: NSAutoPagination];
[printInfo setVerticallyCentered:NO];
[[printInfo dictionary] setValue:[NSNumber numberWithBool:YES] forKey:NSPrintHeaderAndFooter];
printOp = [NSPrintOperation printOperationWithView:textView printInfo:printInfo];
[printOp setShowsPrintPanel:NO];
[printOp runOperation];
}
#implementation MyTextView
- (NSAttributedString *)pageHeader
{
// Adicionando cabeƧalho
NSAttributedString *theHeader = nil;
NSImage * pic = [[NSImage alloc] initWithContentsOfFile:[dirLayout stringByAppendingString:#"cabecalho.jpg"]];
NSTextAttachmentCell *attachmentCell = [[NSTextAttachmentCell alloc] initImageCell:pic];
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
[attachment setAttachmentCell: attachmentCell ];
theHeader = [NSAttributedString attributedStringWithAttachment: attachment];
return theHeader;
}
#end
Instead of overriding -pageHeader, you should override -drawPageBorderWithSize:, which allows you to draw additional marks on the page at print time.
The Size parameter is an NSSize struct containing the size of the current logical page. All you need to do is draw your logo in the correct location:
- (void)drawPageBorderWithSize:(NSSize)pageSize
{
[super drawPageBorderWithSize:pageSize];
//draw your logo
NSPoint offset = NSMakePoint(100.0, 100.0);
NSImage* logo = [NSImage imageNamed:#"logo"];
NSSize logoSize = [logo size];
NSPoint imageOrigin = NSMakePoint(offset.x, pageSize.height - (offset.y + logoSize.height));
[self lockFocus];
[logo drawInRect:NSMakeRect(imageOrigin.x, imageOrigin.y, logoSize.width, logoSize.height)
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0
respectFlipped:YES
hints:nil];
[self unlockFocus];
}
Related
I am working on an desktop app that generates an image from en NSViewController that is not shown.
The view generated has 3 NSImageViews which change the content once created.
I manage to export the NSViewController's view to JPG file, but it never renders in the image given to the NSImageView, it keeps the image which is set in the nib. Also, if I don't set the background color to the view's layer... I get an empty result.
What am I missing here? I guess I need to update the NSViewController's view... but how can I do that? I do not want to show my NSViewController.
My code:
- (IBAction)doExport:(id)sender {
ExportView *view = [[ExportView alloc] initWithNibName:#"ExportView" bundle:nil];
[view.pic1 setImage:self.pic1.image];
[view.pic2 setImage:self.pic2.image];
[view.pic3 setImage:self.pic3.image];
[view.icon setImage:self.icon.image];
// Hardcoding for test
[view.pic1 setImage:[NSImage imageNamed:#"iPhone 4-Inch Screenshot 1"]];
[view.pic1 setNeedsLayout:YES];
[view.pic1 setNeedsDisplay];
[view.pic1 updateLayer];
// Setup the image to render
NSRect imgRect = view.view.frame;
NSSize imgSize = imgRect.size;
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:0
bitsPerPixel:0];
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:g];
// Set view background color
CALayer *viewLayer = [CALayer layer];
[viewLayer setBackgroundColor:[NSColor clearColor].CGColor];
[view.view setWantsLayer:YES];
[view.view setLayer:viewLayer];
// Render
CGContextRef zCgContextRef = (CGContextRef) [g graphicsPort];
[[view.view layer] renderInContext:zCgContextRef];
// Render pic as well, for test
[view.pic1.layer renderInContext:zCgContextRef];
// Get the Data for the image
NSData *exportedData = [rep representationUsingType:NSJPEGFileType properties:nil];
// Start the savepanel
NSSavePanel *savepanel = [NSSavePanel savePanel];
savepanel.title = #"Save chart";
[savepanel setAllowedFileTypes:[NSArray arrayWithObject:#"jpg"]];
[savepanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result)
{
if (NSFileHandlingPanelOKButton == result)
{
NSURL* fileURL = [savepanel URL];
if ([fileURL.pathExtension isEqualToString:#""])
fileURL = [fileURL URLByAppendingPathExtension:#"jpg"];
[exportedData writeToURL:fileURL atomically:YES];
}
}];
}
I solved it in a very ugly way. Basically what I do is I add the view to my contentView and set setHidden to YES straight away. This will intialize the view. Now I change the content of my Nib view.
When its time to render the data to NSData I change setHidden to NO, generate the NSData and then remove the view.
The end result (no beautiful code :( ):
- (IBAction)doExport:(id)sender {
ExportView *view = [[ExportView alloc] initWithNibName:#"ExportView" bundle:nil];
[view.view setHidden:YES];
[self.window.contentView addSubview:view.view];
[view.pic1 setImage:self.pic1.image];
[view.pic2 setImage:self.pic2.image];
[view.pic3 setImage:self.pic3.image];
[view.icon setImage:self.icon.image];
// Setup the image to render
NSRect imgRect = view.view.frame;
NSSize imgSize = imgRect.size;
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:imgSize.width
pixelsHigh:imgSize.height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:0
bitsPerPixel:0];
NSGraphicsContext *g = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:g];
// Set view background color
CALayer *viewLayer = [CALayer layer];
[viewLayer setBackgroundColor:[NSColor clearColor].CGColor];
[view.view setWantsLayer:YES];
[view.view setLayer:viewLayer];
[view.view setHidden:NO];
// Render
CGContextRef zCgContextRef = (CGContextRef) [g graphicsPort];
[[view.view layer] renderInContext:zCgContextRef];
[view.view removeFromSuperview];
// Get the Data for the image
NSData *exportedData = [rep representationUsingType:NSJPEGFileType properties:nil];
// Start the savepanel
NSSavePanel *savepanel = [NSSavePanel savePanel];
savepanel.title = #"Save chart";
[savepanel setAllowedFileTypes:[NSArray arrayWithObject:#"jpg"]];
[savepanel setNameFieldStringValue:#"Test"];
[savepanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result)
{
if (NSFileHandlingPanelOKButton == result)
{
NSURL* fileURL = [savepanel URL];
if ([fileURL.pathExtension isEqualToString:#""])
fileURL = [fileURL URLByAppendingPathExtension:#"jpg"];
[exportedData writeToURL:fileURL atomically:YES];
}
}];
}
I want to make a custom NSButton with a solid color for its background but there is this blue highlight around the button that I can't figure out how to get rid of. Does anyone know how to get rid of it?
Thanks!
EDIT:
Here's the code for the button:
#implementation ZDButton
- (id)init {
if (self = [super init]) {
self.title = #"";
self.isSelected = false;
[self setBordered:NO];
[self setBackgroundColor:[NSColor whiteColor]];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
[[NSColor colorWithCalibratedRed:arc4random_uniform(100) / 100.0
green:arc4random_uniform(100) / 100.0
blue:arc4random_uniform(100) / 100.0
alpha:1.0] set];
NSRectFill(dirtyRect);
NSDictionary *att = nil;
NSMutableParagraphStyle *style =
[[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
[style setAlignment:NSLeftTextAlignment];
att = [[NSDictionary alloc] initWithObjectsAndKeys:
style, NSParagraphStyleAttributeName,
[NSColor whiteColor],
NSForegroundColorAttributeName, nil];
int width = [self.title sizeWithAttributes:att].width;
int height = [self.title sizeWithAttributes:att].height;
int x = (dirtyRect.size.width - width) / 2;
int y = (dirtyRect.size.height - height) / 2;
NSRect centeredText = NSRectFromCGRect(CGRectMake(x, y, width, height));
[self.title drawInRect:centeredText withAttributes:att];
}
#end
I have a view with a slider and a background image. The background image is updated according to the slider, where the slider controls the level of the filter.
I am using this framework https://github.com/BradLarson/GPUImage to process the image with the filter.
From the code below, the image is updating with the slider, and the filter is working great. However I am trying to save the image once processed by the filter(to set a UIImage in another class), but I cannot achieve this(the filtered image is not saved, but the ufiltered image is saved)... am I saving the image wrong, incorrect format?
Please help me I have been at this for hours!
- (void)loadView
{
CGRect mainScreenFrame = [[UIScreen mainScreen] applicationFrame];
GPUImageView *primaryView = [[GPUImageView alloc] initWithFrame:mainScreenFrame];
self.view = primaryView;
*imageSlider = [[UISlider alloc] initWithFrame:CGRectMake(25.0, mainScreenFrame.size.height - 50.0, mainScreenFrame.size.width - 50.0, 40.0)];
[imageSlider addTarget:self action:#selector(updateSliderValue:) forControlEvents:UIControlEventValueChanged];
imageSlider.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
imageSlider.minimumValue = 0.0;
imageSlider.maximumValue = 1.0;
imageSlider.value = 0.5;
[primaryView addSubview:imageSlider];
[self setupDisplayFiltering];
- (IBAction)updateSliderValue:(id)sender
{
CGFloat midpoint = [(UISlider *)sender value];
[(GPUImageBrightnessFilter *)sepiaFilter setBrightness:midpoint];
//[(GPUImageSepiaFilter *)sepiaFilter setIntensity:[(UISlider *)sender value]];
//[(GPUImageSaturationFilter *)sepiaFilter setSaturation:midpoint];
//[(GPUImageRGBFilter *)sepiaFilter setGreen:midpoint];
[sourcePicture processImage];
}
- (void)setupDisplayFiltering;
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *imageToUseData = [defaults dataForKey:#"imageToUse"];
UIImage *inputImage = [UIImage imageWithData:imageToUseData];
sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage smoothlyScaleOutput:YES];
//sepiaFilter = [[GPUImageSepiaFilter alloc] init];
sepiaFilter = [[GPUImageBrightnessFilter alloc] init];
GPUImageView *imageView = (GPUImageView *)self.view;
[sepiaFilter forceProcessingAtSize:imageView.sizeInPixels]; // This is now needed to make the filter run at the smaller output size
[sourcePicture addTarget:sepiaFilter];
[sepiaFilter addTarget:imageView];
[sourcePicture processImage];
UIImage *outputImage = [sepiaFilter imageFromCurrentlyProcessedOutput];
UIImage *quickFilteredImage = [brightnessFilter imageByFilteringImage:inputImage];
// set the image chosen for other classes to set uiimages with
NSData *imageToStore = UIImageJPEGRepresentation(outputImage, 100);
[defaults removeObjectForKey:#"imageToUse"];
[defaults setObject:imageToStore forKey:#"imageToUse"];
}
I have UIScrollView that contains images from the server.
I should put Activity Indicator while the image is currently loading.
UIScrollView contains dynamic number of images from the server.
May I know how can I add activity indicators on each page while the image is loading and remove once image is loaded.
Here's my code to retrieve images:
NSDictionary *items = [NSDictionary dictionaryWithObject:dictInfo forKey:#"images"];
imageList = [items objectForKey:#"images"];
NSArray *img = [imageList objectForKey:#"list"];
NSInteger imgCount = [img count];
buttonArray = [[NSMutableArray alloc] init];
for (int i=0; i<imgCount; i++) {
NSDictionary *imgDict = [img objectAtIndex:i];
// REQUEST FOR IMAGES
NSString *imgPath = [imgDict objectForKey:#"image_slot"];
NSString *imgURL = imgPath;
__block ASIHTTPRequest *requestImage = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:imgURL]];
[requestImage setCompletionBlock:^{
imgView = [UIImage imageWithData:[requestImage responseData]];
if (imgURL.length) {
[pendingRequests removeObjectForKey:imgURL];
}
scrollView.userInteractionEnabled = YES;
scrollView.exclusiveTouch = YES;
scrollView.canCancelContentTouches = YES;
scrollView.delaysContentTouches = YES;
scrollView.bounces = NO;
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
SWTUIButton *imgBtn = [[SWTUIButton alloc] initWithFrame:frame];
imgBtn.url = [requestImage.userInfo objectForKey:#"rURL"];
[imgBtn setImage:imgView forState:UIControlStateNormal];
imgBtn.backgroundColor = [UIColor clearColor];
[imgBtn addTarget:self action:#selector(buttonpushed:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:imgBtn];
[buttonArray addObject:imgBtn];
[imgBtn release];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * img.count, self.scrollView.frame.size.height);
}];
I highly suggest you use NINetworkImageView from https://github.com/jverkoey/nimbus project.
It's very light and useful.
It has a delegate method to let you know when an image is loaded.
What you basically need to do is:
1. create an NINetworkImageView for each page, just like you do with UIImageView, and call set
NINetworkImageView* networkImageView = [[[NINetworkImageView alloc] initWithImage:initialImage]
autorelease];
networkImageView.delegate = self;
networkImageView.contentMode = UIViewContentModeCenter;
[networkImageView setPathToNetworkImage:
#"http://farm3.static.flickr.com/2484/3929945380_deef6f4962_z.jpg"
forDisplaySize: CGSizeMake(kImageDimensions, kImageDimensions)];
https://github.com/jverkoey/nimbus/tree/master/examples/photos/NetworkPhotoAlbums
the add the indicator to the networkImageView as a subview.
implement the delegate as follows:
-(void)networkImageView:(NINetworkImageView *)imageView didLoadImage:(UIImage *)image {
[imageView removeAllSubviews];
}
the end result would be a much smaller code for doing the same thing.
Okay... I want to save the visible rectangle of the IKImageView image only.
My problem is that, somehow, if I had an image in portrait mode it will be not saved in the right orientation. I drawing the image with this code:
[sourceImg drawInRect:targetRect fromRect:sourceRect operation:NSCompositeSourceOver fraction:1.0f];
On the other side if I draw the image with this code:
[sourceImg drawAtPoint:NSZeroPoint fromRect:sourceRect operation:NSCompositeSourceOver fraction:1.0f];
It will be in the right orientation, but edits like zooming are lost. I mean it will save the right cut out, but unfortunately not in the right size.
Here is the code how I load the image:
- (IBAction)imageSelectionButtonAction:(id)sender {
NSLog(#"%s", __FUNCTION__);
NSOpenPanel *panel = [NSOpenPanel openPanel];
id model = [self getModel];
if (imageView) {
[panel setAllowedFileTypes:[NSImage imageFileTypes]];
[panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] completionHandler:^(NSInteger returnCode) {
if (returnCode == 1) {
NSURL *imageUrl = [panel URL];
CGImageRef image = NULL;
CGImageSourceRef isr = CGImageSourceCreateWithURL( (__bridge CFURLRef)imageUrl, NULL);
if (isr) {
NSDictionary *options = [NSDictionary dictionaryWithObject: (id)kCFBooleanTrue forKey: (id) kCGImageSourceShouldCache];
image = CGImageSourceCreateImageAtIndex(isr, 0, (__bridge CFDictionaryRef)options);
if (image) {
_imageProperties = (__bridge_transfer NSDictionary*)CGImageSourceCopyPropertiesAtIndex(isr, 0, (__bridge CFDictionaryRef)_imageProperties);
_imageUTType = (__bridge NSString*)CGImageSourceGetType(isr);
}
CFRelease(isr);
}
if (image) {
[imageView setImage:image imageProperties:_imageProperties];
CGImageRelease(image);
}
[[model saveTempMutabDict] setValue:[imageUrl absoluteString] forKey:#"tempImage"];
}
}];
return;
}
}
And here is the code how I save it:
- (void)saveImage:(NSString *)path {
// get the current image from the image view
CGImageRef sourceImgRef = [imageView image];
NSRect targetRect = [imageView visibleRect];
NSImage *sourceImg = [[NSImage alloc] initWithCGImage:sourceImgRef size:NSZeroSize];
NSMutableDictionary *thisTiffDict = [_imageProperties valueForKey:#"{TIFF}"];
NSInteger theOrientation = [[thisTiffDict valueForKey:#"Orientation"] integerValue];
NSImage *targetImg = nil;
if (theOrientation == 6) {
targetImg = [[NSImage alloc] initWithSize:NSMakeSize([imageView frame].size.height, [imageView frame].size.width)];
} else {
targetImg = [[NSImage alloc] initWithSize:NSMakeSize([imageView frame].size.width, [imageView frame].size.height)];
}
NSRect sourceRect = [imageView convertViewRectToImageRect:targetRect];
[targetImg lockFocus];
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[sourceImg drawAtPoint:NSZeroPoint fromRect:sourceRect operation:NSCompositeSourceOver fraction:1.0f];
[targetImg unlockFocus];
_saveOptions = [[IKSaveOptions alloc] initWithImageProperties:_imageProperties imageUTType: _imageUTType];
NSString * newUTType = [_saveOptions imageUTType];
CGImageRef targetImgRef = [targetImg CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil];
if (targetImgRef) {
NSURL *url = [NSURL fileURLWithPath: path];
CGImageDestinationRef dest = CGImageDestinationCreateWithURL((__bridge CFURLRef)url, (__bridge CFStringRef)newUTType, 1, NULL);
if (dest) {
CGImageDestinationAddImage(dest, targetImgRef, (__bridge CFDictionaryRef)[_saveOptions imageProperties]);
CGImageDestinationFinalize(dest);
CFRelease(dest);
}
}
}
I have no idea what I'm doing wrong?
Thank you
Jens