【问题标题】:Convert UIImage to uint8 array: iOS将 UIImage 转换为 uint8 数组:iOS
【发布时间】:2014-06-29 18:23:37
【问题描述】:

我们可以将 UIImage 转换为 uint8 字节数组吗?

我在这里尝试做的是——我有一个图像,我想将其转换为 8 位字节数组。我还需要这个用于 AES 256 加密。

其实我对这部分 iOS 完全陌生,所以需要基本的帮助。

【问题讨论】:

标签: ios uiimage bytearray aes


【解决方案1】:

这显示了如何访问图像并基于原始图像创建新图像(在本例中为一半大小):

- (UIImage*) halveImage:(UIImage*)sourceImage {

    // Compute the target size
    CGSize sourceSize = sourceImage.size;
    CGSize targetSize;
    targetSize.width = (int) (sourceSize.width / 2);
    targetSize.height = (int) (sourceSize.height / 2);

    // Access the source data bytes
    NSData* sourceData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(sourceImage.CGImage));
    unsigned char* sourceBytes = (unsigned char *)[sourceData bytes];

    // Some info we'll need later
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(sourceImage.CGImage);
    int bitsPerComponent = CGImageGetBitsPerComponent(sourceImage.CGImage);
    int bitsPerPixel = CGImageGetBitsPerPixel(sourceImage.CGImage);
    int __attribute__((unused)) bytesPerPixel = bitsPerPixel / 8;
    int sourceBytesPerRow = CGImageGetBytesPerRow(sourceImage.CGImage);
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(sourceImage.CGImage);

    assert(bytesPerPixel == 4);
    assert(bitsPerComponent == 8);

    // Bytes per row is (apparently) rounded to some boundary
    assert(sourceBytesPerRow >= ((int) sourceSize.width) * 4);
    assert([sourceData length] == ((int) sourceSize.height) * sourceBytesPerRow);

    // Allocate target data bytes
    int targetBytesPerRow = ((int) targetSize.width) * 4;
    // Algorigthm happier if bytes/row a multiple of 16
    targetBytesPerRow = (targetBytesPerRow + 15) & 0xFFFFFFF0;
    int targetBytesSize = ((int) targetSize.height) * targetBytesPerRow;
    unsigned char* targetBytes = (unsigned char*) malloc(targetBytesSize);
    UIImage* targetImage = nil;

    // Copy source to target, averaging 4 pixels into 1
    for (int row = 0; row < targetSize.height; row++) {
        unsigned char* sourceRowStart = sourceBytes + (2 * row * sourceBytesPerRow);
        unsigned char* targetRowStart = targetBytes + (row * targetBytesPerRow);
        for (int column = 0; column < targetSize.width; column++) {

            int sourceColumnOffset = 2 * column * 4;
            int targetColumnOffset = column * 4;

            unsigned char* sourcePixel = sourceRowStart + sourceColumnOffset;
            unsigned char* nextRowSourcePixel = sourcePixel + sourceBytesPerRow;
            unsigned char* targetPixel = targetRowStart + targetColumnOffset;

            uint32_t* sourceWord = (uint32_t*) sourcePixel;
            uint32_t* nextRowSourceWord = (uint32_t*) nextRowSourcePixel;
            uint32_t* targetWord = (uint32_t*) targetPixel;

            uint32_t sourceWord0 = sourceWord[0];
            uint32_t sourceWord1 = sourceWord[1];
            uint32_t sourceWord2 = nextRowSourceWord[0];
            uint32_t sourceWord3 = nextRowSourceWord[1];

            // This apparently bizarre sequence scales the data bytes by 4 so that when added together we'll get an average.  We do lose the least significant bits this way, and thus about half a bit of resolution.
            sourceWord0 = (sourceWord0 & 0xFCFCFCFC) >> 2;
            sourceWord1 = (sourceWord1 & 0xFCFCFCFC) >> 2;
            sourceWord2 = (sourceWord2 & 0xFCFCFCFC) >> 2;
            sourceWord3 = (sourceWord3 & 0xFCFCFCFC) >> 2;

            uint32_t resultWord = sourceWord0 + sourceWord1 + sourceWord2 + sourceWord3;
            targetWord[0] = resultWord;
        }
    }

    // Convert the bits to an image.  Supposedly CGCreateImage will dispose of the target bytes buffer.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, targetBytes, targetBytesSize, NULL);
    CGImageRef targetRef = CGImageCreate(targetSize.width, targetSize.height, bitsPerComponent, bitsPerPixel, targetBytesPerRow, colorSpace, bitmapInfo, provider, NULL, FALSE, kCGRenderingIntentDefault);
    targetImage = [UIImage imageWithCGImage:targetRef];

    // Clean up
    CGColorSpaceRelease(colorSpace);

    // Return result
    return targetImage;
}

【讨论】:

  • 我很抱歉在这里成为一个菜鸟,但我不确定这段代码到底在做什么:(你能在这里为我解释一下吗?
  • 鉴于 HotLicks 的声誉,我只能假设它完全按照您在问题中提出的要求。
  • @Shailesh - 您不需要了解“分配目标数据字节”和“将源复制到目标”部分,因为它正在执行您可能不感兴趣的转换。我包括了它们主要是为了演示访问数据。实际数据提取发生在“访问源数据字节”部分。
  • 好的@HotLicks:我明白了。我们可以将它转换成 NSData 吗?
  • 如果你仔细观察它正在产生一个 NSData 对象:NSData* sourceData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(sourceImage.CGImage));
猜你喜欢
  • 2016-07-24
  • 2017-04-01
  • 1970-01-01
  • 2019-10-20
  • 2016-06-19
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
相关资源
最近更新 更多