KMOCTool.m 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. //
  2. // KMOCTool.m
  3. // PDF Reader Pro
  4. //
  5. // Created by liujiajie on 2023/11/15.
  6. //
  7. #import "KMOCTool.h"
  8. #import <Foundation/Foundation.h>
  9. #import <CoreGraphics/CoreGraphics.h>
  10. #import <Cocoa/Cocoa.h>
  11. #import <PDF_Reader_Pro-Swift.h>
  12. @implementation KMOCTool
  13. + (void)createPDFFile:(NSString *)filePath imagePaths:(NSArray *)paths results:(NSArray *)resultsArray scale:(CGFloat)scale {
  14. if (paths.count < 1) {
  15. return;
  16. }
  17. CFStringRef path = (__bridge CFStringRef)filePath;
  18. CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0);
  19. CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL,
  20. 0,
  21. &kCFTypeDictionaryKeyCallBacks,
  22. &kCFTypeDictionaryValueCallBacks);
  23. CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("Kdan Mobile PDF Reader"));
  24. CGContextRef pdfContext = CGPDFContextCreateWithURL(url, &CGRectZero, myDictionary);
  25. CGContextSetRGBFillColor(pdfContext, 1.0, 0.0, 0.0, 0.0);
  26. CGContextSetTextDrawingMode(pdfContext, kCGTextFill);
  27. CFRelease(myDictionary);
  28. CFRelease(url);
  29. for (int i=0; i<paths.count; i++) {
  30. NSString *path = [paths objectAtIndex:i];
  31. NSImage *image = [[NSImage alloc] initWithContentsOfFile:path];
  32. CIImage *imageCIImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:path]];
  33. NSSize size = [imageCIImage extent].size;
  34. CGRect pageRect = CGRectMake(0, 0, size.width/scale, size.height/scale);
  35. CFMutableDictionaryRef pageDictionary = CFDictionaryCreateMutable(NULL,
  36. 0,
  37. &kCFTypeDictionaryKeyCallBacks,
  38. &kCFTypeDictionaryValueCallBacks);
  39. CFDataRef boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof (CGRect));
  40. CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
  41. CGPDFContextBeginPage (pdfContext, pageDictionary);
  42. NSData *imageData = [NSData dataWithContentsOfFile:path];
  43. CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
  44. CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
  45. CGContextSaveGState(pdfContext);
  46. CGContextDrawImage(pdfContext, pageRect, imageRef);
  47. CGContextRestoreGState(pdfContext);
  48. CGImageRelease(imageRef);
  49. [NSGraphicsContext saveGraphicsState];
  50. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]];
  51. NSArray *results = nil;
  52. if (i < resultsArray.count) {
  53. results = resultsArray[i];
  54. CGFloat newScale = scale;
  55. if([KMGOCRManager defaultManager].OCRType == KMOCRType_Apple)
  56. newScale = 1;
  57. if (results.count == 1) {
  58. KMGOCRResult *result = results[0];
  59. NSRect bounds = NSMakeRect((result.textBounds.origin.x)/newScale,
  60. pageRect.size.height-(result.textBounds.origin.y+result.textBounds.size.height)/newScale,
  61. (result.textBounds.size.width)/newScale,
  62. (result.textBounds.size.height)/newScale);
  63. NSDictionary *dic = @{NSFontAttributeName:FontWithSize(result.text, CGSizeMake(result.textBounds.size.width/newScale, result.textBounds.size.height/newScale)),
  64. NSForegroundColorAttributeName:[NSColor clearColor]};
  65. [result.text drawInRect:bounds withAttributes:dic];
  66. } else {
  67. for (int i=1; i<results.count; i++) {
  68. KMGOCRResult *result = results[i];
  69. NSRect bounds = NSMakeRect((result.textBounds.origin.x)/newScale,
  70. pageRect.size.height-(result.textBounds.origin.y+result.textBounds.size.height)/newScale,
  71. (result.textBounds.size.width)/newScale,
  72. (result.textBounds.size.height)/newScale);
  73. NSDictionary *dic = @{NSFontAttributeName:FontWithSize(result.text, CGSizeMake(result.textBounds.size.width/newScale, result.textBounds.size.height/newScale)),
  74. NSForegroundColorAttributeName:[NSColor clearColor]};
  75. [result.text drawInRect:bounds withAttributes:dic];
  76. }
  77. }
  78. }
  79. [NSGraphicsContext restoreGraphicsState];
  80. CGPDFContextEndPage (pdfContext);
  81. CFRelease(pageDictionary);
  82. CFRelease(boxData);
  83. image = nil;
  84. }
  85. CGPDFContextClose(pdfContext);
  86. CGContextRelease (pdfContext);
  87. }
  88. +(NSData*)convertStringsToPDFWithString:(NSArray *)strings{
  89. return convertStringsToPDF(strings);
  90. }
  91. static inline NSFont * FontWithSize(NSString *strChar, CGSize size) {
  92. CGFloat fontsize = 1.0;
  93. NSFont *font = [NSFont systemFontOfSize:fontsize];
  94. CGSize strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
  95. while ((fontsize<127) && (strSize.width<size.width || strSize.height<size.height)) {
  96. fontsize += 1.0;
  97. font = [NSFont systemFontOfSize:fontsize];
  98. strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
  99. }
  100. return [NSFont systemFontOfSize:fontsize-1];
  101. }
  102. static NSData *convertStringsToPDF(NSArray<NSAttributedString *> *strings)
  103. {
  104. NSMutableData *pdfData = [[NSMutableData alloc] init];
  105. CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)pdfData);
  106. CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL,
  107. 0,
  108. &kCFTypeDictionaryKeyCallBacks,
  109. &kCFTypeDictionaryValueCallBacks);
  110. CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("PDF Reader Pro"));
  111. CGRect mediaBox = CGRectMake(0, 0, 595, 842);
  112. CGContextRef pdfContext = CGPDFContextCreate(consumer, &mediaBox, myDictionary);
  113. CGContextSetRGBFillColor(pdfContext, 1.0, 0.0, 0.0, 0.0);
  114. CGContextSetTextDrawingMode(pdfContext, kCGTextFill);
  115. CFRelease(myDictionary);
  116. for (NSAttributedString *attributeString in strings) {
  117. if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_10) {
  118. NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributeString];
  119. NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
  120. [textStorage addLayoutManager:layoutManager];
  121. while (YES) {
  122. NSSize contentSize = NSMakeSize(mediaBox.size.width-40,
  123. mediaBox.size.height-40);
  124. NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:contentSize];
  125. [layoutManager addTextContainer:textContainer];
  126. NSRange rang = [layoutManager glyphRangeForTextContainer:textContainer];
  127. if (rang.length <= 0 ||
  128. rang.length + rang.location > attributeString.length) {
  129. break;
  130. }
  131. NSAttributedString *attStr = [attributeString attributedSubstringFromRange:rang];
  132. [NSGraphicsContext saveGraphicsState];
  133. // [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:pdfContext flipped:NO]];
  134. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]];
  135. CGContextBeginPage(pdfContext, &mediaBox);
  136. [attStr drawInRect:CGRectMake(20, 20,
  137. mediaBox.size.width-40,
  138. mediaBox.size.height-40)];
  139. CGContextEndPage(pdfContext);
  140. [NSGraphicsContext restoreGraphicsState];
  141. }
  142. } else {
  143. [NSGraphicsContext saveGraphicsState];
  144. [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:pdfContext flipped:NO]];
  145. CGContextBeginPage(pdfContext, &mediaBox);
  146. [attributeString drawInRect:CGRectMake(20, 20,
  147. mediaBox.size.width-40,
  148. mediaBox.size.height-40)];
  149. CGContextEndPage(pdfContext);
  150. [NSGraphicsContext restoreGraphicsState];
  151. }
  152. }
  153. CGPDFContextClose(pdfContext);
  154. CGContextRelease (pdfContext);
  155. return pdfData;
  156. }
  157. @end