/*
|
* Copyright 2012 ZXing authors
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#import "ZXBitMatrix.h"
|
#import "ZXImage.h"
|
|
#if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR
|
#import <ImageIO/ImageIO.h>
|
#endif
|
|
@implementation ZXImage
|
|
- (ZXImage *)initWithCGImageRef:(CGImageRef)image {
|
if (self = [super init]) {
|
_cgimage = CGImageRetain(image);
|
}
|
|
return self;
|
}
|
|
- (ZXImage *)initWithURL:(NSURL const *)url {
|
if (self = [super init]) {
|
CGDataProviderRef provider = CGDataProviderCreateWithURL((__bridge CFURLRef)url);
|
|
if (provider) {
|
CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, 0);
|
|
if (source) {
|
_cgimage = CGImageSourceCreateImageAtIndex(source, 0, 0);
|
CFRelease(source);
|
}
|
|
CGDataProviderRelease(provider);
|
}
|
}
|
|
return self;
|
}
|
|
- (size_t)width {
|
return CGImageGetWidth(self.cgimage);
|
}
|
|
- (size_t)height {
|
return CGImageGetHeight(self.cgimage);
|
}
|
|
- (void)dealloc {
|
if (_cgimage) {
|
CGImageRelease(_cgimage);
|
}
|
}
|
|
+ (ZXImage *)imageWithMatrix:(ZXBitMatrix *)matrix {
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
|
|
CGFloat blackComponents[] = {0.0f, 1.0f};
|
CGColorRef black = CGColorCreate(colorSpace, blackComponents);
|
CGFloat whiteComponents[] = {1.0f, 1.0f};
|
CGColorRef white = CGColorCreate(colorSpace, whiteComponents);
|
|
CFRelease(colorSpace);
|
|
ZXImage *result = [self imageWithMatrix:matrix onColor:black offColor:white];
|
|
CGColorRelease(white);
|
CGColorRelease(black);
|
|
return result;
|
}
|
|
+ (ZXImage *)imageWithMatrix:(ZXBitMatrix *)matrix onColor:(CGColorRef)onColor offColor:(CGColorRef)offColor {
|
int8_t onIntensities[4], offIntensities[4];
|
|
[self setColorIntensities:onIntensities color:onColor];
|
[self setColorIntensities:offIntensities color:offColor];
|
|
int width = matrix.width;
|
int height = matrix.height;
|
int8_t *bytes = (int8_t *)malloc(width * height * 4);
|
for (int y = 0; y < height; y++) {
|
for (int x = 0; x < width; x++) {
|
BOOL bit = [matrix getX:x y:y];
|
for (int i = 0; i < 4; i++) {
|
int8_t intensity = bit ? onIntensities[i] : offIntensities[i];
|
bytes[y * width * 4 + x * 4 + i] = intensity;
|
}
|
}
|
}
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
CGContextRef c = CGBitmapContextCreate(bytes, width, height, 8, 4 * width, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
|
CFRelease(colorSpace);
|
CGImageRef image = CGBitmapContextCreateImage(c);
|
CFRelease(c);
|
free(bytes);
|
|
ZXImage *zxImage = [[ZXImage alloc] initWithCGImageRef:image];
|
|
CFRelease(image);
|
return zxImage;
|
}
|
|
+ (void)setColorIntensities:(int8_t *)intensities color:(CGColorRef)color {
|
memset(intensities, 0, 4);
|
|
size_t numberOfComponents = CGColorGetNumberOfComponents(color);
|
const CGFloat *components = CGColorGetComponents(color);
|
|
if (numberOfComponents == 4) {
|
for (int i = 0; i < 4; i++) {
|
intensities[i] = components[i] * 255;
|
}
|
} else if (numberOfComponents == 2) {
|
for (int i = 0; i < 3; i++) {
|
intensities[i] = components[0] * 255;
|
}
|
intensities[3] = components[1] * 255;
|
}
|
}
|
|
@end
|