Compute the histogram of an image using vImageHistogramCalculation

I’m trying to compute the histogram of an image using vImage’s vImageHistogramCalculation_ARGBFFFF, but I’m getting a vImage_Error of type kvImageNullPointerArgument (error code a -21772).

Here’s my code:

  • How-to convert an iOS camera image to greyscale using the Accelerate Framework?
  • iOS Accelerate Framework vImage - Performance improvement?
  • - (void)histogramForImage:(UIImage *)image {
    
        //setup inBuffer
        vImage_Buffer inBuffer;
    
        //Get CGImage from UIImage
        CGImageRef img = image.CGImage;
    
        //create vImage_Buffer with data from CGImageRef
        CGDataProviderRef inProvider = CGImageGetDataProvider(img);
        CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
    
        //The next three lines set up the inBuffer object
        inBuffer.width = CGImageGetWidth(img);
        inBuffer.height = CGImageGetHeight(img);
        inBuffer.rowBytes = CGImageGetBytesPerRow(img);
    
        //This sets the pointer to the data for the inBuffer object
        inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
    
        //Prepare the parameters to pass to vImageHistogramCalculation_ARGBFFFF
        vImagePixelCount *histogram[4] = {0};
        unsigned int histogram_entries = 4;
        Pixel_F minVal = 0;
        Pixel_F maxVal = 255;
        vImage_Flags flags = kvImageNoFlags;
    
        vImage_Error error = vImageHistogramCalculation_ARGBFFFF(&inBuffer,
                                                                 histogram,
                                                                 histogram_entries,
                                                                 minVal,
                                                                 maxVal,
                                                                 flags);
        if (error) {
            NSLog(@"error %ld", error);
        }
    
        //clean up
        CGDataProviderRelease(inProvider);
    }
    

    I suspect it has something to do with my histogram parameter, which, according to the docs, is supposed to be “a pointer to an array of four histograms”. Am I declaring it correctly?

    Thanks.

    Solutions Collect From Internet About “Compute the histogram of an image using vImageHistogramCalculation”

    The trouble is that you’re not allocating space to hold the computed histograms. If you are only using the histograms locally, you can put them on the stack like so [note that I’m using eight bins instead of four, to make the example more clear]:

    // create an array of four histograms with eight entries each.
    vImagePixelCount histogram[4][8] = {{0}};
    // vImageHistogramCalculation requires an array of pointers to the histograms.
    vImagePixelCount *histogramPointers[4] = { &histogram[0][0], &histogram[1][0], &histogram[2][0], &histogram[3][0] };
    vImage_Error error = vImageHistogramCalculation_ARGBFFFF(&inBuffer, histogramPointers, 8, 0, 255, kvImageNoFlags);
    // You can now access bin j of the histogram for channel i as histogram[i][j].
    // The storage for the histogram will be cleaned up when execution leaves the
    // current lexical block.
    

    If you need the histograms to stick around outside the scope of your function, you’ll need to allocate space for them on the heap instead:

    vImagePixelCount *histogram[4];
    unsigned int histogramEntries = 8;
    histogram[0] = malloc(4*histogramEntries*sizeof histogram[0][0]);
    if (!histogram[0]) { // handle error however is appropriate }
    for (int i=1; i<4; ++i) { histogram[i] = &histogram[0][i*histogramEntries]; }
    vImage_Error error = vImageHistogramCalculation_ARGBFFFF(&inBuffer, histogram, 8, 0, 255, kvImageNoFlags);
    // You can now access bin j of the histogram for channel i as histogram[i][j].
    // Eventually you will need to free(histogram[0]) to release the storage.
    

    Hope this helps.