diff --git a/Tesseract OCR iOS.xcodeproj/project.pbxproj b/Tesseract OCR iOS.xcodeproj/project.pbxproj index 84e2ec9e..56f9f541 100644 --- a/Tesseract OCR iOS.xcodeproj/project.pbxproj +++ b/Tesseract OCR iOS.xcodeproj/project.pbxproj @@ -7,8 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 413F03321A5FBBDD000C194B /* UIImage+G8FixOrientation.h in Headers */ = {isa = PBXBuildFile; fileRef = 413F03301A5FBBDD000C194B /* UIImage+G8FixOrientation.h */; }; - 413F03331A5FBBDD000C194B /* UIImage+G8FixOrientation.m in Sources */ = {isa = PBXBuildFile; fileRef = 413F03311A5FBBDD000C194B /* UIImage+G8FixOrientation.m */; }; 73C0A7961A5932C400D823D4 /* G8Tesseract.h in Headers */ = {isa = PBXBuildFile; fileRef = 64A029D617307CD0002B12E7 /* G8Tesseract.h */; settings = {ATTRIBUTES = (Public, ); }; }; 73C0A7971A5932C800D823D4 /* G8Tesseract.mm in Sources */ = {isa = PBXBuildFile; fileRef = 64A029D717307CD0002B12E7 /* G8Tesseract.mm */; }; 73C0A7981A5932CC00D823D4 /* G8TesseractDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4141211F1A4C578800583ED4 /* G8TesseractDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -331,8 +329,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 413F03301A5FBBDD000C194B /* UIImage+G8FixOrientation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+G8FixOrientation.h"; sourceTree = ""; }; - 413F03311A5FBBDD000C194B /* UIImage+G8FixOrientation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+G8FixOrientation.m"; sourceTree = ""; }; 4141211F1A4C578800583ED4 /* G8TesseractDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = G8TesseractDelegate.h; sourceTree = ""; }; 418997A71A42CC8B00D6477C /* G8Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = G8Constants.h; sourceTree = ""; }; 41A95DE81A3AF39B0085093C /* G8TesseractParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = G8TesseractParameters.h; sourceTree = ""; }; @@ -747,8 +743,6 @@ 418997A71A42CC8B00D6477C /* G8Constants.h */, 6490748A198A5A5600D728CC /* UIImage+G8Filters.h */, 6490748B198A5A5600D728CC /* UIImage+G8Filters.m */, - 413F03301A5FBBDD000C194B /* UIImage+G8FixOrientation.h */, - 413F03311A5FBBDD000C194B /* UIImage+G8FixOrientation.m */, 41C7E8231A3F0682000DC42B /* Core */, 41C7E8211A3F0650000DC42B /* Readme */, 64A0293017307C1D002B12E7 /* Supporting Files */, @@ -1171,7 +1165,6 @@ F1A7AAA71B334C7200FE9650 /* edgblob.h in Headers */, F1A7AAD61B334C7200FE9650 /* intfeaturespace.h in Headers */, F1A7AAD91B334C7200FE9650 /* intproto.h in Headers */, - 413F03321A5FBBDD000C194B /* UIImage+G8FixOrientation.h in Headers */, F1A7AAB81B334C7200FE9650 /* fileerr.h in Headers */, F1A7AB331B334C7300FE9650 /* scanedg.h in Headers */, F1A7AB471B334C7300FE9650 /* stringrenderer.h in Headers */, @@ -1539,7 +1532,6 @@ 73C0A7A11A59330E00D823D4 /* UIImage+G8Filters.m in Sources */, 73C0A79C1A5932F500D823D4 /* G8RecognitionOperation.m in Sources */, 73C0A7971A5932C800D823D4 /* G8Tesseract.mm in Sources */, - 413F03331A5FBBDD000C194B /* UIImage+G8FixOrientation.m in Sources */, 73C0A79E1A5932FD00D823D4 /* G8TesseractParameters.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/TesseractOCR/G8Tesseract.mm b/TesseractOCR/G8Tesseract.mm index d4e3302a..b7fe5107 100644 --- a/TesseractOCR/G8Tesseract.mm +++ b/TesseractOCR/G8Tesseract.mm @@ -10,7 +10,6 @@ #import "G8Tesseract.h" #import "UIImage+G8Filters.h" -#import "UIImage+G8FixOrientation.h" #import "G8TesseractParameters.h" #import "G8Constants.h" #import "G8RecognizedBlock.h" @@ -375,8 +374,6 @@ - (void)setImage:(UIImage *)image return; } - image = [image fixOrientation]; - self.imageSize = image.size; //self.imageSize used in the characterBoxes method Pix *pix = nullptr; @@ -819,14 +816,19 @@ - (Pix *)pixForImage:(UIImage *)image const UInt8 *pixels = CFDataGetBytePtr(imageData); size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage); + size_t bytesPerPixel = bitsPerPixel / 8; size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); int bpp = MAX(1, (int)bitsPerPixel); Pix *pix = pixCreate(width, height, bpp == 24 ? 32 : bpp); l_uint32 *data = pixGetData(pix); int wpl = pixGetWpl(pix); + + void (^copyBlock)(l_uint32 *toAddr, NSUInteger toOffset, const UInt8 *fromAddr, NSUInteger fromOffset) = nil; switch (bpp) { + #if 0 // BPP1 start. Uncomment this if UIImage can support 1bpp someday + // Just a reference for the copyBlock case 1: for (int y = 0; y < height; ++y, data += wpl, pixels += bytesPerRow) { for (int x = 0; x < width; ++x) { @@ -840,15 +842,16 @@ - (Pix *)pixForImage:(UIImage *)image } break; #endif // BPP1 end - case 8: - // Greyscale just copies the bytes in the right order. - for (int y = 0; y < height; ++y, data += wpl, pixels += bytesPerRow) { - for (int x = 0; x < width; ++x) { - SET_DATA_BYTE(data, x, pixels[x]); - } - } + + case 8: { + copyBlock = ^(l_uint32 *toAddr, NSUInteger toOffset, const UInt8 *fromAddr, NSUInteger fromOffset) { + SET_DATA_BYTE(toAddr, toOffset, fromAddr[fromOffset]); + }; break; + } + #if 0 // BPP24 start. Uncomment this if UIImage can support 24bpp someday + // Just a reference for the copyBlock case 24: // Put the colors in the correct places in the line buffer. for (int y = 0; y < height; ++y, pixels += bytesPerRow) { @@ -860,19 +863,106 @@ - (Pix *)pixForImage:(UIImage *)image } break; #endif // BPP24 end - case 32: + + case 32: { + copyBlock = ^(l_uint32 *toAddr, NSUInteger toOffset, const UInt8 *fromAddr, NSUInteger fromOffset) { + toAddr[toOffset] = (fromAddr[fromOffset] << 24) | (fromAddr[fromOffset + 1] << 16) | + (fromAddr[fromOffset + 2] << 8) | fromAddr[fromOffset + 3]; + }; + break; + } + + default: + NSLog(@"Cannot convert image to Pix with bpp = %d", bpp); // LCOV_EXCL_LINE + } + + switch (image.imageOrientation) { + case UIImageOrientationUp: // Maintain byte order consistency across different endianness. for (int y = 0; y < height; ++y, pixels += bytesPerRow, data += wpl) { for (int x = 0; x < width; ++x) { - data[x] = (pixels[x * 4] << 24) | (pixels[x * 4 + 1] << 16) | - (pixels[x * 4 + 2] << 8) | pixels[x * 4 + 3]; + copyBlock(data, x, pixels, x * bytesPerPixel); + } + } + break; + + case UIImageOrientationUpMirrored: + // Maintain byte order consistency across different endianness. + for (int y = 0; y < height; ++y, pixels += bytesPerRow, data += wpl) { + int maxX = width - 1; + for (int x = maxX; x >= 0; --x) { + copyBlock(data, maxX - x, pixels, x * bytesPerPixel); + } + } + break; + + case UIImageOrientationDown: + // Maintain byte order consistency across different endianness. + pixels += (height - 1) * bytesPerRow; + for (int y = height - 1; y >= 0; --y, pixels -= bytesPerRow, data += wpl) { + int maxX = width - 1; + for (int x = maxX; x >= 0; --x) { + copyBlock(data, maxX - x, pixels, x * bytesPerPixel); + } + } + break; + + case UIImageOrientationDownMirrored: + // Maintain byte order consistency across different endianness. + pixels += (height - 1) * bytesPerRow; + for (int y = height - 1; y >= 0; --y, pixels -= bytesPerRow, data += wpl) { + for (int x = 0; x < width; ++x) { + copyBlock(data, x, pixels, x * bytesPerPixel); + } + } + break; + + case UIImageOrientationLeft: + // Maintain byte order consistency across different endianness. + for (int x = 0; x < height; ++x, data += wpl) { + int maxY = width - 1; + for (int y = maxY; y >= 0; --y) { + int x0 = y * (int)bytesPerRow + x * bytesPerPixel; + copyBlock(data, maxY - y, pixels, x0); + } + } + break; + + case UIImageOrientationLeftMirrored: + // Maintain byte order consistency across different endianness. + for (int x = height - 1; x >= 0; --x, data += wpl) { + int maxY = width - 1; + for (int y = maxY; y >= 0; --y) { + int x0 = y * (int)bytesPerRow + x * bytesPerPixel; + copyBlock(data, maxY - y, pixels, x0); + } + } + break; + + case UIImageOrientationRight: + // Maintain byte order consistency across different endianness. + for (int x = height - 1; x >=0; --x, data += wpl) { + for (int y = 0; y < width; ++y) { + int x0 = y * (int)bytesPerRow + x * bytesPerPixel; + copyBlock(data, y, pixels, x0); + } + } + break; + + case UIImageOrientationRightMirrored: + // Maintain byte order consistency across different endianness. + for (int x = 0; x < height; ++x, data += wpl) { + for (int y = 0; y < width; ++y) { + int x0 = y * (int)bytesPerRow + x * bytesPerPixel; + copyBlock(data, y, pixels, x0); } } break; default: - NSLog(@"Cannot convert image to Pix with bpp = %d", bpp); // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE } + pixSetYRes(pix, (l_int32)self.sourceResolution); CFRelease(imageData); diff --git a/TesseractOCR/UIImage+G8FixOrientation.h b/TesseractOCR/UIImage+G8FixOrientation.h deleted file mode 100644 index 85e70a14..00000000 --- a/TesseractOCR/UIImage+G8FixOrientation.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// UIImage+G8FixOrientation.h -// Tesseract OCR iOS -// -// Thanks to `an0` for answer from -// http://stackoverflow.com/a/10611036 -// -// Created by Nikolay Volosatov on 09/01/15. -// Copyright (c) 2014 Daniele Galiotto - www.g8production.com. -// All rights reserved. -// - -#import - -@interface UIImage (G8FixOrientation) - -- (UIImage *)fixOrientation; - -@end diff --git a/TesseractOCR/UIImage+G8FixOrientation.m b/TesseractOCR/UIImage+G8FixOrientation.m deleted file mode 100644 index 90baf53c..00000000 --- a/TesseractOCR/UIImage+G8FixOrientation.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// UIImage+G8FixOrientation.m -// Tesseract OCR iOS -// -// Thanks to `an0` for answer from -// http://stackoverflow.com/a/10611036 -// -// Created by Nikolay Volosatov on 09/01/15. -// Copyright (c) 2014 Daniele Galiotto - www.g8production.com. -// All rights reserved. -// - -#import "UIImage+G8FixOrientation.h" - -@implementation UIImage (G8FixOrientation) - -- (UIImage *)fixOrientation -{ - // No-op if the orientation is already correct - if (self.imageOrientation == UIImageOrientationUp) return self; - - UIImage *result; - - UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); - - [self drawInRect:(CGRect){0, 0, self.size}]; - result = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); - - return result; -} - -@end diff --git a/TestsProject/TestsProject.xcodeproj/project.pbxproj b/TestsProject/TestsProject.xcodeproj/project.pbxproj index d29a3b6a..0afe4f9a 100644 --- a/TestsProject/TestsProject.xcodeproj/project.pbxproj +++ b/TestsProject/TestsProject.xcodeproj/project.pbxproj @@ -32,13 +32,26 @@ 73BE4C311A5B404C002C15F1 /* well_scaned_page.hOCR in Resources */ = {isa = PBXBuildFile; fileRef = 73BE4C301A5B404C002C15F1 /* well_scaned_page.hOCR */; }; 73BE4C351A5BD324002C15F1 /* image_sample.hOCR in Resources */ = {isa = PBXBuildFile; fileRef = 73BE4C341A5BD324002C15F1 /* image_sample.hOCR */; }; 73BE4C441A5DADDD002C15F1 /* TesseractOCR.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73BE4C431A5DADDD002C15F1 /* TesseractOCR.framework */; }; + 84E1362A1B66AF480062F5A2 /* image_sample_right.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 84E136291B66AF480062F5A2 /* image_sample_right.jpg */; }; + 84E1362C1B66AF6F0062F5A2 /* image_sample_down.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 84E1362B1B66AF6F0062F5A2 /* image_sample_down.jpg */; }; + 84E1362E1B66B7950062F5A2 /* image_sample_down_mirrored.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 84E1362D1B66B7950062F5A2 /* image_sample_down_mirrored.jpg */; }; + 84E136301B66BA6B0062F5A2 /* image_sample_right_mirrored.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 84E1362F1B66BA6B0062F5A2 /* image_sample_right_mirrored.jpg */; }; + 84E136321B66BAB00062F5A2 /* image_sample_left_mirrored.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 84E136311B66BAB00062F5A2 /* image_sample_left_mirrored.jpg */; }; + 84E136341B66BC430062F5A2 /* image_sample_up_mirrored.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 84E136331B66BC430062F5A2 /* image_sample_up_mirrored.jpg */; }; + 84E1363C1B66BEE80062F5A2 /* well_scaned_page_down_mirrored.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E136351B66BEE80062F5A2 /* well_scaned_page_down_mirrored.png */; }; + 84E1363D1B66BEE80062F5A2 /* well_scaned_page_down.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E136361B66BEE80062F5A2 /* well_scaned_page_down.png */; }; + 84E1363E1B66BEE80062F5A2 /* well_scaned_page_left_mirrored.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E136371B66BEE80062F5A2 /* well_scaned_page_left_mirrored.png */; }; + 84E1363F1B66BEE80062F5A2 /* well_scaned_page_left.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E136381B66BEE80062F5A2 /* well_scaned_page_left.png */; }; + 84E136401B66BEE80062F5A2 /* well_scaned_page_right_mirrored.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E136391B66BEE80062F5A2 /* well_scaned_page_right_mirrored.png */; }; + 84E136411B66BEE80062F5A2 /* well_scaned_page_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E1363A1B66BEE80062F5A2 /* well_scaned_page_right.png */; }; + 84E136421B66BEE80062F5A2 /* well_scaned_page_up_mirrored.png in Resources */ = {isa = PBXBuildFile; fileRef = 84E1363B1B66BEE80062F5A2 /* well_scaned_page_up_mirrored.png */; }; 8FA2F9CE23919BEC8C64A5EA /* libPods-TestsProjectTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CD3C116A45C293ADAC81D1B /* libPods-TestsProjectTests.a */; }; F120B54A1B45D642003F38A7 /* empty.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F120B5491B45D642003F38A7 /* empty.pdf */; }; F18F53451AE7A6C9005F3843 /* grayscaledImage.png in Resources */ = {isa = PBXBuildFile; fileRef = F18F53441AE7A6C9005F3843 /* grayscaledImage.png */; }; F19D834A1B34C97D00EB8D2E /* NSData+G8Equal.m in Sources */ = {isa = PBXBuildFile; fileRef = F19D83491B34C97D00EB8D2E /* NSData+G8Equal.m */; }; F1A7AB8E1B34B91000FE9650 /* well_scaned_page.pdf in Resources */ = {isa = PBXBuildFile; fileRef = F1A7AB8D1B34B91000FE9650 /* well_scaned_page.pdf */; }; F1D1AFF21B4580C100AB59EE /* well_scaned_page.png in Resources */ = {isa = PBXBuildFile; fileRef = F1D1AFF11B4580C100AB59EE /* well_scaned_page.png */; }; - F1DF11991AE5772400FA6F5D /* rotated_image_sample.jpg in Resources */ = {isa = PBXBuildFile; fileRef = F1DF11981AE5772400FA6F5D /* rotated_image_sample.jpg */; }; + F1DF11991AE5772400FA6F5D /* image_sample_left.jpg in Resources */ = {isa = PBXBuildFile; fileRef = F1DF11981AE5772400FA6F5D /* image_sample_left.jpg */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -90,6 +103,19 @@ 73BE4C341A5BD324002C15F1 /* image_sample.hOCR */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = image_sample.hOCR; sourceTree = ""; }; 73BE4C431A5DADDD002C15F1 /* TesseractOCR.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TesseractOCR.framework; path = "../build/Debug-iphoneos/TesseractOCR.framework"; sourceTree = ""; }; 73C0A7BC1A59561F00D823D4 /* TesseractOCR.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TesseractOCR.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 84E136291B66AF480062F5A2 /* image_sample_right.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_right.jpg; sourceTree = ""; }; + 84E1362B1B66AF6F0062F5A2 /* image_sample_down.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_down.jpg; sourceTree = ""; }; + 84E1362D1B66B7950062F5A2 /* image_sample_down_mirrored.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_down_mirrored.jpg; sourceTree = ""; }; + 84E1362F1B66BA6B0062F5A2 /* image_sample_right_mirrored.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_right_mirrored.jpg; sourceTree = ""; }; + 84E136311B66BAB00062F5A2 /* image_sample_left_mirrored.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_left_mirrored.jpg; sourceTree = ""; }; + 84E136331B66BC430062F5A2 /* image_sample_up_mirrored.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_up_mirrored.jpg; sourceTree = ""; }; + 84E136351B66BEE80062F5A2 /* well_scaned_page_down_mirrored.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_down_mirrored.png; sourceTree = ""; }; + 84E136361B66BEE80062F5A2 /* well_scaned_page_down.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_down.png; sourceTree = ""; }; + 84E136371B66BEE80062F5A2 /* well_scaned_page_left_mirrored.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_left_mirrored.png; sourceTree = ""; }; + 84E136381B66BEE80062F5A2 /* well_scaned_page_left.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_left.png; sourceTree = ""; }; + 84E136391B66BEE80062F5A2 /* well_scaned_page_right_mirrored.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_right_mirrored.png; sourceTree = ""; }; + 84E1363A1B66BEE80062F5A2 /* well_scaned_page_right.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_right.png; sourceTree = ""; }; + 84E1363B1B66BEE80062F5A2 /* well_scaned_page_up_mirrored.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page_up_mirrored.png; sourceTree = ""; }; 8CA185A06F5E788CE0DC28EB /* Pods-TestsProjectTests.coverage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestsProjectTests.coverage.xcconfig"; path = "../Pods/Target Support Files/Pods-TestsProjectTests/Pods-TestsProjectTests.coverage.xcconfig"; sourceTree = ""; }; F120B5491B45D642003F38A7 /* empty.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = empty.pdf; sourceTree = ""; }; F18F53441AE7A6C9005F3843 /* grayscaledImage.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = grayscaledImage.png; sourceTree = ""; }; @@ -97,7 +123,7 @@ F19D83491B34C97D00EB8D2E /* NSData+G8Equal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+G8Equal.m"; sourceTree = ""; }; F1A7AB8D1B34B91000FE9650 /* well_scaned_page.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = well_scaned_page.pdf; sourceTree = ""; }; F1D1AFF11B4580C100AB59EE /* well_scaned_page.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = well_scaned_page.png; sourceTree = ""; }; - F1DF11981AE5772400FA6F5D /* rotated_image_sample.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = rotated_image_sample.jpg; sourceTree = ""; }; + F1DF11981AE5772400FA6F5D /* image_sample_left.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = image_sample_left.jpg; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -219,13 +245,26 @@ F120B5491B45D642003F38A7 /* empty.pdf */, 73BE4C301A5B404C002C15F1 /* well_scaned_page.hOCR */, F1D1AFF11B4580C100AB59EE /* well_scaned_page.png */, + 84E136351B66BEE80062F5A2 /* well_scaned_page_down_mirrored.png */, + 84E136361B66BEE80062F5A2 /* well_scaned_page_down.png */, + 84E136371B66BEE80062F5A2 /* well_scaned_page_left_mirrored.png */, + 84E136381B66BEE80062F5A2 /* well_scaned_page_left.png */, + 84E136391B66BEE80062F5A2 /* well_scaned_page_right_mirrored.png */, + 84E1363A1B66BEE80062F5A2 /* well_scaned_page_right.png */, + 84E1363B1B66BEE80062F5A2 /* well_scaned_page_up_mirrored.png */, F1A7AB8D1B34B91000FE9650 /* well_scaned_page.pdf */, 41C68DB21A41849100848AE1 /* image_sample.jpg */, 41C68DB41A41854600848AE1 /* image_sample_tr.png */, 412E9EAC1A45872A007DDAA5 /* image_sample_bl.png */, 73BE4C341A5BD324002C15F1 /* image_sample.hOCR */, 4141211D1A4B1E3900583ED4 /* image_blank.png */, - F1DF11981AE5772400FA6F5D /* rotated_image_sample.jpg */, + F1DF11981AE5772400FA6F5D /* image_sample_left.jpg */, + 84E136291B66AF480062F5A2 /* image_sample_right.jpg */, + 84E1362B1B66AF6F0062F5A2 /* image_sample_down.jpg */, + 84E136331B66BC430062F5A2 /* image_sample_up_mirrored.jpg */, + 84E136311B66BAB00062F5A2 /* image_sample_left_mirrored.jpg */, + 84E1362F1B66BA6B0062F5A2 /* image_sample_right_mirrored.jpg */, + 84E1362D1B66B7950062F5A2 /* image_sample_down_mirrored.jpg */, F18F53441AE7A6C9005F3843 /* grayscaledImage.png */, ); name = Images; @@ -324,18 +363,31 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 84E1363F1B66BEE80062F5A2 /* well_scaned_page_left.png in Resources */, F1D1AFF21B4580C100AB59EE /* well_scaned_page.png in Resources */, - F1DF11991AE5772400FA6F5D /* rotated_image_sample.jpg in Resources */, + 84E136421B66BEE80062F5A2 /* well_scaned_page_up_mirrored.png in Resources */, + F1DF11991AE5772400FA6F5D /* image_sample_left.jpg in Resources */, + 84E136301B66BA6B0062F5A2 /* image_sample_right_mirrored.jpg in Resources */, + 84E1362C1B66AF6F0062F5A2 /* image_sample_down.jpg in Resources */, 41C68DB31A41849100848AE1 /* image_sample.jpg in Resources */, 73BE4C351A5BD324002C15F1 /* image_sample.hOCR in Resources */, + 84E136321B66BAB00062F5A2 /* image_sample_left_mirrored.jpg in Resources */, + 84E1362E1B66B7950062F5A2 /* image_sample_down_mirrored.jpg in Resources */, 4115B96C1A3EF8E90004EC0A /* Images.xcassets in Resources */, 4115B9851A3EF9920004EC0A /* Launch Screen.xib in Resources */, + 84E1362A1B66AF480062F5A2 /* image_sample_right.jpg in Resources */, + 84E1363E1B66BEE80062F5A2 /* well_scaned_page_left_mirrored.png in Resources */, F1A7AB8E1B34B91000FE9650 /* well_scaned_page.pdf in Resources */, 4141211E1A4B1E3900583ED4 /* image_blank.png in Resources */, + 84E136401B66BEE80062F5A2 /* well_scaned_page_right_mirrored.png in Resources */, F18F53451AE7A6C9005F3843 /* grayscaledImage.png in Resources */, + 84E136341B66BC430062F5A2 /* image_sample_up_mirrored.jpg in Resources */, + 84E136411B66BEE80062F5A2 /* well_scaned_page_right.png in Resources */, 41C68DB51A41854600848AE1 /* image_sample_tr.png in Resources */, 41184B591A3EFD41007F5923 /* tessdata in Resources */, + 84E1363D1B66BEE80062F5A2 /* well_scaned_page_down.png in Resources */, 736EFF271A5882730031B432 /* tessdata-rus in Resources */, + 84E1363C1B66BEE80062F5A2 /* well_scaned_page_down_mirrored.png in Resources */, 73BE4C311A5B404C002C15F1 /* well_scaned_page.hOCR in Resources */, 412E9EAD1A45872A007DDAA5 /* image_sample_bl.png in Resources */, F120B54A1B45D642003F38A7 /* empty.pdf in Resources */, diff --git a/TestsProject/TestsProject/image_sample_down.jpg b/TestsProject/TestsProject/image_sample_down.jpg new file mode 100644 index 00000000..78a88698 Binary files /dev/null and b/TestsProject/TestsProject/image_sample_down.jpg differ diff --git a/TestsProject/TestsProject/image_sample_down_mirrored.jpg b/TestsProject/TestsProject/image_sample_down_mirrored.jpg new file mode 100644 index 00000000..fb631616 Binary files /dev/null and b/TestsProject/TestsProject/image_sample_down_mirrored.jpg differ diff --git a/TestsProject/TestsProject/rotated_image_sample.jpg b/TestsProject/TestsProject/image_sample_left.jpg similarity index 100% rename from TestsProject/TestsProject/rotated_image_sample.jpg rename to TestsProject/TestsProject/image_sample_left.jpg diff --git a/TestsProject/TestsProject/image_sample_left_mirrored.jpg b/TestsProject/TestsProject/image_sample_left_mirrored.jpg new file mode 100644 index 00000000..de3707a8 Binary files /dev/null and b/TestsProject/TestsProject/image_sample_left_mirrored.jpg differ diff --git a/TestsProject/TestsProject/image_sample_right.jpg b/TestsProject/TestsProject/image_sample_right.jpg new file mode 100644 index 00000000..88d003c2 Binary files /dev/null and b/TestsProject/TestsProject/image_sample_right.jpg differ diff --git a/TestsProject/TestsProject/image_sample_right_mirrored.jpg b/TestsProject/TestsProject/image_sample_right_mirrored.jpg new file mode 100644 index 00000000..8024d91b Binary files /dev/null and b/TestsProject/TestsProject/image_sample_right_mirrored.jpg differ diff --git a/TestsProject/TestsProject/image_sample_up_mirrored.jpg b/TestsProject/TestsProject/image_sample_up_mirrored.jpg new file mode 100644 index 00000000..b4b1ed3d Binary files /dev/null and b/TestsProject/TestsProject/image_sample_up_mirrored.jpg differ diff --git a/TestsProject/TestsProject/well_scaned_page_down.png b/TestsProject/TestsProject/well_scaned_page_down.png new file mode 100644 index 00000000..d78e9be3 Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_down.png differ diff --git a/TestsProject/TestsProject/well_scaned_page_down_mirrored.png b/TestsProject/TestsProject/well_scaned_page_down_mirrored.png new file mode 100644 index 00000000..241085ec Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_down_mirrored.png differ diff --git a/TestsProject/TestsProject/well_scaned_page_left.png b/TestsProject/TestsProject/well_scaned_page_left.png new file mode 100644 index 00000000..cd863da4 Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_left.png differ diff --git a/TestsProject/TestsProject/well_scaned_page_left_mirrored.png b/TestsProject/TestsProject/well_scaned_page_left_mirrored.png new file mode 100644 index 00000000..2a629977 Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_left_mirrored.png differ diff --git a/TestsProject/TestsProject/well_scaned_page_right.png b/TestsProject/TestsProject/well_scaned_page_right.png new file mode 100644 index 00000000..2c6b8b08 Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_right.png differ diff --git a/TestsProject/TestsProject/well_scaned_page_right_mirrored.png b/TestsProject/TestsProject/well_scaned_page_right_mirrored.png new file mode 100644 index 00000000..adf8edab Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_right_mirrored.png differ diff --git a/TestsProject/TestsProject/well_scaned_page_up_mirrored.png b/TestsProject/TestsProject/well_scaned_page_up_mirrored.png new file mode 100644 index 00000000..e53ad6a1 Binary files /dev/null and b/TestsProject/TestsProject/well_scaned_page_up_mirrored.png differ diff --git a/TestsProject/TestsProjectTests/RecognitionTests.m b/TestsProject/TestsProjectTests/RecognitionTests.m index 72e60736..b8d22b37 100644 --- a/TestsProject/TestsProjectTests/RecognitionTests.m +++ b/TestsProject/TestsProjectTests/RecognitionTests.m @@ -18,6 +18,27 @@ SPEC_BEGIN(RecognitionTests) +void (^testImageWithOrientationShouldContainText)() = ^(UIImage *image, UIImageOrientation orientation, NSString *text) { + UIImage *rotatedImage = [UIImage imageWithCGImage:image.CGImage + scale:image.scale + orientation:orientation]; + + NSAssert(image.imageOrientation != rotatedImage.imageOrientation, @"Error! Image has not been rotated"); + + G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:kG8Languages]; + tesseract.image = rotatedImage; + + [[theBlock(^{ + [tesseract recognize]; + }) shouldNot] raise]; + + NSString *recognizedText = tesseract.recognizedText; + [[recognizedText should] containString:text]; + + UIImage *thresholdedImage = tesseract.thresholdedImage; + [[theValue(thresholdedImage.imageOrientation) should] equal:theValue(UIImageOrientationUp)]; +}; + __block G8RecognitionTestsHelper *helper; beforeEach(^{ @@ -61,25 +82,15 @@ }); it(@"Should recognize regardless of orientation", ^{ - UIImage *image = [UIImage imageNamed:@"rotated_image_sample.jpg"]; - UIImage *rotatedImage = [UIImage imageWithCGImage:image.CGImage - scale:image.scale - orientation:UIImageOrientationRight]; - - NSAssert(image.imageOrientation != rotatedImage.imageOrientation, @"Error! Image has not been rotated"); - - G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:kG8Languages]; - tesseract.image = rotatedImage; - [[theBlock(^{ - [tesseract recognize]; - }) shouldNot] raise]; - - NSString *recognizedText = tesseract.recognizedText; - [[recognizedText should] containString:@"1234567890"]; - - UIImage *thresholdedImage = tesseract.thresholdedImage; - [[theValue(thresholdedImage.imageOrientation) should] equal:theValue(UIImageOrientationUp)]; + NSString *text = @"1234567890"; + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_left.jpg"], UIImageOrientationLeft, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_right.jpg"], UIImageOrientationRight, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_down.jpg"], UIImageOrientationDown, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_up_mirrored.jpg"], UIImageOrientationUpMirrored, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_left_mirrored.jpg"], UIImageOrientationLeftMirrored, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_right_mirrored.jpg"], UIImageOrientationRightMirrored, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"image_sample_down_mirrored.jpg"], UIImageOrientationDownMirrored, text); }); describe(@"Subimage", ^{ @@ -286,6 +297,18 @@ [[[[helper.tesseract recognizedBlocksByIteratorLevel:G8PageIteratorLevelWord] should] haveAtLeast:10] items]; }); + + it(@"Should recognize regardless of orientation", ^{ + + NSString *text = kG8WellScanedFinalLongString; + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_left"], UIImageOrientationLeft, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_right"], UIImageOrientationRight, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_down"], UIImageOrientationDown, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_up_mirrored"], UIImageOrientationUpMirrored, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_left_mirrored"], UIImageOrientationLeftMirrored, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_right_mirrored"], UIImageOrientationRightMirrored, text); + testImageWithOrientationShouldContainText([UIImage imageNamed:@"well_scaned_page_down_mirrored"], UIImageOrientationDownMirrored, text); + }); }); #pragma mark - hOCR