В течение многих лет я пытался убедить людей, что они должны были записать модульный тест на свой код. Записали ли они тесты сначала (как в TDD) или после того, как они кодировали функциональность, я всегда пытался объяснить их все преимущества наличия модульных тестов на код. Едва ли кто-то не согласился со мной. Вы не можете не согласиться с чем-то, что очевидно, и любой умный человек будет видеть преимущества модульного теста и TDD.
проблема с поблочным тестированием состоит в том, что оно требует изменения в поведении, и очень трудно изменить поведение людей. Со словами Вы заставите много людей соглашаться с Вами, но Вы не будете видеть многих изменений в способе, которым они делают вещи.
необходимо убедить людей путем выполнения. Ваш личный успех притянет больше людей, чем все аргументы, которые Вы можете иметь. Если они будут видеть, что Вы только говорите о модульном тесте или TDD, но Вы делаете то, что Вы проповедуете, и Вы успешны, люди попытаются подражать Вам.
необходимо также взять на себя ведущую роль, потому что никакой модульный тест записей не исправляется в первый раз, таким образом, Вы, возможно, должны тренировать их о том, как сделать это, покажите им путь и инструменты, доступные им. Помогите им, в то время как они пишут свои первые тесты, рассматривают тесты, они пишут самостоятельно и показывают им приемы, идиомы и шаблоны, которые Вы изучили через свои собственные события. Через некоторое время они начнут видеть преимущества самостоятельно, и они изменят свое поведение для слияния модульных тестов или TDD на их панель инструментов.
Изменений не произойдет за ночь, но с определенным терпением, можно достигнуть цели.
Посмотрим, работает ли это лучше таким образом:
+ (UIImage*)maskImage:(UIImage*)image withMask:(UIImage*)maskImage {
UIGraphicsBeginImageContext(image.size);
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef), CGImageGetHeight(maskRef), CGImageGetBitsPerComponent(maskRef), CGImageGetBitsPerPixel(maskRef), CGImageGetBytesPerRow(maskRef), CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask(image.CGImage, mask);
UIImage* result = [UIImage imageWithData:UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext())];
UIGraphicsEndImageContext();
CGImageRelease(mask);
CGImageRelease(masked);
return result;
}
Следует отметить один важный момент: блокируются не методы , а экземпляры объектов .
Когда вы вызываете alphonse .bow (gaston)
, он пытается получить блокировку на alphonse
. Как только блокировка установлена, он печатает сообщение, затем вызывает gaston.bowBack (alphonse)
. На этом этапе он пытается получить блокировку на Gaston
. Как только блокировка установлена, он печатает сообщение, затем снимает блокировку и, наконец, снимает блокировку на alphonse
.
В тупиковой ситуации блокировки устанавливаются в таком порядке, что нет возможности для любой поток для продолжения.
alphonse
gaston
CGImageMaskCreate
не делает то, что вы ожидаете. В частности:
Для масок изображения, которые имеют 2, 4 или 8 битов на компонент, каждый компонент отображается в диапазон от 0 до 1 путем масштабирования с использованием этой формулы:
1 / (2 ^ бит на компонент - 1)
Например, 4-битная маска имеет значения в диапазоне от 0 до 15. Эти значения масштабируются на 1/15, так что каждый компонент находится в диапазоне от 0 до 1. Значения компонентов, масштабируемые до 0 или 1, ведут себя как так же, как они ведут себя для 1-битных масок изображений. Значения, которые масштабируются от 0 до 1, действуют как обратная альфа. То есть цвет заливки окрашивается так, как если бы он имел альфа-значение (1 - MaskSampleValue). Например, если значение выборки 8-битной маски масштабируется до 0,8, текущий цвет заливки окрашивается так, как если бы он имел альфа-значение 0,2, то есть (1–0,8).
Я предполагаю, что функция переинтерпретирует ваши данные RGB в этом другом формате, который искажает значения цвета. Вы пробовали использовать маску CGImage напрямую?
Быстрое редактирование: то, что я имею в виду под «напрямую», - это просто написать
+ (UIImage*)maskImage:(UIImage*)image withMask:(UIImage*)maskImage
{
CGImageRef masked = CGImageCreateWithMask([image CGImage], [maskImage CGImage]);
return [UIImage imageWithCGImage:masked];
}
Как вы обнаружили, то, как вы сохраняете файл, может иметь значение, потому что Core Graphics очень требовательна к формату битов, которые она использует для маскирования.
Я обнаружил, что лучший и самый надежный способ сгенерировать маску изображения из произвольного изображения - это сделать следующее:
Попробуйте эту функцию:
CGImageRef createMaskWithImage(CGImageRef image)
{
int maskWidth = CGImageGetWidth(image);
int maskHeight = CGImageGetHeight(image);
// round bytesPerRow to the nearest 16 bytes, for performance's sake
int bytesPerRow = (maskWidth + 15) & 0xfffffff0;
int bufferSize = bytesPerRow * maskHeight;
// allocate memory for the bits
CFMutableDataRef dataBuffer = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFDataSetLength(dataBuffer, bufferSize);
// the data will be 8 bits per pixel, no alpha
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceGray();
CGContextRef ctx = CGBitmapContextCreate(CFDataGetMutableBytePtr(dataBuffer),
maskWidth, maskHeight,
8, bytesPerRow, colourSpace, kCGImageAlphaNone);
// drawing into this context will draw into the dataBuffer.
CGContextDrawImage(ctx, CGRectMake(0, 0, maskWidth, maskHeight), image);
CGContextRelease(ctx);
// now make a mask from the data.
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(dataBuffer);
CGImageRef mask = CGImageMaskCreate(maskWidth, maskHeight, 8, 8, bytesPerRow,
dataProvider, NULL, FALSE);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colourSpace);
CFRelease(dataBuffer);
return mask;
}