41
41
#import <CoreLocation/CoreLocation.h>
42
42
#import <objc/runtime.h>
44
#define TAPPITY_MAX_FEEDBACK_SIZE 240
45
45
CGImageRef UIGetScreenImage(void);
47
47
@interface UIImage (ScreenImage)
48
48
+ (UIImage *)imageWithScreenContents;
51
@implementation UIImage (ScreenImage)
52
+ (UIImage *)imageWithScreenContents
54
CGImageRef cgScreen = UIGetScreenImage();
56
UIImage *result = [UIImage imageWithCGImage:cgScreen];
57
CGImageRelease(cgScreen);
49
- (UIImage*) scaledToSize: (CGSize) size;
64
52
@interface CLLocationManager (TappityServer)
545
533
[capturedImagesQueue removeObjectAtIndex: 0];
547
535
[capturedImagesCondition unlock];
537
CGRect imgRect = {CGPointZero, [img size]};
539
float aspect = imgRect.size.width/imgRect.size.height;
540
CGSize newSize = CGSizeMake(
541
MIN(TAPPITY_MAX_FEEDBACK_SIZE, TAPPITY_MAX_FEEDBACK_SIZE*aspect),
542
MIN(TAPPITY_MAX_FEEDBACK_SIZE, TAPPITY_MAX_FEEDBACK_SIZE/aspect));
544
img = [img scaledToSize: newSize];
549
546
NSData* imgData = UIImagePNGRepresentation(img);
552
[messenger sendData: imgData withIdentifier: kTapRawScreenshot];
550
NSString* rstr = NSStringFromCGRect(imgRect);
551
NSDictionary* imgDict = [NSDictionary dictionaryWithObjectsAndKeys: imgData, TapImageDataKey, rstr, TapImageRectKey, rstr, TapReferenceRectKey, nil];
552
NSData* data = [NSPropertyListSerialization dataFromPropertyList: imgDict format:NSPropertyListBinaryFormat_v1_0 errorDescription: nil];
553
[messenger sendData: data withIdentifier: kTapPlacedScreenshot];
641
642
// prep the ingredients
642
643
int bitsPerComponent = 8;
643
644
int bitsPerPixel = 32;
644
int bytesPerRow = 4 * 320;
645
int bytesPerRow = 4 * viewport[2];
645
646
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
646
647
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
647
648
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
649
650
// make the cgimage
650
CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
651
CGImageRef imageRef = CGImageCreate(viewport[2], viewport[3], bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
652
653
// then make the uiimage from that
653
654
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
657
static NSData* dataFromGL(void)
658
static NSData* dataFromGL(GLint* viewport)
659
NSInteger myDataLength = 320 * 480 * 4;
660
NSInteger myDataLength = viewport[2] * viewport[3] * 4;
661
662
NSMutableData* data = [NSMutableData dataWithLength: myDataLength];
663
664
// allocate array and read pixels into it.
664
665
void* buffer = [data mutableBytes];
665
glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
666
glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, buffer);
668
size_t bpr = 4*viewport[2];
668
669
void* rowbuf = calloc(1, bpr);
670
671
// swap image in Y
671
for (size_t i = 0; i < 480/2; ++i)
672
for (size_t i = 0; i < viewport[3]/2; ++i)
673
674
memcpy(rowbuf, buffer + i*bpr, bpr);
674
memcpy(buffer + i*bpr, buffer + (480-i-1)*bpr, bpr);
675
memcpy(buffer + (480-i-1)*bpr, rowbuf, bpr);
675
memcpy(buffer + i*bpr, buffer + (viewport[3]-i-1)*bpr, bpr);
676
memcpy(buffer + (viewport[3]-i-1)*bpr, rowbuf, bpr);
688
689
NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
689
690
if (lastGlUpdate + desiredFrameInterval < now)
691
NSData* rawData = dataFromGL();
692
UIImage* image = imageFromGLData(rawData);
694
NSData* data = UIImagePNGRepresentation(image);
696
[messenger sendData: data withIdentifier: kTapRawScreenshot];
694
glGetIntegerv(GL_VIEWPORT, viewport);
696
NSData* rawData = dataFromGL(viewport);
698
float aspect = (float)viewport[2]/(float)viewport[3];
699
CGSize newSize = CGSizeMake(
700
MIN(TAPPITY_MAX_FEEDBACK_SIZE, TAPPITY_MAX_FEEDBACK_SIZE*aspect),
701
MIN(TAPPITY_MAX_FEEDBACK_SIZE, TAPPITY_MAX_FEEDBACK_SIZE/aspect));
703
UIImage* image = [imageFromGLData(rawData, viewport) scaledToSize: newSize];
705
NSData* imgData = UIImagePNGRepresentation(image);
708
CGRect imgRect = CGRectMake(viewport[0], viewport[1], viewport[2], viewport[3]);
709
NSString* rstr = NSStringFromCGRect(imgRect);
710
NSDictionary* imgDict = [NSDictionary dictionaryWithObjectsAndKeys: imgData, TapImageDataKey, rstr, TapImageRectKey, NSStringFromCGRect(CGRectZero), TapReferenceRectKey, nil];
711
NSData* data = [NSPropertyListSerialization dataFromPropertyList: imgDict format:NSPropertyListBinaryFormat_v1_0 errorDescription: nil];
712
[messenger sendData: data withIdentifier: kTapPlacedScreenshot];
698
715
lastGlUpdate = now;
731
748
@synthesize locationDelegate, headingDelegate;
752
@implementation UIImage (ScreenImage)
754
+ (UIImage *)imageWithScreenContents
756
CGImageRef cgScreen = UIGetScreenImage();
758
UIImage *result = [UIImage imageWithCGImage:cgScreen];
759
CGImageRelease(cgScreen);
765
CGImageRef CreateScaledCGImageFromCGImage(CGImageRef image, CGSize size)
767
int width = size.width;
768
int height = size.height;
770
// Declare the number of bytes per row. Each pixel in the bitmap in this
771
// example is represented by 4 bytes; 8 bits each of red, green, blue, and
773
size_t bitmapBytesPerRow = (width * 4);
774
size_t bitmapByteCount = (bitmapBytesPerRow * height);
776
// Allocate memory for image data. This is the destination in memory
777
// where any drawing to the bitmap context will be rendered.
778
void* bitmapData = malloc( bitmapByteCount );
779
if (bitmapData == NULL)
784
// Create the bitmap context. We want pre-multiplied ARGB, 8-bits
785
// per component. Regardless of what the source image format is
786
// (CMYK, Grayscale, and so on) it will be converted over to the format
787
// specified here by CGBitmapContextCreate.
788
CGColorSpaceRef colorspace = CGImageGetColorSpace(image);
789
CGContextRef context = CGBitmapContextCreate (bitmapData,width,height,8,bitmapBytesPerRow,
790
colorspace,kCGImageAlphaPremultipliedFirst);
791
CGColorSpaceRelease(colorspace);
794
// error creating context
800
// Draw the image to the bitmap context. Once we draw, the memory
801
// allocated for the context for rendering will then contain the
802
// raw image data in the specified color space.
803
CGContextDrawImage(context, CGRectMake(0,0,width, height), image);
805
CGImageRef imgRef = CGBitmapContextCreateImage(context);
806
CGContextRelease(context);
813
- (UIImage*) scaledToSize: (CGSize) size
815
CGImageRef imgref = CreateScaledCGImageFromCGImage([self CGImage], size);
819
UIImage* img = [UIImage imageWithCGImage: imgref];
821
CGImageRelease(imgref);