iOS - Как преобразовать изображение png в 4-битное растровое изображение в оттенках серого?

Это тот случай,

Я хочу использовать iOS6+ для преобразования изображения PNG (или JPEG) в 4-битное растровое изображение в градациях серого, для этого 4-битного растрового изображения необходимо поддерживать только 16 оттенков серого.

Как я могу сделать ?

Заранее спасибо.


person Kuo Ming Lin    schedule 01.10.2013    source источник


Ответы (2)


Вы можете преобразовать его в 8-битное изображение в градациях серого (см. Преобразование UIImage в 8-битное). или см. ссылку, которой поделился Spynet, которая включает другие перестановки), но мне не удалось адаптировать это для создания 4-битного растрового изображения в градациях серого (CGBitmapContextCreate жалуется, что это недопустимая комбинация параметров). Кажется, что теоретически это должно быть возможно (есть 4-битные форматы, перечисленные в разделе CVPixelBuffer типы форматов пикселей), но мне не удалось заставить его работать с этим методом.

person Rob    schedule 01.10.2013
comment
Спасибо за ваш ответ, я проверю. - person Kuo Ming Lin; 01.10.2013

Я нашел решение для преобразования изображения в 4-битную шкалу серого, такой код.

-(UIImage *)grayscaleImageAt4Bits:(UIImage *)_image
{
    CGImageRef imageRef = [_image CGImage];
    int width  = CGImageGetWidth(imageRef);
    int height = CGImageGetHeight(imageRef);
    NSInteger _bitsPerComponent = 8;
    NSInteger _bytesPerPixel    = 1;
    NSInteger _bytesPerRow      = _bytesPerPixel * width;
    CGColorSpaceRef colorSpace  = CGColorSpaceCreateDeviceGray();
    uint8_t *sourceData = malloc(height * width * _bytesPerPixel);
    CGContextRef context = CGBitmapContextCreate(sourceData,
                                                 width,
                                                 height,
                                                 _bitsPerComponent,
                                                 _bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaNone);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

    const int _redIndex   = 0;
    const int _greenIndex = 1;
    const int _blueIndex  = 2;
    int _byteIndex  = 0;
    int _bitIndex   = 0;
    uint8_t *_newImageBits = malloc( height * width * _bytesPerPixel / 2 );
    for(int j=0;j<height;j++)
    {
        for(int k=0;k<width;k++)
        {
            UInt8 _perPixel = _newImageBits[_byteIndex];
            UInt8 *rgbPixel = (UInt8 *) &sourceData[j * width + k];
            int _red   = rgbPixel[_redIndex];
            int _green = rgbPixel[_greenIndex];
            int _blue  = rgbPixel[_blueIndex];
            int _pixelGrayValue = (_green + _red + _blue) / 16;
            UInt8 _pixelByte = (UInt8)_pixelGrayValue;
            _perPixel |= (_pixelByte<<4);
            _newImageBits[_byteIndex] = _perPixel;
            _bitIndex += 4;
            if(_bitIndex > 7)
            {
                _byteIndex++;
                _bitIndex = 0;
            }
        }
    }
    free(sourceData);
    //Direct fetch Bytes of 4-Bits, then you can use this Bytes ( sourceData ) to do something.
    sourceData = _newImageBits;
    CGImageRef cgImage  = CGBitmapContextCreateImage(context);
    UIImage *_grayImage = [UIImage imageWithCGImage:cgImage];
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    //Convert to NSData type, then you can use this NSData ( _sourceImageData ) to do something.
    NSData *_sourceImageData  = [NSData dataWithBytes:sourceData length:(width * height * _bytesPerPixel)];
    free(sourceData);
    return _grayImage;
}

И iOS поддерживает только наименьший 8-битный цвет для отображения, поэтому 4-битные данные передаются только в текстуру openGL для использования.

person Kuo Ming Lin    schedule 10.10.2013
comment
iOS 8 теперь выдает предупреждение: implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGBitmapInfo' (aka 'enum CGBitmapInfo') - person Jasper Blues; 19.07.2015