Created
April 24, 2014 13:57
-
-
Save randomsequence/11255547 to your computer and use it in GitHub Desktop.
UIImage - Mirror every other row & every other column. This produces an image with the same histogram as the source.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIImage+Scramble.m | |
// | |
// Created by Johnnie Walker on 24/04/2014. | |
// | |
#import "UIImage+Scramble.h" | |
@import Accelerate; | |
typedef u_int8_t Quantum; | |
typedef struct { | |
Quantum opacity, red, green, blue; | |
} PixelPacket; | |
CGContextRef bitmapContextFromImage(UIImage *image) { | |
CGSize size = CGSizeApplyAffineTransform(image.size, CGAffineTransformMakeScale(image.scale, image.scale)); | |
size_t width = (size_t) ceil(size.width); | |
size_t height = (size_t) ceil(size.height); | |
size_t rowBytes = (size_t) ceil(size.width) * 4 * sizeof(uint8_t); | |
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); | |
CGContextRef context = CGBitmapContextCreate(NULL, | |
width, | |
height, | |
8, | |
rowBytes, | |
colorSpace, | |
(CGBitmapInfo) kCGImageAlphaPremultipliedFirst); | |
CGColorSpaceRelease(colorSpace); | |
CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), image.CGImage); | |
return context; | |
} | |
typedef void (^PixelProcessor)(void *inputPixels, void *outputPixels, size_t width, size_t height, size_t rowBytes); | |
@implementation UIImage (Scramble) | |
- (UIImage *)processWithBlocks:(NSArray *)pixelProcessors { | |
CGContextRef inputContext = bitmapContextFromImage(self); | |
CGContextRef outputContext = bitmapContextFromImage(self); | |
size_t width = CGBitmapContextGetWidth(inputContext); | |
size_t height = CGBitmapContextGetHeight(inputContext); | |
size_t rowBytes = CGBitmapContextGetBytesPerRow(inputContext); | |
for (PixelProcessor pixelProcessor in pixelProcessors) { | |
CGContextRef tmp = inputContext; | |
inputContext = outputContext; | |
outputContext = tmp; | |
void *inputPixels = CGBitmapContextGetData(inputContext); | |
void *outputPixels = CGBitmapContextGetData(outputContext); | |
memcpy(outputPixels, inputPixels, height*rowBytes); | |
pixelProcessor(inputPixels, outputPixels, width, height, rowBytes); | |
} | |
CGContextRelease(inputContext); | |
CGImageRef imageRef = CGBitmapContextCreateImage(outputContext); | |
UIImage *processed = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; | |
CGImageRelease(imageRef); | |
CGContextRelease(outputContext); | |
return processed; | |
} | |
- (PixelProcessor)horizontalReflectProcessor:(size_t)lineSpacing { | |
NSParameterAssert(lineSpacing > 0); | |
PixelProcessor pixelProcessor = ^(void *inputPixels, void *outputPixels, size_t width, size_t height, size_t rowBytes) { | |
vImage_Buffer src; | |
src.width = width; | |
src.height = 1; | |
src.rowBytes = rowBytes; | |
vImage_Buffer dest; | |
dest.width = width; | |
dest.height = 1; | |
dest.rowBytes = rowBytes; | |
for (size_t y = 0; y < height; y += lineSpacing) { | |
src.data = inputPixels + (rowBytes * y); | |
dest.data = outputPixels + (rowBytes * y); | |
vImageHorizontalReflect_ARGB8888(&src, &dest, 0); | |
} | |
}; | |
return [pixelProcessor copy]; | |
} | |
- (PixelProcessor)verticalReflectProcessor:(size_t)columnSpacing { | |
NSParameterAssert(columnSpacing > 0); | |
PixelProcessor pixelProcessor = ^(void *inputPixels, void *outputPixels, size_t width, size_t height, size_t rowBytes) { | |
vImage_Buffer src; | |
src.width = 1; | |
src.height = height; | |
src.rowBytes = rowBytes; | |
vImage_Buffer dest; | |
dest.width = 1; | |
dest.height = height; | |
dest.rowBytes = rowBytes; | |
for (size_t x = 0; x < width; x += columnSpacing) { | |
src.data = inputPixels + (x * 4); | |
dest.data = outputPixels + (x * 4); | |
vImageVerticalReflect_ARGB8888(&src, &dest, 0); | |
} | |
}; | |
return [pixelProcessor copy]; | |
} | |
- (UIImage *)scrambledImage { | |
return [self processWithBlocks:@[ | |
[self horizontalReflectProcessor:2], | |
[self verticalReflectProcessor:2], | |
]]; | |
} | |
- (UIImage *)unscrambledImage { | |
return [self processWithBlocks:@[ | |
[self verticalReflectProcessor:2], | |
[self horizontalReflectProcessor:2], | |
]]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment