All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.earth.worldwind.render.image.ImageSource.kt Maven / Gradle / Ivy

Go to download

The WorldWind Kotlin SDK (WWK) includes the library, examples and tutorials for building multiplatform 3D virtual globe applications for Android, Web and Java.

There is a newer version: 1.5.23
Show newest version
package earth.worldwind.render.image

import dev.icerock.moko.resources.ImageResource
import earth.worldwind.util.AbstractSource
import earth.worldwind.util.Logger.ERROR
import earth.worldwind.util.Logger.logMessage
import java.awt.Color
import java.awt.image.BufferedImage
import java.io.File
import java.net.MalformedURLException
import java.net.URL

/**
 * Provides a mechanism for specifying images from a variety of sources. ImageSource retains the image source on behalf
 * of the caller, making this information available to WorldWind components that load images on the caller's behalf.
 * 
* ImageSource supports following source types: * - Uniform Resource Locator [URL] * - Local image [File] * - [BufferedImage] object * - WorldWind [ImageSource.ImageFactory] * - Multi-platform resource identifier *
* ImageSource instances are intended to be used as a key into a cache or other data structure that enables sharing of * loaded images. BufferedImages and WorldWind image factories are compared by reference. File paths and URLs with the * same string representation considered equals. */ actual open class ImageSource protected constructor(source: Any): AbstractSource(source) { actual companion object { protected val lineStippleFactories = mutableMapOf() /** * Constructs an image source with a multi-platform resource identifier. * * @param imageResource the multi-platform resource identifier * * @return the new image source */ @JvmStatic actual fun fromResource(imageResource: ImageResource) = ImageSource(imageResource) /** * Constructs an image source with a [BufferedImage]. * * @param image the [BufferedImage] to use as an image source * * @return the new image source */ @JvmStatic fun fromImage(image: BufferedImage) = ImageSource(image) /** * Constructs an image source with a [ImageFactory]. WorldWind shapes configured with an image factory image source * construct their images lazily, typically when the shape becomes visible on screen. * * @param factory the [ImageFactory] to use as an image source * * @return the new image source */ @JvmStatic fun fromImageFactory(factory: ImageFactory) = ImageSource(factory) /** * Constructs an image source with a [File]. * * @param file the source [File] to use as an image source * * @return the new image source */ @JvmStatic fun fromFile(file: File): ImageSource { require(file.isFile) { logMessage(ERROR, "ImageSource", "fromFile", "invalidFile") } return ImageSource(file) } /** * Constructs an image source with a file path. * * @param filePath complete path name to the file * * @return the new image source */ @JvmStatic fun fromFilePath(filePath: String) = fromFile(File(filePath)) /** * Constructs an image source with an [URL]. * * @param url Uniform Resource Locator * * @return the new image source */ @JvmStatic fun fromUrl(url: URL) = ImageSource(url) /** * Constructs an image source with a URL string. * * @param urlString complete URL string * * @return the new image source */ @JvmStatic actual fun fromUrlString(urlString: String) = try { fromUrl(URL(urlString)) } catch (e: MalformedURLException) { logMessage(ERROR, "ImageSource", "fromUrlString", "invalidUrlString", e) throw e } /** * Constructs an image source with a line stipple pattern. The result is a one-dimensional image with pixels * representing the specified stipple factor and stipple pattern. Line stipple images can be used for displaying * dashed shape outlines. See [earth.worldwind.shape.ShapeAttributes.outlineImageSource]. * * @param factor specifies the number of times each bit in the pattern is repeated before the next bit is used. For * example, if the factor is 3, each bit is repeated three times before using the next bit. The * specified factor must be either 0 or an integer greater than 0. A factor of 0 indicates no * stippling. * @param pattern specifies a number whose lower 16 bits define a pattern of which pixels in the image are white and * which are transparent. Each bit corresponds to a pixel, and the pattern repeats after every n*16 * pixels, where n is the factor. For example, if the factor is 3, each bit in the pattern is * repeated three times before using the next bit. * * @return the new image source */ @JvmStatic actual fun fromLineStipple(factor: Int, pattern: Short): ImageSource { val lFactor = factor.toLong() and 0xFFFFFFFFL val lPattern = pattern.toLong() and 0xFFFFL val key = lFactor shl 32 or lPattern val factory = lineStippleFactories[key] ?: LineStippleImageFactory(factor, pattern).also { lineStippleFactories[key] = it } return ImageSource(factory) } /** * Constructs an image source with a generic [Any] instance. The source may be any non-null object. This is * equivalent to calling one of ImageSource's type-specific factory methods when the source is a recognized type. * * @param source the generic source * * @return the new image source */ @JvmStatic actual fun fromUnrecognized(source: Any) = when (source) { is ImageResource -> fromResource(source) is BufferedImage -> fromImage(source) is ImageFactory -> fromImageFactory(source) is File -> fromFile(source) is URL -> fromUrl(source) else -> ImageSource(source) } } /** * Indicates whether this image source is a multi-platform resource. */ val isResource get() = source is ImageResource /** * Indicates whether this image source is a [BufferedImage]. */ val isImage get() = source is BufferedImage /** * Indicates whether this image source is an image factory. */ val isImageFactory get() = source is ImageFactory /** * Indicates whether this image source is a [File]. */ val isFile get() = source is File /** * Indicates whether this image source is an [URL]. */ val isUrl get() = source is URL /** * @return the source multi-platform resource identifier. Call isResource to determine whether the source is an * Multi-platform resource. */ fun asResource() = source as ImageResource /** * @return the source [BufferedImage]. Call [isImage] to determine whether the source is a [BufferedImage]. */ fun asImage() = source as BufferedImage /** * @return the source [ImageFactory]. Call isImageFactory to determine whether the source is an image * factory. */ fun asImageFactory() = source as ImageFactory /** * @return the source [File]. Call [isFile] to determine whether the source is a [File]. */ fun asFile() = source as File /** * @return the source [URL]. Call [isUrl] to determine whether the source is an [URL]. */ fun asUrl() = source as URL override fun toString() = when (source) { is ImageResource -> "Resource: $source" is BufferedImage -> "BufferedImage: $source" is ImageFactory -> "ImageFactory: $source" is File -> "File: $source" is URL -> "URL: $source" else -> super.toString() } /** * Factory for delegating construction of images. WorldWind shapes configured with a ImageFactory construct * their images lazily, typically when the shape becomes visible on screen. */ interface ImageFactory { /** * Image factory runs asynchronously by default, but this behavior can be changed by overriding current attribute. */ val isRunBlocking: Boolean get() = false /** * Returns the image associated with this factory. This method may be called more than once and may be called * from a non-UI thread. Each invocation must return an image with equivalent content, dimensions and * configuration. Any side effects applied to the WorldWind scene by the factory must be executed on the main * thread. * * @return the image associated with this factory */ suspend fun createImage(): BufferedImage? } protected open class LineStippleImageFactory(protected val factor: Int, protected val pattern: Short): ImageFactory { override suspend fun createImage(): BufferedImage { val pixels = if (factor <= 0) { IntArray(16) { Color.WHITE.rgb } } else { IntArray(factor * 16).also { pixels -> var pixel = 0 for (bi in 0..15) { val bit = pattern.toInt() and (1 shl bi) val color = if (bit == 0) 0 else Color.WHITE.rgb for (fi in 0 until factor) pixels[pixel++] = color } } } return BufferedImage(pixels.size, 1, BufferedImage.TYPE_INT_ARGB).apply { setRGB(0, 0, pixels.size, 1, pixels, 0, pixels.size) } } override fun toString() = "LineStippleBitmapFactory factor=$factor, pattern=" + (pattern.toInt() and 0xFFFF).toString(16).uppercase() } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy