@startuml
    namespace it.tidalwave.image.op {

        class RotateQuadrantOp [[RotateQuadrantOp.html]] {
            +RotateQuadrantOp(int)
            +getDegrees(): int
        }

        class CreateOp [[CreateOp.html]] {
            +CreateOp(int, int, DataType)
            +CreateOp(int, int, DataType, Color)
            +CreateOp(int, int, DataType, double...)
            +getWidth(): int
            +getHeight(): int
            +getDataType(): DataType
            +getFiller(): double[]
        }

        abstract class ImplementationFactory [[ImplementationFactory.html]] {
            +registerImplementation(Class<? extends Operation>, Class<? extends OperationImplementation>): void
            +unregisterImplementation(Class<? extends Operation>): void
            +findImplementation(Operation): OperationImplementation<Operation, Object>
            +createImageModel(BufferedImage): ImageModel
            {abstract} +canConvertFrom(Class): boolean
            {abstract} +convertFrom(Object): ImageModel
            {abstract} +canConvertTo(Class<?>): boolean
            {abstract} +convertTo(Object): Object
        }

        class ForceRenderingOp [[ForceRenderingOp.html]]

        class RotateOp [[RotateOp.html]] {
            +RotateOp(double)
            +RotateOp(double, Quality)
            +getDegrees(): double
            +getQuality(): Quality
        }

        class ConvolveOp [[ConvolveOp.html]] {
            +ConvolveOp(Kernel)
            +getKernel(): Kernel
        }

        class OptimizeOp [[OptimizeOp.html]] {
            +OptimizeOp(double, Quality)
            +OptimizeOp()
            +OptimizeOp(double)
            +getScale(): double
            +getQuality(): Quality
        }

        class ScaleOp [[ScaleOp.html]] {
            +ScaleOp(double, double, Quality)
            +ScaleOp(double)
            +ScaleOp(double, double)
            +ScaleOp(double, Quality)
            +getXScale(): double
            +getYScale(): double
            +getQuality(): Quality
        }

        class WriteOp [[WriteOp.html]] {
            +WriteOp(String, String)
            +WriteOp(String, String, ImageWriteParam)
            +WriteOp(String, Object)
            +WriteOp(String, Object, ImageWriteParam)
            +WriteOp(String, Object, ImageWriteParam, IIOMetadata)
            +getFormat(): String
            +getOutput(): Object
            +getImageWriteParam(): ImageWriteParam
            +getIIOMetadata(): IIOMetadata
        }

        class ReadOp [[ReadOp.html]] {
            +ReadOp(Object)
            +ReadOp(Object, Options...)
            +ReadOp(Object, int, Options...)
            +ReadOp(Object, int, int, Options...)
            +execute(): EditableImage
            {static} +createImageReader(File, PluginBlackList): ImageReader
            {static} +createImageReader(URL, PluginBlackList): ImageReader
        }

        interface it.tidalwave.image.op.ReadOp.Options [[ReadOp.Options.html]]

        class it.tidalwave.image.op.ReadOp.PluginBlackList [[ReadOp.PluginBlackList.html]] {
            +PluginBlackList(String...)
            +contains(String): boolean
        }

        enum it.tidalwave.image.op.ReadOp.Type [[ReadOp.Type.html]] {
            {static} +IMAGE
            {static} +THUMBNAIL
            {static} +METADATA
            {abstract} #read(ReadOp): EditableImage
        }

        class DrawOp [[DrawOp.html]] {
            +DrawOp(Executor)
        }

        interface it.tidalwave.image.op.DrawOp.Executor [[DrawOp.Executor.html]] {
            {abstract} +draw(Graphics2D, EditableImage): void
        }

        class ImplementationFactoryRegistry [[ImplementationFactoryRegistry.html]] {
            {static} +getDefault(): ImplementationFactoryRegistry
            +createImageModel(Object): ImageModel
            +findImplementation(Operation, ImageModel, boolean): OperationImplementation
        }

        class SizeOp [[SizeOp.html]] {
            +SizeOp(double)
            +getScale(): double
        }

        class CropOp [[CropOp.html]] {
            +CropOp(int, int, int, int)
            +getX(): int
            +getY(): int
            +getW(): int
            +getH(): int
        }

        class CreateFunctionOp [[CreateFunctionOp.html]] {
            +CreateFunctionOp(int, int, ImageFunction, DataType)
            +getImageFunction(): ImageFunction
        }

        class PaintOp [[PaintOp.html]] {
            +PaintOp(Graphics2D, int, int, int, int, Quality, PreviewSettings, ImageObserver)
            +PaintOp(Graphics2D, int, int, int, int, PreviewSettings, ImageObserver)
            +PaintOp(Graphics2D, int, int, PreviewSettings, ImageObserver)
            +PaintOp(Graphics2D, int, int, PreviewSettings)
            +PaintOp(Graphics2D, Point, PreviewSettings)
            +PaintOp(Graphics2D, int, int)
            +PaintOp(Graphics2D, Point)
            +getX(): int
            +getY(): int
            +getW(): int
            +getH(): int
            +getGraphics2D(): Graphics2D
            +getQuality(): Quality
            +getPreviewSettings(): PreviewSettings
            +getImageObserver(): ImageObserver
        }

        abstract class AbstractCreateOp [[AbstractCreateOp.html]]

        class PrintOp [[PrintOp.html]] {
            +PrintOp()
            +PrintOp(PrinterJob)
            +PrintOp(PrinterJob, PrintRequestAttributeSet)
            +PrintOp(PrinterJob, PrintRequestAttributeSet, boolean)
            +getPrinterJob(): PrinterJob
            +getPrintRequestAttributeSet(): PrintRequestAttributeSet
            +confirmPrint(): boolean
        }

        abstract class OperationImplementation<Op extends Operation, Model> [[OperationImplementation.html]] {
            +execute(EditableImage, Object): Object
            +canHandle(Op extends Operation): boolean
            #bind(Op extends Operation): void
            {abstract} #execute(Op extends Operation, EditableImage, Model): Model
        }

        class WrapOp [[WrapOp.html]] {
            +WrapOp(BufferedImage)
            +getSourceImage(): BufferedImage
        }

        class ConvertToBufferedImageOp [[ConvertToBufferedImageOp.html]] {
            +setBufferedImage(BufferedImage): void
            +getBufferedImage(): BufferedImage
        }

        abstract class Operation [[Operation.html]]

        class CaptureOp [[CaptureOp.html]] {
            +CaptureOp(Component)
            +getComponent(): Component
        }

        class MultiplyOp [[MultiplyOp.html]] {
            +MultiplyOp(EditableImage)
            +getOperand(): EditableImage
        }

        class ApplyUnsharpMaskOp [[ApplyUnsharpMaskOp.html]] {
            +ApplyUnsharpMaskOp(double, double, double)
            +getIntensity(): double
            +getRadius(): double
            +getThreshold(): double
        }

        class HistogramOp [[HistogramOp.html]] {
            +setHistogram(Histogram): void
            +getHistogram(): Histogram
        }

        class AddOp [[AddOp.html]] {
            +AddOp(EditableImage)
            +getOperand(): EditableImage
        }

        class AssignColorProfileOp [[AssignColorProfileOp.html]] {
        }

        class ConvertColorProfileOp [[ConvertColorProfileOp.html]] {
            +ConvertColorProfileOp(ICC_Profile)
        }

        enum it.tidalwave.image.op.ConvertColorProfileOp.RenderingIntent [[ConvertColorProfileOp.RenderingIntent.html]] {
            {static} +ABSOLUTE
            {static} +RELATIVE_COLORIMETRIC
            {static} +PERCEPTUAL
            {static} +SATURATION
        }

        class TranslateOp [[TranslateOp.html]] {
            +TranslateOp(float, float, InterpolationType)
            +getDeltaX(): float
            +getDeltaY(): float
        }

        enum it.tidalwave.image.op.TranslateOp.InterpolationType [[TranslateOp.InterpolationType.html]] {
            {static} +NEAREST
            {static} +BICUBIC
        }

        class ChangeBufferTypeOp [[ChangeBufferTypeOp.html]] {
            +ChangeBufferTypeOp(int)
            +getBufferType(): int
        }

        class ChangeFormatOp [[ChangeFormatOp.html]] {
            +ChangeFormatOp(DataType)
            +getType(): DataType
        }

        class PadPeriodicOp [[PadPeriodicOp.html]]

        class DivideByConstOp [[DivideByConstOp.html]] {
            +DivideByConstOp(float)
            +getDivider(): float
        }

        class BandMergeOp [[BandMergeOp.html]] {
            +BandMergeOp(EditableImage)
            +getOperand(): EditableImage
        }

        class PadBlackOp [[PadBlackOp.html]]

        class MagnitudeOp [[MagnitudeOp.html]]

        class ConjugateOp [[ConjugateOp.html]]

        class CenterShiftOp [[CenterShiftOp.html]]

        class MultiplyComplexOp [[MultiplyComplexOp.html]] {
            +MultiplyComplexOp(EditableImage)
            +getOperand(): EditableImage
        }

        class IDFTOp [[IDFTOp.html]]

        class DivideComplexOp [[DivideComplexOp.html]] {
            +DivideComplexOp(EditableImage)
            +getOperand(): EditableImage
        }

        class PadPeriodicPlanarOp [[PadPeriodicPlanarOp.html]]

        class DFTOp [[DFTOp.html]]

        Operation <|-- RotateQuadrantOp
        AbstractCreateOp <|-- CreateOp
        Operation <|-- ForceRenderingOp
        Operation <|-- RotateOp
        Operation <|-- ConvolveOp
        Operation <|-- OptimizeOp
        Operation <|-- ScaleOp
        Operation <|-- WriteOp
        Operation <|-- ReadOp
        ReadOp +-- it.tidalwave.image.op.ReadOp.Options
        it.tidalwave.image.op.ReadOp.Options <|.. it.tidalwave.image.op.ReadOp.PluginBlackList
        ReadOp +-- it.tidalwave.image.op.ReadOp.PluginBlackList
        it.tidalwave.image.op.ReadOp.PluginBlackList --> it.tidalwave.image.op.ReadOp.PluginBlackList: DEFAULT
        it.tidalwave.image.op.ReadOp.Options <|.. it.tidalwave.image.op.ReadOp.Type
        ReadOp +-- it.tidalwave.image.op.ReadOp.Type
        Operation <|-- DrawOp
        DrawOp --> it.tidalwave.image.op.DrawOp.Executor: executor
        DrawOp +-- it.tidalwave.image.op.DrawOp.Executor
        Operation <|-- SizeOp
        Operation <|-- CropOp
        CreateOp <|-- CreateFunctionOp
        Operation <|-- PaintOp
        Operation <|-- AbstractCreateOp
        Operation <|-- PrintOp
        AbstractCreateOp <|-- WrapOp
        Operation <|-- ConvertToBufferedImageOp
        AbstractCreateOp <|-- CaptureOp
        Operation <|-- MultiplyOp
        Operation <|-- ApplyUnsharpMaskOp
        Operation <|-- HistogramOp
        Operation <|-- AddOp
        Operation <|-- AssignColorProfileOp
        Operation <|-- ConvertColorProfileOp
        ConvertColorProfileOp +-- it.tidalwave.image.op.ConvertColorProfileOp.RenderingIntent
        Operation <|-- TranslateOp
        TranslateOp --> it.tidalwave.image.op.TranslateOp.InterpolationType: interpolationType
        TranslateOp +-- it.tidalwave.image.op.TranslateOp.InterpolationType
        Operation <|-- ChangeBufferTypeOp
        Operation <|-- ChangeFormatOp
        Operation <|-- PadPeriodicOp
        Operation <|-- DivideByConstOp
        Operation <|-- BandMergeOp
        Operation <|-- PadBlackOp
        Operation <|-- MagnitudeOp
        Operation <|-- ConjugateOp
        Operation <|-- CenterShiftOp
        Operation <|-- MultiplyComplexOp
        Operation <|-- IDFTOp
        Operation <|-- DivideComplexOp
        Operation <|-- PadPeriodicPlanarOp
        Operation <|-- DFTOp
    }

    center footer UMLDoclet 2.0.12, PlantUML 1.2020.16
@enduml
