|
|
|
@ -1,11 +1,10 @@ |
|
|
|
|
// |
|
|
|
|
// Mat+QuickLook.mm |
|
|
|
|
// MatQuickLook.mm |
|
|
|
|
// |
|
|
|
|
// Created by Giles Payne on 2021/07/18. |
|
|
|
|
// |
|
|
|
|
|
|
|
|
|
#import "Mat+QuickLook.h" |
|
|
|
|
#import "Mat+Converters.h" |
|
|
|
|
#import "MatQuickLook.h" |
|
|
|
|
#import "Rect2i.h" |
|
|
|
|
#import "Core.h" |
|
|
|
|
#import "Imgproc.h" |
|
|
|
@ -39,9 +38,9 @@ static UIFont* getSystemFont() { |
|
|
|
|
|
|
|
|
|
typedef UIFont* (*FontGetter)(); |
|
|
|
|
|
|
|
|
|
@implementation Mat (QuickLook) |
|
|
|
|
@implementation MatQuickLook |
|
|
|
|
|
|
|
|
|
- (NSString*)makeLabel:(BOOL)isIntType val:(NSNumber*)num { |
|
|
|
|
+ (NSString*)makeLabel:(BOOL)isIntType val:(NSNumber*)num { |
|
|
|
|
if (isIntType) { |
|
|
|
|
return [NSString stringWithFormat:@"%d", num.intValue]; |
|
|
|
|
} else { |
|
|
|
@ -56,31 +55,31 @@ typedef UIFont* (*FontGetter)(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
- (void)relativeLine:(UIBezierPath*)path relX:(CGFloat)x relY:(CGFloat)y { |
|
|
|
|
+ (void)relativeLine:(UIBezierPath*)path relX:(CGFloat)x relY:(CGFloat)y { |
|
|
|
|
CGPoint curr = path.currentPoint; |
|
|
|
|
[path addLineToPoint:CGPointMake(curr.x + x, curr.y + y)]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
- (id)debugQuickLookObject { |
|
|
|
|
if ([self dims] == 2 && [self rows] <= 10 && [self cols] <= 10 && [self channels] == 1) { |
|
|
|
|
+ (id)matDebugQuickLookObject:(Mat*)mat { |
|
|
|
|
if ([mat dims] == 2 && [mat rows] <= 10 && [mat cols] <= 10 && [mat channels] == 1) { |
|
|
|
|
FontGetter fontGetters[] = { getCMU, getBodoni72, getAnySerif, getSystemFont }; |
|
|
|
|
UIFont* font = nil; |
|
|
|
|
for (int fontGetterIndex = 0; font==nil && fontGetterIndex < (sizeof(fontGetters)) / (sizeof(fontGetters[0])); fontGetterIndex++) { |
|
|
|
|
font = fontGetters[fontGetterIndex](); |
|
|
|
|
} |
|
|
|
|
int elements = [self rows] * [self cols]; |
|
|
|
|
int elements = [mat rows] * [mat cols]; |
|
|
|
|
NSDictionary<NSAttributedStringKey,id>* textFontAttributes = @{ NSFontAttributeName: font, NSForegroundColorAttributeName: UIColor.blackColor }; |
|
|
|
|
NSMutableArray<NSNumber*>* rawData = [NSMutableArray new]; |
|
|
|
|
for (int dataIndex = 0; dataIndex < elements; dataIndex++) { |
|
|
|
|
[rawData addObject:[NSNumber numberWithDouble:0]]; |
|
|
|
|
} |
|
|
|
|
[self get:0 col: 0 data: rawData]; |
|
|
|
|
BOOL isIntType = [self depth] <= CV_32S; |
|
|
|
|
[mat get:0 col: 0 data: rawData]; |
|
|
|
|
BOOL isIntType = [mat depth] <= CV_32S; |
|
|
|
|
NSMutableArray<NSString*>* labels = [NSMutableArray new]; |
|
|
|
|
NSMutableDictionary<NSString*, NSValue*>* boundingRects = [NSMutableDictionary dictionaryWithCapacity:elements]; |
|
|
|
|
int maxWidth = 0, maxHeight = 0; |
|
|
|
|
for (NSNumber* number in rawData) { |
|
|
|
|
NSString* label = [self makeLabel:isIntType val:number]; |
|
|
|
|
NSString* label = [MatQuickLook makeLabel:isIntType val:number]; |
|
|
|
|
[labels addObject:label]; |
|
|
|
|
CGRect boundingRect = [label boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:textFontAttributes context:nil]; |
|
|
|
|
if (boundingRect.size.width > maxWidth) { |
|
|
|
@ -97,18 +96,18 @@ typedef UIFont* (*FontGetter)(); |
|
|
|
|
int borderGap = 8; |
|
|
|
|
int lineThickness = 3; |
|
|
|
|
int lipWidth = 6; |
|
|
|
|
int imageWidth = 2 * (borderGap + lipWidth) + maxWidth * [self cols] + colGap * ([self cols] - 1); |
|
|
|
|
int imageHeight = 2 * (borderGap + lipWidth) + maxHeight * [self rows] + rowGap * ([self rows] - 1); |
|
|
|
|
int imageWidth = 2 * (borderGap + lipWidth) + maxWidth * [mat cols] + colGap * ([mat cols] - 1); |
|
|
|
|
int imageHeight = 2 * (borderGap + lipWidth) + maxHeight * [mat rows] + rowGap * ([mat rows] - 1); |
|
|
|
|
|
|
|
|
|
UIBezierPath* leftBracket = [UIBezierPath new]; |
|
|
|
|
[leftBracket moveToPoint:CGPointMake(borderGap, borderGap)]; |
|
|
|
|
[self relativeLine:leftBracket relX:0 relY:imageHeight - 2 * borderGap]; |
|
|
|
|
[self relativeLine:leftBracket relX:lineThickness + lipWidth relY:0]; |
|
|
|
|
[self relativeLine:leftBracket relX:0 relY:-lineThickness]; |
|
|
|
|
[self relativeLine:leftBracket relX:-lipWidth relY:0]; |
|
|
|
|
[self relativeLine:leftBracket relX:0 relY:-(imageHeight - 2 * (borderGap + lineThickness))]; |
|
|
|
|
[self relativeLine:leftBracket relX:lipWidth relY:0]; |
|
|
|
|
[self relativeLine:leftBracket relX:0 relY:-lineThickness]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:0 relY:imageHeight - 2 * borderGap]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:lineThickness + lipWidth relY:0]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:0 relY:-lineThickness]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:-lipWidth relY:0]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:0 relY:-(imageHeight - 2 * (borderGap + lineThickness))]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:lipWidth relY:0]; |
|
|
|
|
[MatQuickLook relativeLine:leftBracket relX:0 relY:-lineThickness]; |
|
|
|
|
[leftBracket closePath]; |
|
|
|
|
CGAffineTransform reflect = CGAffineTransformConcat(CGAffineTransformMakeTranslation(-imageWidth, 0), CGAffineTransformMakeScale(-1, 1)); |
|
|
|
|
UIBezierPath* rightBracket = [leftBracket copy]; |
|
|
|
@ -124,8 +123,8 @@ typedef UIFont* (*FontGetter)(); |
|
|
|
|
[labels enumerateObjectsUsingBlock:^(id label, NSUInteger index, BOOL *stop) |
|
|
|
|
{ |
|
|
|
|
CGRect boundingRect = boundingRects[label].CGRectValue; |
|
|
|
|
int row = (int)index / [self cols]; |
|
|
|
|
int col = (int)index % [self cols]; |
|
|
|
|
int row = (int)index / [mat cols]; |
|
|
|
|
int col = (int)index % [mat cols]; |
|
|
|
|
int x = borderGap + lipWidth + col * (maxWidth + colGap) + (maxWidth - boundingRect.size.width) / 2; |
|
|
|
|
int y = borderGap + lipWidth + row * (maxHeight + rowGap) + (maxHeight - boundingRect.size.height) / 2; |
|
|
|
|
CGRect textRect = CGRectMake(x, y, boundingRect.size.width, boundingRect.size.height); |
|
|
|
@ -134,26 +133,26 @@ typedef UIFont* (*FontGetter)(); |
|
|
|
|
UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); |
|
|
|
|
UIGraphicsEndImageContext(); |
|
|
|
|
return image; |
|
|
|
|
} else if (([self dims] == 2) && ([self type] == CV_8U || [self type] == CV_8UC3 || [self type] == CV_8UC4)) { |
|
|
|
|
return [self toUIImage]; |
|
|
|
|
} else if ([self dims] == 2 && [self channels] == 1) { |
|
|
|
|
} else if (([mat dims] == 2) && ([mat type] == CV_8U || [mat type] == CV_8UC3 || [mat type] == CV_8UC4)) { |
|
|
|
|
return [mat toUIImage]; |
|
|
|
|
} else if ([mat dims] == 2 && [mat channels] == 1) { |
|
|
|
|
Mat* normalized = [Mat new]; |
|
|
|
|
[Core normalize:self dst:normalized alpha:0 beta:255 norm_type:NORM_MINMAX dtype:CV_8U]; |
|
|
|
|
Mat* normalizedKey = [[Mat alloc] initWithRows:[self rows] + 10 cols:[self cols] type:CV_8U]; |
|
|
|
|
[Core normalize:mat dst:normalized alpha:0 beta:255 norm_type:NORM_MINMAX dtype:CV_8U]; |
|
|
|
|
Mat* normalizedKey = [[Mat alloc] initWithRows:[mat rows] + 10 cols:[mat cols] type:CV_8U]; |
|
|
|
|
std::vector<char> key; |
|
|
|
|
for (int index = 0; index < [self cols]; index++) { |
|
|
|
|
key.push_back((char)(index * 256 / [self cols])); |
|
|
|
|
for (int index = 0; index < [mat cols]; index++) { |
|
|
|
|
key.push_back((char)(index * 256 / [mat cols])); |
|
|
|
|
} |
|
|
|
|
for (int index = 0; index < 10; index++) { |
|
|
|
|
[normalizedKey put:@[[NSNumber numberWithInt:index], [NSNumber numberWithInt:0]] count:[self cols] byteBuffer:key.data()]; |
|
|
|
|
[normalizedKey put:@[[NSNumber numberWithInt:index], [NSNumber numberWithInt:0]] count:[mat cols] byteBuffer:key.data()]; |
|
|
|
|
} |
|
|
|
|
[normalized copyTo:[normalizedKey submatRoi:[[Rect2i alloc] initWithX:0 y:10 width:[self cols] height:[self rows]]]]; |
|
|
|
|
[normalized copyTo:[normalizedKey submatRoi:[[Rect2i alloc] initWithX:0 y:10 width:[mat cols] height:[mat rows]]]]; |
|
|
|
|
Mat* colorMap = [Mat new]; |
|
|
|
|
[Imgproc applyColorMap:normalizedKey dst:colorMap colormap:COLORMAP_JET]; |
|
|
|
|
[Imgproc cvtColor:colorMap dst:colorMap code:COLOR_BGR2RGB]; |
|
|
|
|
return [colorMap toUIImage]; |
|
|
|
|
} |
|
|
|
|
return [self description]; |
|
|
|
|
return [mat description]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@end |