<p>
Inverts the image's intensity:<br>
O<sub>x,y</sub> = max - I<sub>x,y</sub><br>
</p>

@param input  Input image. Not modified.
@param output If not null, the output image.  If null a new image is declared and returned.  Modified.
@return Output image.
556397
public static GrayU8 invert(GrayU8 input, int max , GrayU8 output) {
		output = InputSanityCheck.checkDeclare(input, output);

		ImplGrayImageOps.invert(input,max,output);

		return output;
	}
900709
public static void grayToBitmap( GrayU8 input , Bitmap output , byte[] storage) {
		if( output.getWidth() != input.getWidth() || output.getHeight() != input.getHeight() ) {
			throw new IllegalArgumentException("Image shapes are not the same");
		}
		
		if( storage == null )
			storage = declareStorage(output,null);
		
		ImplConvertBitmap.grayToArray(input, storage,output.getConfig());
		output.copyPixelsFromBuffer(ByteBuffer.wrap(storage));
	}
372748
public static String getImageFormat(ImageInputStream input) {
        Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
        String format = "unknown";
        if (readers.hasNext()) {
            ImageReader reader = readers.next();
            try {
                format = reader.getFormatName();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                reader.dispose();
            }
        }

        return format;
    }
282863
public static void rotateCCW( GrayS64 input , GrayS64 output ) {
		if( input.width != output.height || input.height != output.width )
			throw new IllegalArgumentException("Incompatible shapes");

		int w = input.width-1;

		for( int y = 0; y < input.height; y++ ) {
			int indexIn = input.startIndex + y*input.stride;
			for (int x = 0; x < input.width; x++) {
				output.unsafe_set(y,w-x,input.data[indexIn++]);
			}
		}
	}
171060
public static <T extends ImageGray<T>>
	void scaleImageUp(T input , T output , int scale, InterpolatePixelS<T> interp ) {
		if( scale <= 1 )
			throw new IllegalArgumentException("Scale must be >= 2");
		if( input instanceof GrayF32) {
			ImplPyramidOps.scaleImageUp((GrayF32)input,(GrayF32)output,scale,(InterpolatePixelS)interp);
		} else if( input instanceof GrayU8) {
			ImplPyramidOps.scaleImageUp((GrayU8)input,(GrayU8)output,scale,(InterpolatePixelS)interp);
		} else {
			throw new IllegalArgumentException("Image type not yet supported");
		}
	}
1083852
public static <T extends ImageGray<T>> void minimum(Planar<T> input, T output) {
		minimum(input, output, 0, input.getNumBands() - 1);
	}
1034672
public static void scaleDown2(GrayF32 input , GrayF32 output ) {
		
		output.reshape(input.width / 2, input.height / 2);

		for (int y = 0; y < output.height; y++) {
			int indexInput = 2*y*input.stride;
			int indexOutput = y*output.stride;
			for (int x = 0; x < output.width; x++,indexInput+=2) {
				output.data[indexOutput++] = input.data[indexInput];
			}
		}
	}
1353997
public static <T extends ImageGray<T>> void average(Planar<T> input, T output) {
		average(input, output, 0, input.getNumBands() - 1);
	}
19748
public static void imageToTensor(Planar<GrayF32> input , Tensor_F32 output , int miniBatch) {
		if( input.isSubimage())
			throw new RuntimeException("Subimages not accepted");
		if( output.getDimension() != 4 )
			throw new IllegalArgumentException("Output should be 4-DOF.  batch + spatial (channel,height,width)");
		if( output.length(1) != input.getNumBands() )
			throw new IllegalArgumentException("Number of bands don't match");
		if( output.length(2) != input.getHeight() )
			throw new IllegalArgumentException("Spatial height doesn't match");
		if( output.length(3) != input.getWidth() )
			throw new IllegalArgumentException("Spatial width doesn't match");

		for (int i = 0; i < input.getNumBands(); i++) {
			GrayF32 band = input.getBand(i);
			int indexOut = output.idx(miniBatch,i,0,0);

			int length = input.width*input.height;
			System.arraycopy(band.data, 0,output.d,indexOut,length);
		}
	}
811389
public static void nv21ToBoof(byte[] data, int width, int height, ImageBase output) {

		if( output instanceof Planar) {
			Planar ms = (Planar) output;

			if (ms.getBandType() == GrayU8.class) {
				ConvertNV21.nv21TPlanarRgb_U8(data, width, height, ms);
			} else if (ms.getBandType() == GrayF32.class) {
				ConvertNV21.nv21ToPlanarRgb_F32(data, width, height , ms);
			} else {
				throw new IllegalArgumentException("Unsupported output band format");
			}
		} else if( output instanceof ImageGray) {
			if (output.getClass() == GrayU8.class) {
				nv21ToGray(data, width, height, (GrayU8) output);
			} else if (output.getClass() == GrayF32.class) {
				nv21ToGray(data, width, height, (GrayF32) output);
			} else {
				throw new IllegalArgumentException("Unsupported output type");
			}
		} else if( output instanceof ImageInterleaved ) {
			if( output.getClass() == InterleavedU8.class ) {
				ConvertNV21.nv21ToInterleaved(data, width, height, (InterleavedU8) output);
			} else if( output.getClass() == InterleavedF32.class ) {
				ConvertNV21.nv21ToInterleaved(data, width, height, (InterleavedF32) output);
			} else {
				throw new IllegalArgumentException("Unsupported output type");
			}
		} else {
			throw new IllegalArgumentException("Boofcv image type not yet supported");
		}
	}
281254
public static <T extends ImageBase<T>> void sharpen4(T input , T output ) {
		if( input instanceof Planar ) {
			Planar pi = (Planar)input;
			Planar po = (Planar)output;
			for (int i = 0; i < pi.getNumBands(); i++) {
				sharpen4(pi.getBand(i),po.getBand(i));
			}
		} else {
			if (input instanceof GrayU8) {
				EnhanceImageOps.sharpen4((GrayU8) input, (GrayU8) output);
			} else if (input instanceof GrayF32) {
				EnhanceImageOps.sharpen4((GrayF32) input, (GrayF32) output);
			} else {
				throw new IllegalArgumentException("Image type not supported. " + input.getClass().getSimpleName());
			}
		}
	}
379414
public static InterleavedF32 convert( Planar<GrayF32> input , InterleavedF32 output ) {
		if (output == null) {
			output = new InterleavedF32(input.width, input.height,input.getNumBands());
		} else {
			output.reshape(input.width,input.height,input.getNumBands());
		}

		if( BoofConcurrency.USE_CONCURRENT ) {
			ImplConvertImage_MT.convert(input,output);
		} else {
			ImplConvertImage.convert(input,output);
		}

		return output;
	}
604462
static public void naive4(GrayF32 _intensity , GrayS8 direction , GrayF32 output )
	{
		final int w = _intensity.width;
		final int h = _intensity.height;

		ImageBorder_F32 intensity = (ImageBorder_F32)FactoryImageBorderAlgs.value(_intensity, 0);

		BoofConcurrency.loopFor(0,h,y->{
			for( int x = 0; x < w; x++ ) {
				int dir = direction.get(x,y);
				int dx,dy;

				if( dir == 0 ) {
					dx = 1; dy = 0;
				} else if( dir == 1 ) {
					dx = 1; dy = 1;
				} else if( dir == 2 ) {
					dx = 0; dy = 1;
				} else {
					dx = 1; dy = -1;
				}

				float left = intensity.get(x-dx,y-dy);
				float middle = intensity.get(x,y);
				float right = intensity.get(x+dx,y+dy);

				// suppress the value if either of its neighboring values are more than or equal to it
				if( left > middle || right > middle ) {
					output.set(x,y,0);
				} else {
					output.set(x,y,middle);
				}
			}
		});

	}
215671
@Override
    public ImageSource apply(ImageSource input) {
        if (input.isGrayscale()) {
            return input;
        }
        if (!isAlgorithm) {
            double r, g, b, gray;

            for (int i = 0; i < EffectHelper.getSize(input); i++) {
                r = EffectHelper.getRed(i, input);
                g = EffectHelper.getGreen(i, input);
                b = EffectHelper.getBlue(i, input);
                int a = EffectHelper.getAlpha(i, input);

                gray = (r * redCoefficient + g * greenCoefficient + b * blueCoefficient);

                EffectHelper.setRGB(i, (int) gray, (int) gray, (int) gray, a, input);
            }
            return input;
        } else {
            return apply(input, grayscaleMethod);
        }
    }
123251
public static <T extends ImageGray<T>>
	void orderBandsIntoRGB(Planar<T> image , BufferedImage input ) {

		boolean swap = swapBandOrder(input);

		// Output formats are: RGB and RGBA

		if( swap ) {
			if( image.getNumBands() == 3 ) {
				int bufferedImageType = input.getType();
				if( bufferedImageType == BufferedImage.TYPE_3BYTE_BGR ||
						bufferedImageType == BufferedImage.TYPE_INT_BGR )
				{
					T tmp = image.getBand(0);
					image.bands[0] = image.getBand(2);
					image.bands[2] = tmp;
				}
			} else if( image.getNumBands() == 4 ) {
				T[] temp = (T[]) Array.newInstance(image.getBandType(),4);

				int bufferedImageType = input.getType();
				if( bufferedImageType == BufferedImage.TYPE_INT_ARGB ) {
					temp[0] = image.getBand(1);
					temp[1] = image.getBand(2);
					temp[2] = image.getBand(3);
					temp[3] = image.getBand(0);
				} else if( bufferedImageType == BufferedImage.TYPE_4BYTE_ABGR ) {
					temp[0] = image.getBand(3);
					temp[1] = image.getBand(2);
					temp[2] = image.getBand(1);
					temp[3] = image.getBand(0);
				}

				image.bands[0] = temp[0];
				image.bands[1] = temp[1];
				image.bands[2] = temp[2];
				image.bands[3] = temp[3];
			}
		}
	}
882830
public static BufferedImage getImage(InputStream input) throws IOException
    {
        final BufferedImage buffer = ImageIO.read(input);
        if (buffer == null)
        {
            throw new IOException("Invalid image !");
        }
        return copyImage(buffer);
    }
539513
public static void yu12ToBoof(byte[] data, int width, int height, ImageBase output) {

        if( output instanceof Planar) {
            Planar ms = (Planar) output;
            ms.reshape(width,height,3);

            if( BoofConcurrency.USE_CONCURRENT ) {
                if (ms.getBandType() == GrayU8.class) {
                    ImplConvertYV12_MT.yv12ToPlanarRgb_U8(data, ms);
                } else if (ms.getBandType() == GrayF32.class) {
                    ImplConvertYV12_MT.yv12ToPlanarRgb_F32(data, ms);
                } else {
                    throw new IllegalArgumentException("Unsupported output band format");
                }
            } else {
                if (ms.getBandType() == GrayU8.class) {
                    ImplConvertYV12.yv12ToPlanarRgb_U8(data, ms);
                } else if (ms.getBandType() == GrayF32.class) {
                    ImplConvertYV12.yv12ToPlanarRgb_F32(data, ms);
                } else {
                    throw new IllegalArgumentException("Unsupported output band format");
                }
            }
        } else if( output instanceof ImageGray) {
            if (output.getClass() == GrayU8.class) {
                yu12ToGray(data, width, height, (GrayU8) output);
            } else if (output.getClass() == GrayF32.class) {
                yu12ToGray(data, width, height, (GrayF32) output);
            } else {
                throw new IllegalArgumentException("Unsupported output type");
            }
        } else if( output instanceof ImageInterleaved ) {
            ((ImageMultiBand)output).reshape(width,height,3);

            if( BoofConcurrency.USE_CONCURRENT ) {
                if (output.getClass() == InterleavedU8.class) {
                    ImplConvertYV12_MT.yv12ToInterleaved(data, (InterleavedU8) output);
                } else if (output.getClass() == InterleavedF32.class) {
                    ImplConvertYV12_MT.yv12ToInterleaved(data, (InterleavedF32) output);
                } else {
                    throw new IllegalArgumentException("Unsupported output type");
                }
            } else {
                if (output.getClass() == InterleavedU8.class) {
                    ImplConvertYV12.yv12ToInterleaved(data, (InterleavedU8) output);
                } else if (output.getClass() == InterleavedF32.class) {
                    ImplConvertYV12.yv12ToInterleaved(data, (InterleavedF32) output);
                } else {
                    throw new IllegalArgumentException("Unsupported output type");
                }
            }
        } else {
            throw new IllegalArgumentException("Boofcv image type not yet supported");
        }
    }