Turning a grayscale image into a histogram of the intensity of the pixels of that image This is exercise 3.1.4. from the book Computer Science An Interdisciplinary Approach by Sedgewick &amp; Wayne:
Write a program that takes the name of a grayscale image file as a command-line argument and uses StdDraw to plot a histogram of the frequency of occurrence of each of the 256 grayscale intensities.
Here is my program:
import java.awt.Color;

public class ImageToHistogram
{
    public static double getIntensity(Color color) // this method produces monochrome luminance
    {
        int r = color.getRed();
        int g = color.getGreen();
        int b = color.getBlue();
        return 0.299*r + 0.587*g + 0.114*b;
    }
    public static double[][] convertPictureToArray(Picture picture)
    {
        int width = picture.width();
        int height = picture.height();
        double[][] pixels = new double[width][height];      
        for (int col = 0; col &lt; width; col++)
        {
            for (int row = 0; row &lt; height; row++)
            {
                Color color = picture.get(col,row);
                pixels[col][row] = getIntensity(color);
            }
        }
        return pixels;
    }
    public static void drawHistogram(double[][] a)
    {
        int m = a.length;
        int n = a[0].length;
        int pixels = m*n;
        int[] histogram = new int[256];
        StdDraw.setPenColor(StdDraw.BOOK_BLUE);
        for (int i = 0; i &lt; m; i++)
        {
            for (int j = 0; j &lt; n; j++)
            {
                int intensity = (int) a[i][j];
                histogram[intensity]++;
            }
        }
        StdDraw.setXscale(0,256);
        StdDraw.setYscale(0,pixels/20); // obtained &quot;20&quot; by experimentation
        StdDraw.enableDoubleBuffering();
        for (int i = 0; i &lt; 256; i++)
        {
            StdDraw.filledRectangle(i+0.5,histogram[i]/2,0.5,histogram[i]/2);
        }
        StdDraw.show();
    }
    public static void main(String[] args)
    {
        Picture picture = new Picture(args[0]);
        double[][] a = convertPictureToArray(picture);
        drawHistogram(a);
    }
}

StdDraw and Picture are simple APIs written by the authors of the book. I checked my program and it works. Here is one instance of it:
Input (Grayscale picture of Coleen Gray taken from Wikipedia):

Output:

I also tested the extreme cases of pure black and pure white images.
Is there any way that I can improve my program?
Thanks for your attention.
Clarification:
I used the preview of the image provided by Wikipedia with resolution of 800 by 933 and not the original image with resolution of 2000 by 2333.
JPG vs PNG
Somehow, your code seems to produce wrong results with the above JPG. When used with the same image converted to PNG, the histogram looks much better, and much closer to what Photoshop displays.
ImageIO.read(file) seems to not return the correct RGB values with the above JPG. It is outside of your code though, and seems to be called by Picture class.
As mentioned by @Nayuki, it seems to be a known bug/feature:

https://bugs.openjdk.java.net/browse/JDK-5051418
https://stackoverflow.com/questions/31312645/java-imageio-grayscale-png-issue
https://stackoverflow.com/questions/32583772/reading-grayscale-png-image-files-without-distortion

Double -&gt; int
getIntensity returns a double.
For example, getIntensity(new Color(1, 1, 1)) returns 0.9999999999999999, which is very close to 1.0 but strictly smaller than 1.0.
When you cast this double to an integer in int intensity = (int) a[i][j], it gets converted to 0, which isn't desired.
With your current code, the first histogram bins look like this:
[37509, 2429, 0, 3981, 0, 1763, 1757, 4131, 0, 2016, 4718, 0, 6498, 0, 3526, 7824, ...

If you replace the line with int intensity = (int) Math.round(a[i][j]);, the first bins look like this:
[32317, 5192, 2429, 2327, 1654, 1763, 1757, 2034, 2097, 2016, 2230, 2488, 2947, 3551, 3526, 3683, 4141, ...

Which should produce a smoother and more correct diagram.
As mentioned by @MarkRansom:

the goal should be to redistribute the values in a way that preserves
their overall distribution.

Rounding the doubles should work fine in the above case, because the values are very close to integers. In the general case, truncating might be preferred.