Printing multiple images each on a separate page using single NSPrintOperation - objective-c

I have a application that intends to print raster image of each page of a document using NSPrintOperation. I am able to create a NSImage of a single page and print it using NSPrintOperation as follows
-void printPage:(NSImage)nsImage
{
NSImageView *nsImageView = [[NSImageView alloc] init];
NSSize imageSize = [nsImage size];
[nsImageView setImage:(NSImage *)nsImage];
[nsImageView setFrame:NSMakeRect(0, 0, imageSize.width, imageSize.height)];
[nsImageView setImageScaling:NSScaleToFit];
NSPrintOperation *mNSPrintOperation = [NSPrintOperation printOperationWithView:(NSView *)nsImageView];
NSPrintInfo *currentNSPrintInfo = [NSPrintInfo sharedPrintInfo];
[currentNSPrintInfo setHorizontalPagination:NSFitPagination];
[currentNSPrintInfo setVerticalPagination:NSFitPagination];
[mNSPrintOperation setPrintInfo:currentNSPrintInfo];
[mNSPrintOperation setShowsPrintPanel:NO];
[mNSPrintOperation setShowsProgressPanel:YES];
[mNSPrintOperation runOperation];
}
Now when I have multiple pages to print, I would like to print all of them using a single NSPrintOperation. So basically, I would like to insert NSImage/NSImageView of each page as a separate page into a single NSView and use this NSView to print finally using NSPrintOperation. The reason I want to print it using single NSPrintOperation is that I want to get the print progress bar that shows the current page being printed. Otherwise, I could have created a separate NSPrintOperation for each NSImageView and print using it.

Related

Loading a png into a UIImageView iOS

I have two images that need to be overlaid over one another, and they are both png images (since I need to be able to make them transparent). However, when I load them into a UIImage view in my xib file, neither of them display at all! When I try using the jpg format of the same images it works fine, but because jpg doesn't support transparency, the overlay effect I need is lost. How can I get the png images to actually display in the window?
This is the kind of task that is easier to do from code than from Interface "Crappy" Builder:
CGRect imageFrame = CGRectMake(x, y, width, height);
UIImage *image1 = // however you obtain your 1st image
UIImage *image2 = // however you obtain your 2nd image
UIImageView *imgView1 = [[UIImageView alloc] initWithImage:image1];
// Adjust the alpha of the view
imgView1.alpha = 1.0f; // This is most advisably 1.0 (always)
imgView1.backgroundColor = [UIColor clearColor];
imgView1.frame = imageFrame;
UIImageView *imgView2 = [[UIImageView alloc] initWithImage:image2];
// Adjust the alpha of the view
imgView1.alpha = 0.5f; // or whatever you find practical
imgView1.backgroundColor = [UIColor clearColor];
imgView2.frame = imageFrame;
// Assume a view controller
[self.view addSubview:imgView1];
[self.view addSUbview:imgView2]; // add the image view later which you wanna be on the top of the other one
// If non-ARC environment, we need to take care of the percious RAM
[imgView1 release];
[imgView2 release];
Try to open your png images in a photo editor like photoshop or pixelmator and save it again as NOT interlaced (in the save options of png).

how load many photos from url in background (asynchronous)

i have this method i use to load many images to scroll view, but when the images load from the url my scroll view is stuck and i can't understand how to load them in the background so the user will not feel it.
this method will call few times (8) in "for" cycle.
- (void)loadPhotosToLeftscroll{
//getting image information from JSON
NSMutableDictionary *photoDict;
photoDict = [leftPhotoArray lastObject];
//getting the photo
NSString *photoPath = [photoDict objectForKey:#"photos_path"];
NSLog(#"photo Path:%#",photoPath);
NSData * imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:photoPath]];
UIImage *image = [UIImage imageWithData:imageData];
// use the image how you like, say, as your button background
//calculating the hight of next photo
UIImageView *leftImage = [leftBlockScroll.subviews lastObject];
//allocating photoView
UIImageView *photoView = [[UIImageView alloc]initWithFrame:CGRectMake(5 , leftImage.frame.origin.y + leftImage.frame.size.height+5, image.size.width/2, image.size.height/2 )];
photoView.userInteractionEnabled=YES;
[photoView.layer setMasksToBounds:YES];
[photoView.layer setCornerRadius:3];
//getting items list
NSDictionary *sh_items = [photoDict objectForKey:#"items"];
//adding image button
UIButton *imageOverButton = [UIButton buttonWithType:UIButtonTypeCustom];
imageOverButton.frame = CGRectMake(0, 0, photoView.frame.size.width, photoView.frame.size.height);
[imageOverButton addTarget:self action:#selector(LeftimagePressed:) forControlEvents:UIControlEventTouchUpInside];
[imageOverButton setTag:[leftPhotoArray count]-1];
[photoView addSubview:imageOverButton];
//adding sh button to imageView
[self addThe_sh_signs:sh_items To_ImageView:photoView];
//subViewing the image to the scrollView
[self insert_Image:image toImageView:photoView in_Scroll:leftBlockScroll];
//calclulating the position of next imageView in scroll.
nextLeftPhotoHight = photoView.frame.size.height + photoView.frame.origin.y + 5;
//calculating the hight of the highest scroll view in both.
leftBlockScroll.contentSize = CGSizeMake(160, [self theSizeOfScrollViewHight]);
rightBlocScroll.contentSize = CGSizeMake(160, [self theSizeOfScrollViewHight]);
isLoadindContant = NO;
[self.view reloadInputViews];
[leftBlockScroll reloadInputViews];
}
please do not send me to some link that trying to explain how to use the asynchronous.
Try to explain according the method you see here.
Im here for any question, that you need to ask to help me.
You will have to do it asynchronously in a proper way. I do not think there is any way around that. I subclassed an UIImageView object and placed many instances of it within the cells of a talbe (in your case within the scroll view). The subclass objects are initialized with an url and load their image asynchronously (with some caching so that the image is not loaded every time).
This tutorial helped me much in the beginning:
http://www.markj.net/iphone-asynchronous-table-image/
You will just have to adopt that to your scroll view. The underlaying principle remains the same.

Obj-C View to PDF only renders first page

I've got a UIView extension class called UIView+PDFView which takes the current view, splits it into pages, and renders a PDF document. My issue lies in the rendering part; I can successfully 'create' pages for content, however all pages after the first are blank. My end goal is to take the current view, 'scale' the width equal to the page, and paginate the rest of the view within a PDF.
What the issue isn't:
Attaching the PDF to e-mail
Sending the PDF to a printer/print simulator
Only printing one page while actually generating the PDF correctly
Correctly resizing the view (SO Question 4919388)
I do this before I send to method. Verified by making frame 10px tall, still prints one (and only one) full page
Correctly translating the view. Verified by making both a translation and a scale; both correctly changed the view, however neither rendered on more than the first page.
My code is as follows:
#interface UIView (PDFView)
-(id)createPDFAndSaveToDocumentsWithFileName:(NSString*)aFilename andDocumentInfo:(NSDictionary *)documentInfo;
#end
#implementation UIView (PDFView)
-(id)createPDFAndSaveToDocumentsWithFileName:(NSString*)aFilename andDocumentInfo:(NSDictionary *)documentInfo {
// http://developer.apple.com/library/ios/DOCUMENTATION/GraphicsImaging/Reference/CGPDFContext/Reference/reference.html#//apple_ref/doc/constant_group/Auxiliary_Dictionary_Keys
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
CGSize pageSize = CGSizeMake(self.bounds.size.width, 792);
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, documentInfo);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
NSInteger currentPage = 0;
BOOL done = NO;
do {
CGRect currentPageRect = CGRectMake(0, (pageSize.height*currentPage), pageSize.width, pageSize.height);
UIGraphicsBeginPDFPageWithInfo(currentPageRect, nil);
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[self.layer renderInContext:pdfContext];
// If we're at the end of the view, exit the loop.
if ((pageSize.height*currentPage) > self.bounds.size.height) {
done = YES;
} else {
currentPage++;
}
} while (!done);
// remove PDF rendering context
UIGraphicsEndPDFContext();
if (aFilename == nil) {
return pdfData;
} else {
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectoryFilename);
return nil;
}
}
i think your problem lies
CGRect currentPageRect = CGRectMake(0, (pageSize.height*currentPage), pageSize.width, pageSize.height);
instead of that try using either of the below statements
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0.0, 0.0, 612.0, 792.0), nil);
UIGraphicsBeginPDFPage();
everytime you wish to add a new page to the context use the above statements and you would be able to add pages to the context.
if you wish to use the default size of the page i.e. 612 X 792 you can directly use UIGraphicsBeginPDFPage();
for custom page size you can use UIGraphicsBeginPDFPageWithInfo(CGRectMake(0.0, 0.0, 612.0, 792.0), nil);
I think that should solve your problem.

issue in setting UIViews, view.bounds.origin.y while using in layer renderInContext:

I am trying to crop and then transform a UIView to a pdf file. The UIView is cropping correctly for x component, width and height. But it is taking the same y component,ie 0 for rendering.I want to crop the image 110 points from top. This is my code
UIView *tempV;
tempV=self.view;
CGRect fram= tempV.bounds;
fram.origin.x=537;
fram.origin.y=110;
fram.size.width=404;
fram.size.height=772;
tempV.bounds=fram;
NSLog(#"Mail");
NSLog(#"%f,%f,%f,%f",tempV.bounds.origin.x,tempV.bounds.origin.y,tempV.bounds.size.width,tempV.bounds.size.height);
NSMutableData *pdfData=[NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, tempV.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext= UIGraphicsGetCurrentContext();
[tempV.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
MFMailComposeViewController *mailComposer=[[[MFMailComposeViewController alloc]init] autorelease];
mailComposer.mailComposeDelegate=self;
[mailComposer addAttachmentData: pdfData mimeType: #"application/pdf" fileName: #"Dudel creation.pdf"];
[pdfData writeToFile:#"Dudel creation.pdf" atomically:YES];
[self presentModalViewController: mailComposer animated: YES];
You are doing something very wrong in your initial part of your code... I don't even want to go there, but let me break down a few things:
1) UIGraphicsBeginPDFContextToData second parameter is a CGRect.
2) From what I've understood, you want a very specific rectangle of what's showing on your screen and although its center is completely different from your view controller's view (you're trying to change both origin and size). So, why create a dependency on your view controller's view's bounds? (remember bounds and center always go hand in hand).
3) So why not just get rid of the initial part of your code and do this:
CGRect fram = CGRectMake (537, 110, 404, 772); // A rectangle with no other dependency, since you want one very specific.
NSMutableData *pdfData=[NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, fram, nil); // Passing the newly created rectangle as the second parameter to the function.
UIGraphicsBeginPDFPage();
CGContextRef pdfContext= UIGraphicsGetCurrentContext();
[tempV.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
MFMailComposeViewController *mailComposer=[[[MFMailComposeViewController alloc]init] autorelease];
mailComposer.mailComposeDelegate=self;
[mailComposer addAttachmentData: pdfData mimeType: #"application/pdf" fileName: #"Dudel creation.pdf"];
[pdfData writeToFile:#"Dudel creation.pdf" atomically:YES];
[self presentModalViewController: mailComposer animated: YES];

NSPrintOperation hangs application

I have an application that hangs whenever I call NSPrintOperation.
I have a view that is creates a separate class (UIView) like this:
PBPrintImage *printImage = [[PBPrintImage alloc] init];
printImage.image = finalImage;
[printImage printWithNoPanel:self];
Then inside PBPrintImage I have the following method:
- (void)printWithNoPanel:(id)sender {
CGSize picSize = CGSizeMake(300, 446);
NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
NSRect imageRect = NSRectFromCGRect(CGRectMake(0, 0, picSize.width, picSize.height));
NSImageView *imageView = [[NSImageView alloc] initWithFrame:imageRect];
[imageView setImage:image];
NSPrintOperation *op = [NSPrintOperation printOperationWithView:imageView printInfo:printInfo];
[op setCanSpawnSeparateThread:YES];
[op setShowsPrintPanel:NO];
[op runOperation];
}
If I don't call it the application works as suspected. And I've tried calling it with and without setCanSpawnSeparateThread:. How do I set it up so it has to be in a separate thread and therefore doesn't mess up the regular flow of the application?
It does print, but that is only half of the job.
The application should show a modal print dialog (and start a modal run loop), so I would not call it "hanged". It returns to the normal main thread flow as soon as you hit Ok or Cancel.
As for the setCanSpawnSeparateThread: issue, it only kicks in when the print dialog is displayed as a sheet, so you need to call it like this: `[op runOperationModalForWindow:window delegate:self didRunSelector:#selector(_printOperationDidRun:success:contextInfo:) contextInfo:nil]