diff --git a/DTImageToDataPatch.h b/DTImageToDataPatch.h new file mode 100644 index 0000000..0c58ce7 --- /dev/null +++ b/DTImageToDataPatch.h @@ -0,0 +1,15 @@ +@interface DTImageToDataPatch : QCPatch +{ + QCImagePort *inputImage; + QCIndexPort *inputImageFileType; + QCVirtualPort *outputRawData; +} + ++(BOOL)isSafe; ++(BOOL)allowsSubpatchesWithIdentifier:(id)identifier; ++(QCPatchExecutionMode)executionModeWithIdentifier:(id)identifier; ++(QCPatchTimeMode)timeModeWithIdentifier:(id)identifier; +-(id)initWithIdentifier:(id)identifier; +-(BOOL)execute:(QCOpenGLContext*)context time:(double)time arguments:(NSDictionary*)arguments; + +@end diff --git a/DTImageToDataPatch.m b/DTImageToDataPatch.m new file mode 100644 index 0000000..004eed9 --- /dev/null +++ b/DTImageToDataPatch.m @@ -0,0 +1,53 @@ +#import "DTImageToDataPatch.h" + +@implementation DTImageToDataPatch + ++(BOOL)isSafe +{ + return NO; +} + ++(BOOL)allowsSubpatchesWithIdentifier:(id)identifier +{ + return NO; +} + ++(QCPatchExecutionMode)executionModeWithIdentifier:(id)identifier +{ + return kQCPatchExecutionModeProcessor; +} + ++(QCPatchTimeMode)timeModeWithIdentifier:(id)identifier +{ + return kQCPatchTimeModeNone; +} + +-(id)initWithIdentifier:(id)identifier +{ + if(self = [super initWithIdentifier:identifier]) + { + [[self userInfo] setObject:@"Kineme Image To Data" forKey:@"name"]; + + [inputImageFileType setMaxIndexValue:NSJPEG2000FileType]; + [inputImageFileType setIndexValue:NSPNGFileType]; + } + return self; +} + +-(BOOL)execute:(QCOpenGLContext*)context time:(double)time arguments:(NSDictionary*)arguments +{ + if ([inputImage wasUpdated] || [inputImageFileType wasUpdated]) + { + NSBitmapImageFileType imageFileType = [inputImageFileType indexValue]; + NSImage *image = [inputImage value]; + NSArray *representations = [image representations]; + NSData *data = [NSBitmapImageRep representationOfImageRepsInArray:representations + usingType:imageFileType + properties:nil]; + [outputRawData setRawValue:data]; + } + + return YES; +} + +@end diff --git a/DTImageToDataPatch.xml b/DTImageToDataPatch.xml new file mode 100644 index 0000000..cec963a --- /dev/null +++ b/DTImageToDataPatch.xml @@ -0,0 +1,57 @@ + + + + + nodeAttributes + + name + Image To Data + categories + + Kineme DataTools + + copyright + Copyright 2011 Kosada Incorporated. All rights reserved. + description + This patch converts an image to raw data bytes. + +http://kineme.net/ + + inputAttributes + + inputImage + + name + Image + description + The image to convert + + inputImageFileType + + name + Image Representation + description + The image representation to use when converting to bytes + menu + + TIFF + BMP + GIF + JPEG + PNG + JPEG2000 + + + + outputAttributes + + outputRawData + + name + Raw Data + description + The bytes of the image + + + + diff --git a/DataTools.xcodeproj/project.pbxproj b/DataTools.xcodeproj/project.pbxproj index c3c29cc..d89223d 100644 --- a/DataTools.xcodeproj/project.pbxproj +++ b/DataTools.xcodeproj/project.pbxproj @@ -87,6 +87,9 @@ E74FE0A015502957009E29D6 /* DTStringToDataPatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E74FE09F15502957009E29D6 /* DTStringToDataPatch.m */; }; E74FE0A115502957009E29D6 /* DTStringToDataPatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E74FE09F15502957009E29D6 /* DTStringToDataPatch.m */; }; E74FE0CB15502E3F009E29D6 /* DTStringToDataPatch.xml in Resources */ = {isa = PBXBuildFile; fileRef = E74FE0CA15502E3F009E29D6 /* DTStringToDataPatch.xml */; }; + E74FE11F15505A7F009E29D6 /* DTImageToDataPatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E74FE11E15505A7F009E29D6 /* DTImageToDataPatch.m */; }; + E74FE12015505A7F009E29D6 /* DTImageToDataPatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E74FE11E15505A7F009E29D6 /* DTImageToDataPatch.m */; }; + E74FE12215505A8D009E29D6 /* DTImageToDataPatch.xml in Resources */ = {isa = PBXBuildFile; fileRef = E74FE12115505A8D009E29D6 /* DTImageToDataPatch.xml */; }; E78586E913E9F64A000BBF4B /* DTStructureKeyPatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E78586E813E9F64A000BBF4B /* DTStructureKeyPatch.m */; }; E78586EB13E9F7DB000BBF4B /* DTStructureKeyPatch.xml in Resources */ = {isa = PBXBuildFile; fileRef = E78586EA13E9F7DB000BBF4B /* DTStructureKeyPatch.xml */; }; E785870513E9F967000BBF4B /* DTStructureKeyPatch.m in Sources */ = {isa = PBXBuildFile; fileRef = E78586E813E9F64A000BBF4B /* DTStructureKeyPatch.m */; }; @@ -194,6 +197,9 @@ E74FE09E15502957009E29D6 /* DTStringToDataPatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTStringToDataPatch.h; sourceTree = ""; }; E74FE09F15502957009E29D6 /* DTStringToDataPatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTStringToDataPatch.m; sourceTree = ""; }; E74FE0CA15502E3F009E29D6 /* DTStringToDataPatch.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DTStringToDataPatch.xml; sourceTree = ""; }; + E74FE11D15505A7F009E29D6 /* DTImageToDataPatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTImageToDataPatch.h; sourceTree = ""; }; + E74FE11E15505A7F009E29D6 /* DTImageToDataPatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTImageToDataPatch.m; sourceTree = ""; }; + E74FE12115505A8D009E29D6 /* DTImageToDataPatch.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DTImageToDataPatch.xml; sourceTree = ""; }; E78586E713E9F64A000BBF4B /* DTStructureKeyPatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTStructureKeyPatch.h; sourceTree = ""; }; E78586E813E9F64A000BBF4B /* DTStructureKeyPatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTStructureKeyPatch.m; sourceTree = ""; }; E78586EA13E9F7DB000BBF4B /* DTStructureKeyPatch.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = DTStructureKeyPatch.xml; sourceTree = ""; }; @@ -371,6 +377,7 @@ E7DC1662134E13A700DBDFC8 /* DTConvertToDataPatch.xml */, E7DC1664134E13E600DBDFC8 /* DTConvertFromDataPatch.xml */, E74FE0CA15502E3F009E29D6 /* DTStringToDataPatch.xml */, + E74FE12115505A8D009E29D6 /* DTImageToDataPatch.xml */, ); name = XML; sourceTree = ""; @@ -467,6 +474,8 @@ E7DC1621134E0F9E00DBDFC8 /* DTConvertFromDataPatch.m */, E74FE09E15502957009E29D6 /* DTStringToDataPatch.h */, E74FE09F15502957009E29D6 /* DTStringToDataPatch.m */, + E74FE11D15505A7F009E29D6 /* DTImageToDataPatch.h */, + E74FE11E15505A7F009E29D6 /* DTImageToDataPatch.m */, ); name = Convert; sourceTree = ""; @@ -572,6 +581,7 @@ E7DC1665134E13E600DBDFC8 /* DTConvertFromDataPatch.xml in Resources */, E78586EB13E9F7DB000BBF4B /* DTStructureKeyPatch.xml in Resources */, E74FE0CB15502E3F009E29D6 /* DTStringToDataPatch.xml in Resources */, + E74FE12215505A8D009E29D6 /* DTImageToDataPatch.xml in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -630,6 +640,7 @@ E72971A313B6ED0C001BBB7F /* DTStructureBreakOutPatchUI.m in Sources */, E785870513E9F967000BBF4B /* DTStructureKeyPatch.m in Sources */, E74FE0A115502957009E29D6 /* DTStringToDataPatch.m in Sources */, + E74FE12015505A7F009E29D6 /* DTImageToDataPatch.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -664,6 +675,7 @@ E7DC1622134E0F9E00DBDFC8 /* DTConvertFromDataPatch.m in Sources */, E78586E913E9F64A000BBF4B /* DTStructureKeyPatch.m in Sources */, E74FE0A015502957009E29D6 /* DTStringToDataPatch.m in Sources */, + E74FE11F15505A7F009E29D6 /* DTImageToDataPatch.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -687,7 +699,6 @@ INFOPLIST_FILE = Info.plist; ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = DataTools; - RUN_CLANG_STATIC_ANALYZER = NO; SDKROOT = macosx10.5; }; name = Release; @@ -738,7 +749,6 @@ ); PREBINDING = NO; PRODUCT_NAME = Tests; - RUN_CLANG_STATIC_ANALYZER = NO; }; name = Release; }; diff --git a/DataToolsPrincipal.m b/DataToolsPrincipal.m index bdea035..2d3e25f 100644 --- a/DataToolsPrincipal.m +++ b/DataToolsPrincipal.m @@ -17,6 +17,7 @@ #import "DTConvertToDataPatch.h" #import "DTConvertFromDataPatch.h" #import "DTStringToDataPatch.h" +#import "DTImageToDataPatch.h" #import "SpookySendPatch.h" #import "SpookyReceivePatch.h" @@ -79,6 +80,7 @@ +(void)registerNodesWithManager:(QCNodeManager*)manager KIRegisterPatch(DTConvertToDataPatch); KIRegisterPatch(DTConvertFromDataPatch); KIRegisterPatch(DTStringToDataPatch); + KIRegisterPatch(DTImageToDataPatch); /* disabled for now, since this hack results in input splitters that require DataTools (which is kinda misleading) { diff --git a/TestDTConvert.m b/TestDTConvert.m index bfbad6a..3f0be9b 100644 --- a/TestDTConvert.m +++ b/TestDTConvert.m @@ -2,6 +2,7 @@ #import "DTConvertToDataPatch.h" #import "DTConvertFromDataPatch.h" #import "DTStringToDataPatch.h" +#import "DTImageToDataPatch.h" @interface TestDTConvert : SkankySDK_TestCase @@ -56,4 +57,34 @@ - (void)testStringToData [dataString release]; } +- (void)testImageToData +{ + DTImageToDataPatch *patch = [[DTImageToDataPatch alloc] initWithIdentifier:nil]; + + // TIFF image -> TIFF data + NSImage *compressedTiffNSImage = [[NSImage alloc] initWithContentsOfFile:@"/Library/User Pictures/Fun/Pizza.tif"]; + NSData *inTiffData = [compressedTiffNSImage TIFFRepresentationUsingCompression:NSTIFFCompressionNone factor:0]; + NSImage *inTiffNSImage = [[NSImage alloc] initWithData:inTiffData]; + QCImage *inTiffQCImage = [[QCImage alloc] initWithNSImage:inTiffNSImage options:nil]; + [self setInputValue:inTiffQCImage forPort:@"inputImage" onPatch:patch]; + [self setInputValue:[NSNumber numberWithInt:NSTIFFFileType] forPort:@"inputImageFileType" onPatch:patch]; + [self executePatch:patch]; + NSData *outTiffData = [self getOutputForPort:@"outputRawData" onPatch:patch]; + const unsigned char expectedTiffBytes[] = { 0x4d, 0x4d, 0x00, 0x2a }; + NSData *expectedTiffData = [NSData dataWithBytes:(const void *)expectedTiffBytes length:4]; + GHAssertEqualObjects(expectedTiffData, [outTiffData subdataWithRange:NSMakeRange(0, 4)], @""); +// NSBitmapImageRep *outTiffImageRep = [NSBitmapImageRep imageRepWithData:outTiffData]; +// GHAssertEqualObjects(inTiffData, [outTiffImageRep TIFFRepresentation], @""); + + // JPEG image -> PNG data + QCImage *inJpegQCImage = [[QCImage alloc] initWithFile:@"/Library/Desktop Pictures/Solid Colors/Solid Aqua Blue.png" options:nil]; + [self setInputValue:inJpegQCImage forPort:@"inputImage" onPatch:patch]; + [self setInputValue:[NSNumber numberWithInt:NSPNGFileType] forPort:@"inputImageFileType" onPatch:patch]; + [self executePatch:patch]; + NSData *outPngData = [self getOutputForPort:@"outputRawData" onPatch:patch]; + const unsigned char expectedPngBytes[] = { 0x89, 0x50, 0x4e, 0x47 }; + NSData *expectedPngData = [NSData dataWithBytes:(const void *)expectedPngBytes length:4]; + GHAssertEqualObjects(expectedPngData, [outPngData subdataWithRange:NSMakeRange(0, 4)], @""); +} + @end