/****************************************************************************** * Compilation: javac StdPicture.java * Execution: java StdPicture filename.jpg * Dependencies: Picture.java * ******************************************************************************/ package edu.princeton.cs.algs4; /** * The {@code StdPicture} class provides static methods for manipulating * the individual pixels of an image using the RGB color model. * You can either initialize a blank image (of a given dimension) or read an * image in a supported file format (typically JPEG, PNG, GIF, TIFF, and BMP). * This class also includes methods for displaying the image in a window * and saving it to a file. * *

* Use in the curriculum. * The {@code StdPicture} class is intended for early usage in the * curriculum, before objects. * The {@link Picture} class is an object-oriented version that supports * manipulating multiple pictures at the same time. * *

* Getting started. * To use this class, you must have {@code StdPicture} in your Java classpath. * Here are three possible ways to do this: *

* *

* As a test, cut-and-paste the following short program into your editor: *

 *   public class TestStdPicture {
 *       public static void main(String[] args) {
 *           StdPicture.read("https://introcs.cs.princeton.edu/java/stdlib/mandrill.jpg");
 *           StdPicture.show();
 *       }
 *   }
 *  
*

* If you compile and execute the program, you should see a picture of a mandrill * (a colorful monkey native to west-central Africa) in a window. * *

* Anatomy of an image. * An image is a width-by-height grid of pixels, with pixel (0, 0) * in the upper-left corner. * Each pixel has a color that is represented using the RGB color model, * which specifies the levels of red (R), green (G), and blue (B) * on an integer scale from 0 to 255. * *

* anatomy of an image *
* *

* Initializing the picture. * You can use the following methods to initialize the picture: *

*

* The first method reads an image in a supported file format * (typically JPEG, PNG, GIF, TIFF, and BMP) * and initializes the picture to that image. * The second method initializes a width-by-height * picture, with each pixel black. * *

* Getting and setting the colors of the individual pixels. * You can use the following methods to retrieve the RGB components * of a specified pixel: *

*

* The first three methods return the red, green, and blue components of pixel * (col, row). Each component is an integer between 0 and 255, * with 0 corresponding to the absence of that component and 255 corresponding * to full intensity of that component. * The last method sets the red, green, and blue components of pixel * (col, row) to the specified values. * *

Iterating over the pixels. * A common operation in image processing is to iterate over and process * all of the pixels in an image. * Here is a prototypical example that converts a color image * to grayscale, using the NTSC formula * Y = 0.299r + 0.587g + 0.114b. * Note that if the red, green, and blue components are all equal, * then the color is a shade of gray. *

 *  StdPicture.read("https://introcs.cs.princeton.edu/java/stdlib/mandrill.jpg");
 *  for (int col = 0; col < StdPicture.width(); col++) {
 *      for (int row = 0; row < StdPicture.height(); row++) {
 *          int r = StdPicture.getRed(col, row);
 *          int g = StdPicture.getGreen(col, row);
 *          int b = StdPicture.getBlue(col, row);
 *          int y = (int) (Math.round(0.299*r + 0.587*g + 0.114*b));
 *          StdPicture.setRGB(col, row, y, y, y);
 *      }
 *  }
 *  StdPicture.show();
 *  
* *

Transparency. * The {@code StdPicture} class supports transparent images, using the * ARGB color model. The following methods are useful for this: *

*

* The first method gets the alpha component of pixel (col, row). * The second methods sets the red, green, blue, and alpha components of * pixel (col, row). * The alpha value defines the transparency of a color, with 0 corresponding to * completely transparent and 255 to completely opaque. If transparency is not * explicitly used, the alpha value is 255. * *

Saving files. * The {@code StdPicture} class supports writing images to a supported * file format (typically JPEG, PNG, GIF, TIFF, and BMP). * You can save the picture to a file two method: *

* *

Alternatively, you can save the picture interactively * by using the menu option File → Save from the picture window. * *

File formats. * The {@code StdPicture} class supports reading and writing images to any of the * file formats supported by {@link javax.imageio} (typically JPEG, PNG, * GIF, TIFF, and BMP). * The file extensions corresponding to JPEG, PNG, GIF, TIFF, and BMP, * are {@code .jpg}, {@code .png}, {@code .gif}, {@code .tif}, * and {@code .bmp}, respectively. * The file formats JPEG and BMP do not support transparency. * *

Memory usage. * A W-by-H picture uses ~ 4 W H bytes of memory, * since the color of each pixel is encoded as a 32-bit int. * *

Additional documentation. * For additional documentation, see * Section 3.1 of * Computer Science: An Interdisciplinary Approach * by Robert Sedgewick and Kevin Wayne. * * @author Robert Sedgewick * @author Kevin Wayne */ public final class StdPicture { // the default picture width and height private static final int DEFAULT_SIZE = 512; // the underlying picture private static Picture picture = new Picture(DEFAULT_SIZE, DEFAULT_SIZE); // singleton pattern: client can't instantiate private StdPicture() { } /** * Initializes a {@code width}-by-{@code height} picture, with {@code width} columns * and {@code height} rows, where each pixel is black. * * @param width the width of the picture * @param height the height of the picture * @throws IllegalArgumentException if {@code width} is negative or zero * @throws IllegalArgumentException if {@code height} is negative or zero */ public static void init(int width, int height) { if (picture.isVisible()) { hide(); picture = new Picture(width, height); show(); } else { picture = new Picture(width, height); } } /** * Creates a {@code width}-by-{@code height} picture, with {@code width} columns * and {@code height} rows, where each pixel is black. * * @param width the width of the picture * @param height the height of the picture * @throws IllegalArgumentException if {@code width} is negative or zero * @throws IllegalArgumentException if {@code height} is negative or zero * @deprecated Replaced by {@link #init(int, int)}. */ @Deprecated public static void create(int width, int height) { init(width, height); } /** * Initializes the picture by reading a JPEG, PNG, GIF, BMP, or TIFF image * from a file or URL. * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif}, * {@code .bmp}, or {@code .tif}. * * @param filename the name of the file or URL * @throws IllegalArgumentException if cannot read image * @throws IllegalArgumentException if {@code name} is {@code null} */ public static void read(String filename) { Picture newPicture = new Picture(filename); // same dimension, so copy pixels instead of using new Picture and GUI if (newPicture.width() == picture.width() && newPicture.height() == newPicture.height()) { for (int col = 0; col < picture.width(); col++) { for (int row = 0; row < picture.height(); row++) { picture.setRGB(col, row, newPicture.getRGB(col, row)); } } } // different dimension, so need to use new Picture and GUI else if (picture.isVisible()) { hide(); picture = newPicture; show(); } // no GUI, so use the new Picture else { picture = newPicture; } } /** * Initializes the picture by reading an image from a file or URL. * * @param filename the name of the file or URL * @throws IllegalArgumentException if cannot read image * @throws IllegalArgumentException if {@code name} is {@code null} * @deprecated Replaced by {@link #read(String)}. */ @Deprecated public static void create(String filename) { read(filename); } /** * Displays the picture in a window on the screen. */ public static void show() { picture.show(); } /** * Hides the window on the screen containing the picture. */ public static void hide() { picture.hide(); } /** * Pauses for t milliseconds. This method is intended to support computer animation. * @param t number of milliseconds * @throws IllegalArgumentException if {@code t} is negative */ public static void pause(int t) { if (t < 0) throw new IllegalArgumentException("argument must be non-negative"); try { Thread.sleep(t); } catch (InterruptedException e) { System.out.println("Error sleeping"); } } /** * Returns the height of the picture. * * @return the height of the picture (in pixels) */ public static int height() { return picture.height(); } /** * Returns the width of the picture. * * @return the width of the picture (in pixels) */ public static int width() { return picture.width(); } /** * Returns the alpha component of the color of pixel ({@code col}, {@code row}). * * @param col the column index * @param row the row index * @return the alpha component of the color of pixel ({@code col}, {@code row}) * @throws IllegalArgumentException unless both {@code 0 <= col < width} and {@code 0 <= row < height} */ public static int getAlpha(int col, int row) { int rgb = picture.getRGB(col, row); return (rgb >> 24) & 0xFF; } /** * Returns the red component of the color of pixel ({@code col}, {@code row}). * * @param col the column index * @param row the row index * @return the red component of the color of pixel ({@code col}, {@code row}) * @throws IllegalArgumentException unless both {@code 0 <= col < width} and {@code 0 <= row < height} */ public static int getRed(int col, int row) { int rgb = picture.getRGB(col, row); return (rgb >> 16) & 0xFF; } /** * Returns the green component of the color of pixel ({@code col}, {@code row}). * * @param col the column index * @param row the row index * @return the green component of the color of pixel ({@code col}, {@code row}) * @throws IllegalArgumentException unless both {@code 0 <= col < width} and {@code 0 <= row < height} */ public static int getGreen(int col, int row) { int rgb = picture.getRGB(col, row); return (rgb >> 8) & 0xFF; } /** * Returns the blue component of the color of pixel ({@code col}, {@code row}). * * @param col the column index * @param row the row index * @return the blue component of the color of pixel ({@code col}, {@code row}) * @throws IllegalArgumentException unless both {@code 0 <= col < width} and {@code 0 <= row < height} */ public static int getBlue(int col, int row) { int rgb = picture.getRGB(col, row); return (rgb >> 0) & 0xFF; } /** * Sets the color of pixel ({@code col}, {@code row}) to given color. * * @param col the column index * @param row the row index * @param r the red component of the color * @param g the green component of the color * @param b the blue component of the color * @throws IllegalArgumentException unless both {@code 0 <= col < width} and {@code 0 <= row < height} * @throws IllegalArgumentException unless {@code 0 <= r < 256}, {@code 0 <= g < 256}, * and {@code 0 <= b < 256}. */ public static void setRGB(int col, int row, int r, int g, int b) { int a = 255; int rgb = (a << 24) | (r << 16) | (g << 8) | (b << 0); picture.setRGB(col, row, rgb); } /** * Sets the color of pixel ({@code col}, {@code row}) to given color. * * @param col the column index * @param row the row index * @param a the alpha component of the color * @param r the red component of the color * @param g the green component of the color * @param b the blue component of the color * @throws IllegalArgumentException unless both {@code 0 <= col < width} and {@code 0 <= row < height} * @throws IllegalArgumentException unless {@code 0 <= a < 256}, {@code 0 <= r < 256}, * {@code 0 <= g < 256}, and {@code 0 <= b < 256}. */ public static void setARGB(int col, int row, int a, int r, int g, int b) { int rgb = (a << 24) | (r << 16) | (g << 8) | (b << 0); picture.setRGB(col, row, rgb); } /** * Sets the title of this picture. * @param title the title * @throws IllegalArgumentException if {@code title} is {@code null} */ public static void setTitle(String title) { picture.setTitle(title); } /** * Saves the picture to a file in a supported file format * (typically JPEG, PNG, GIF, TIFF, and BMP). * The filetype extension must be {@code .jpg}, {@code .png}, {@code .gif}, * {@code .bmp}, or {@code .tif}. * If the file format does not support transparency (such as JPEG * or BMP), it will be converted to be opaque (with purely * transparent pixels converted to black). * * @param filename the name of the file * @throws IllegalArgumentException if {@code filename} is {@code null} * @throws IllegalArgumentException if {@code filename} is the empty string */ public static void save(String filename) { picture.save(filename); } /** * Unit tests this {@code StdPicture} data type. * Reads a picture specified by the command-line argument, * and shows it in a window on the screen. * * @param args the command-line arguments */ public static void main(String[] args) { StdPicture.read(args[0]); System.out.printf("%d-by-%d\n", picture.width(), picture.height()); StdPicture.show(); } } /****************************************************************************** * Copyright 2002-2022, Robert Sedgewick and Kevin Wayne. * * This file is part of algs4.jar, which accompanies the textbook * * Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne, * Addison-Wesley Professional, 2011, ISBN 0-321-57351-X. * http://algs4.cs.princeton.edu * * * algs4.jar is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * algs4.jar is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with algs4.jar. If not, see http://www.gnu.org/licenses. ******************************************************************************/