私は1つのアプリケーションを開発しています。画像をimageviews
変更する前に.SOを使用しているため、その画像をオブジェクトで取得し、別のオブジェクトと比較して、両方が同じかどうかを確認する必要があります。そこで、その方法を教えてください。UIImageview
UIimage
UIImage
19 に答える
まず画像データに変換してから比較する方法があります。
- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{
NSData *data1 = UIImagePNGRepresentation(image1);
NSData *data2 = UIImagePNGRepresentation(image2);
return [data1 isEqual:data2];
}
@Simonの回答のSwift実装:
func image(image1: UIImage, isEqualTo image2: UIImage) -> Bool {
let data1: NSData = UIImagePNGRepresentation(image1)!
let data2: NSData = UIImagePNGRepresentation(image2)!
return data1.isEqual(data2)
}
または、@nhgrif の提案に基づいて UIImage を拡張することによって:
import UIKit
extension UIImage {
func isEqualToImage(image: UIImage) -> Bool {
let data1: NSData = UIImagePNGRepresentation(self)!
let data2: NSData = UIImagePNGRepresentation(image)!
return data1.isEqual(data2)
}
}
両方を使用する場合[UIImage imageNamed:]
は を使用できますがisEqual:
、それ以外の場合はデータを比較できます。
私の好みの(Swift)ソリューション
import UIKit
func ==(lhs: UIImage, rhs: UIImage) -> Bool
{
guard let data1 = UIImagePNGRepresentation(lhs),
data2 = UIImagePNGRepresentation(rhs)
else { return false }
return data1.isEqual(data2)
}
正解は「どのような比較をしたいか」によって異なります。
- 最も簡単な方法は、データを比較することです。
- イメージが 1 つのローカル ファイルから作成されたかどうかを知りたい場合は、-isEqual: を使用できます (ただし、イメージ キャッシュが何らかの理由でクリアされた場合にどうなるかわからないため、危険な方法があります)。
- 難しい方法は、ピクセルごとの比較を提供することです(確かに、システムはより多くの時間を費やします)。法的な理由により、当社のライブラリからコードを提供することはできません:(
ただし、facebook の ios-snapshot-test-case プロジェクトの良い例をここで確認できます: link right to the needed file。パフォーマンス テストを使用して、処理時間を測定できます。
大正義のために、そこからコードを以下にコピーします。
- (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance
{
NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size.");
CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage));
CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
// The images have the equal size, so we could use the smallest amount of bytes because of byte padding
size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage));
size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow;
void *referenceImagePixels = calloc(1, referenceImageSizeBytes);
void *imagePixels = calloc(1, referenceImageSizeBytes);
if (!referenceImagePixels || !imagePixels) {
free(referenceImagePixels);
free(imagePixels);
return NO;
}
CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels,
referenceImageSize.width,
referenceImageSize.height,
CGImageGetBitsPerComponent(self.CGImage),
minBytesPerRow,
CGImageGetColorSpace(self.CGImage),
(CGBitmapInfo)kCGImageAlphaPremultipliedLast
);
CGContextRef imageContext = CGBitmapContextCreate(imagePixels,
imageSize.width,
imageSize.height,
CGImageGetBitsPerComponent(image.CGImage),
minBytesPerRow,
CGImageGetColorSpace(image.CGImage),
(CGBitmapInfo)kCGImageAlphaPremultipliedLast
);
if (!referenceImageContext || !imageContext) {
CGContextRelease(referenceImageContext);
CGContextRelease(imageContext);
free(referenceImagePixels);
free(imagePixels);
return NO;
}
CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage);
CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage);
CGContextRelease(referenceImageContext);
CGContextRelease(imageContext);
BOOL imageEqual = YES;
// Do a fast compare if we can
if (tolerance == 0) {
imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0);
} else {
// Go through each pixel in turn and see if it is different
const NSInteger pixelCount = referenceImageSize.width * referenceImageSize.height;
FBComparePixel *p1 = referenceImagePixels;
FBComparePixel *p2 = imagePixels;
NSInteger numDiffPixels = 0;
for (int n = 0; n < pixelCount; ++n) {
// If this pixel is different, increment the pixel diff count and see
// if we have hit our limit.
if (p1->raw != p2->raw) {
numDiffPixels ++;
CGFloat percent = (CGFloat)numDiffPixels / pixelCount;
if (percent > tolerance) {
imageEqual = NO;
break;
}
}
p1++;
p2++;
}
}
free(referenceImagePixels);
free(imagePixels);
return imageEqual;
}
手短で迅速な解決策
extension UIImage: Equatable {
static func ==(lhs: UIImage, rhs: UIImage) -> Bool {
return lhs.pngData() == rhs.pngData()
}
}
かなり高価になるため、UIImageデータの比較についてはわかりません。あなたができることは、Uimageをサブクラス化し、タグプロパティを自分で追加してから、画像を変更する前にタグを比較することです。割当
画像の名前を 1 つ知っていれば、役に立ちます....
CGImageRef cgImage = [imageView.image CGImage];
if (cgImage == [UIImage imageNamed:@"imagename.png"].CGImage) {
// True Statement
}
Objective-C で isEqualToData メソッドを使用する必要があります。Apple のドキュメントには、次のように記載されています。
Two data objects are equal if they hold the same number of bytes, and if the bytes at the same position in the objects are the same.
- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{
NSData *data1 = UIImagePNGRepresentation(image1);
NSData *data2 = UIImagePNGRepresentation(image2);
return [data1 isEqualToData:data2];
}
「タグ」プロパティを使用して、プログラムの後半の段階でオブジェクトを識別することもできます。整数値を設定するだけで準備完了です