У меня есть следующая проблема, и я пока не могу ее решить. Я работаю с XCode 3.2.5, разрабатывая для iOS 4+.
Я просто пытаюсь создать изображение заранее определенного размера, манипулирую пикселями на нем и затем показываю изображение в UIImageView. Мое представление состоит из простой кнопки, подключенной к IBAction под названием «buttonClicked» и UIImageView под названием «qrImage», установленного как «IBOutlet». Я использую следующий код:
Заголовочный файл: myClassViewController.h
#import
@interface myClassViewController : UIViewController
{
IBOutlet UIImageView *qrImage;
}
@property (nonatomic, retain) UIImageView *qrImage;
- (IBAction) buttonClicked;
- (UIImage*) drawQRImage;
@end
Главный файл myClassViewController.m
#import "myClassViewController.h"
#include
@implementation myClassViewController
@synthesize qrImage;
-(UIImage*) drawQRImage
{
// load Image
//
UIImage *image = [UIImage imageNamed:@"blank.png"];
CGImageRef imageRef = image.CGImage;
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
char *pixels = (char *)[data bytes];
unsigned long int startPixel, pixelNr;
// manipulate the individual pixels
//
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
//
// [...] deleted some unimportant code here
//
pixelNr = 10;
int red = pixelNr*3;
int green = pixelNr*3+1;
int blue = pixelNr*3+2;
// Set Pixel-Color Black
//
pixels[red] = 0;
pixels[green] = 0;
pixels[blue] = 0;
//
// [...] deleted some unimportant code here
//
// create a new image from the modified pixel data
//
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);
CGImageRef newImageRef = CGImageCreate (
width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorspace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// the modified image
//
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// cleanup
//
free(pixels);
//CGImageRelease(imageRef); // DO NOT RELEASE OR ON NEXT RUN NSData GETS EXC_BAD_ACCESS
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
CGImageRelease(newImageRef);
QRcode_free(qrCode);
QRinput_free(input);
[image release];
// return created Image
//
return newImage;
}
-(IBAction) buttonClicked
{
UIImage *createdUIImg = [self drawQRImage];
qrImage.image = createdUIImg;
}
Я надеюсь, что этот код говорит само за себя, если бы не здесь краткое описание:
A. При нажатии кнопки я вызываю метод drawQRImage, который вернет UIImage. манипулировать пикселями на нем, а затем показывать изображение в UIImageView. Мое представление состоит из простой кнопки, подключенной к IBAction под названием «buttonClicked» и UIImageView под названием «qrImage», установленного как «IBOutlet». Я использую следующий код:
Заголовочный файл: myClassViewController.h
#import
@interface myClassViewController : UIViewController
{
IBOutlet UIImageView *qrImage;
}
@property (nonatomic, retain) UIImageView *qrImage;
- (IBAction) buttonClicked;
- (UIImage*) drawQRImage;
@end
Главный файл myClassViewController.m
#import "myClassViewController.h"
#include
@implementation myClassViewController
@synthesize qrImage;
-(UIImage*) drawQRImage
{
// load Image
//
UIImage *image = [UIImage imageNamed:@"blank.png"];
CGImageRef imageRef = image.CGImage;
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
char *pixels = (char *)[data bytes];
unsigned long int startPixel, pixelNr;
// manipulate the individual pixels
//
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
//
// [...] deleted some unimportant code here
//
pixelNr = 10;
int red = pixelNr*3;
int green = pixelNr*3+1;
int blue = pixelNr*3+2;
// Set Pixel-Color Black
//
pixels[red] = 0;
pixels[green] = 0;
pixels[blue] = 0;
//
// [...] deleted some unimportant code here
//
// create a new image from the modified pixel data
//
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);
CGImageRef newImageRef = CGImageCreate (
width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorspace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// the modified image
//
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// cleanup
//
free(pixels);
//CGImageRelease(imageRef); // DO NOT RELEASE OR ON NEXT RUN NSData GETS EXC_BAD_ACCESS
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
CGImageRelease(newImageRef);
QRcode_free(qrCode);
QRinput_free(input);
[image release];
// return created Image
//
return newImage;
}
-(IBAction) buttonClicked
{
UIImage *createdUIImg = [self drawQRImage];
qrImage.image = createdUIImg;
}
Я надеюсь, что этот код говорит само за себя, если бы не здесь краткое описание:
A. При нажатии кнопки я вызываю метод drawQRImage, который вернет UIImage. манипулировать пикселями на нем, а затем показывать изображение в UIImageView. Мое представление состоит из простой кнопки, подключенной к IBAction под названием «buttonClicked» и UIImageView под названием «qrImage», установленного как «IBOutlet». Я использую следующий код:
Заголовочный файл: myClassViewController.h
#import
@interface myClassViewController : UIViewController
{
IBOutlet UIImageView *qrImage;
}
@property (nonatomic, retain) UIImageView *qrImage;
- (IBAction) buttonClicked;
- (UIImage*) drawQRImage;
@end
Главный файл myClassViewController.m
#import "myClassViewController.h"
#include
@implementation myClassViewController
@synthesize qrImage;
-(UIImage*) drawQRImage
{
// load Image
//
UIImage *image = [UIImage imageNamed:@"blank.png"];
CGImageRef imageRef = image.CGImage;
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
char *pixels = (char *)[data bytes];
unsigned long int startPixel, pixelNr;
// manipulate the individual pixels
//
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
//
// [...] deleted some unimportant code here
//
pixelNr = 10;
int red = pixelNr*3;
int green = pixelNr*3+1;
int blue = pixelNr*3+2;
// Set Pixel-Color Black
//
pixels[red] = 0;
pixels[green] = 0;
pixels[blue] = 0;
//
// [...] deleted some unimportant code here
//
// create a new image from the modified pixel data
//
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);
CGImageRef newImageRef = CGImageCreate (
width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorspace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// the modified image
//
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// cleanup
//
free(pixels);
//CGImageRelease(imageRef); // DO NOT RELEASE OR ON NEXT RUN NSData GETS EXC_BAD_ACCESS
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
CGImageRelease(newImageRef);
QRcode_free(qrCode);
QRinput_free(input);
[image release];
// return created Image
//
return newImage;
}
-(IBAction) buttonClicked
{
UIImage *createdUIImg = [self drawQRImage];
qrImage.image = createdUIImg;
}
Я надеюсь, что этот код говорит само за себя, если бы не здесь краткое описание:
A. При нажатии кнопки я вызываю метод drawQRImage, который вернет UIImage. m
#import "myClassViewController.h"
#include
@implementation myClassViewController
@synthesize qrImage;
-(UIImage*) drawQRImage
{
// load Image
//
UIImage *image = [UIImage imageNamed:@"blank.png"];
CGImageRef imageRef = image.CGImage;
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
char *pixels = (char *)[data bytes];
unsigned long int startPixel, pixelNr;
// manipulate the individual pixels
//
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
//
// [...] deleted some unimportant code here
//
pixelNr = 10;
int red = pixelNr*3;
int green = pixelNr*3+1;
int blue = pixelNr*3+2;
// Set Pixel-Color Black
//
pixels[red] = 0;
pixels[green] = 0;
pixels[blue] = 0;
//
// [...] deleted some unimportant code here
//
// create a new image from the modified pixel data
//
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);
CGImageRef newImageRef = CGImageCreate (
width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorspace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// the modified image
//
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// cleanup
//
free(pixels);
//CGImageRelease(imageRef); // DO NOT RELEASE OR ON NEXT RUN NSData GETS EXC_BAD_ACCESS
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
CGImageRelease(newImageRef);
QRcode_free(qrCode);
QRinput_free(input);
[image release];
// return created Image
//
return newImage;
}
-(IBAction) buttonClicked
{
UIImage *createdUIImg = [self drawQRImage];
qrImage.image = createdUIImg;
}
Надеюсь, этот код не требует пояснений, если бы не краткое описание:
A. При нажатии кнопки я вызываю метод drawQRImage, который вернет UIImage. m
#import "myClassViewController.h"
#include
@implementation myClassViewController
@synthesize qrImage;
-(UIImage*) drawQRImage
{
// load Image
//
UIImage *image = [UIImage imageNamed:@"blank.png"];
CGImageRef imageRef = image.CGImage;
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
char *pixels = (char *)[data bytes];
unsigned long int startPixel, pixelNr;
// manipulate the individual pixels
//
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
//
// [...] deleted some unimportant code here
//
pixelNr = 10;
int red = pixelNr*3;
int green = pixelNr*3+1;
int blue = pixelNr*3+2;
// Set Pixel-Color Black
//
pixels[red] = 0;
pixels[green] = 0;
pixels[blue] = 0;
//
// [...] deleted some unimportant code here
//
// create a new image from the modified pixel data
//
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL);
CGImageRef newImageRef = CGImageCreate (
width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorspace,
bitmapInfo,
provider,
NULL,
false,
kCGRenderingIntentDefault
);
// the modified image
//
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// cleanup
//
free(pixels);
//CGImageRelease(imageRef); // DO NOT RELEASE OR ON NEXT RUN NSData GETS EXC_BAD_ACCESS
CGColorSpaceRelease(colorspace);
CGDataProviderRelease(provider);
CGImageRelease(newImageRef);
QRcode_free(qrCode);
QRinput_free(input);
[image release];
// return created Image
//
return newImage;
}
-(IBAction) buttonClicked
{
UIImage *createdUIImg = [self drawQRImage];
qrImage.image = createdUIImg;
}
Надеюсь, этот код не требует пояснений, если бы не краткое описание:
A. При нажатии кнопки я вызываю метод drawQRImage, который вернет UIImage. B. Внутри drawQRImage я открываю PNG-файл, до сих пор он имел размер 210x210 и только белый фон. Ничего больше. Затем я манипулирую некоторыми пикселями на нем и «закрашиваю их в черный цвет». Текущий код должен установить номер пикселя. 11 черный. По завершении я возвращаю только что созданное изображение. C. Метод buttonClicked затем покажет это изображение внутри UIImageView.
В целом, на самом деле очень просто. Он также работает (почти) отлично. Но теперь я хочу внести некоторые изменения, но до сих пор не могу заставить их работать:
Изображение, которое я должен вернуть, не всегда имеет размер 210x210 пикселей, поэтому я должен иметь возможность изменить размер. Загрузка «пустого» PNG-файла и манипулирование его пикселями было единственным обходным решением, которое до сих пор мне удавалось работать. Более элегантным способом было бы создание пустого изображения с белым BG желаемого размера, которое я мог бы использовать в моем текущем методе. К сожалению, я пока ничего по этому поводу не нашел. Только при манипулировании пикселями на уже существующих изображениях. Вот как я придумал текущий обходной путь. Я уже пробовал вырезать для изменения размера по следующей ссылке: Правильное изменение размера UIImage
На кнопку можно нажать несколько раз, окрашенные пиксели также изменятся. Моя проблема сейчас в том, что у меня, похоже, утечка памяти, потому что я закомментировал строку
// CGImageRelease (imageRef);
Но если я выпущу UIImageRef «imageRef», я получу EXC_BAD_ACCESS-Error при повторном нажатии кнопки. Итак, я знаю, что это означает, что я пытаюсь получить доступ к уже выпущенному объекту. Но как я могу решить эту проблему, я не уверен, что все правильно понял. Я думал, что imageRef будет создан заново в начале метода "drawQRImage", и, следовательно, его освобождение не должно быть проблемой, когда я вызову метод в другой раз. Но похоже, что я ошибаюсь.
Мы ценим любую помощь!