in plot-base/src/commonMain/kotlin/org/jetbrains/letsPlot/core/plot/base/geom/RasterGeom.kt [31:115]
override fun buildIntern(
root: SvgRoot,
aesthetics: Aesthetics,
pos: PositionAdjustment,
coord: CoordinateSystem,
ctx: GeomContext
) {
val iter = with_X_Y(aesthetics.dataPoints()).iterator()
if (!iter.hasNext()) {
return
}
val randomP = iter.next()
val helper = GeomHelper(pos, coord, ctx)
// Find size of image (row x col)
val boundsXY = layerAesBounds(aesthetics)
val stepX = ctx.getResolution(Aes.X)
val stepY = ctx.getResolution(Aes.Y)
require(stepX > SeriesUtil.TINY) { "x-step is too small: $stepX" }
require(stepY > SeriesUtil.TINY) { "y-step is too small: $stepY" }
val width = (round(boundsXY.dimension.x / stepX) + 1)
val height = (round(boundsXY.dimension.y / stepY) + 1)
if (width * height > 5000000) {
val center = boundsXY.center
val text = "Raster image size\n[$width X $height]\nexceeds capability\nof\nyour imaging device"
val label = Label(text)
label.textColor().set(Color.DARK_MAGENTA)
label.setTextOpacity(0.5)
label.setFontSize(12.0)
label.setLineHeight(16.0)
label.setFontWeight("bold")
label.setHorizontalAnchor(HorizontalAnchor.MIDDLE)
label.setVerticalAnchor(VerticalAnchor.CENTER)
val loc = helper.toClient(center.x, center.y, randomP)!!
label.moveTo(loc)
root.add(label.rootGroup)
return
}
val cols = round(width).toInt()
val rows = round(height).toInt()
// translate to client coordinates
// expand bounds by 1/2 step before the translation to adjust for the size of 'image pixel'
val halfStep = DoubleVector(stepX * 0.5, stepY * 0.5)
val corner0 = helper.toClient(boundsXY.origin.subtract(halfStep), randomP)!!
val corner2 = helper.toClient(boundsXY.origin.add(boundsXY.dimension).add(halfStep), randomP)!!
val invertedX = corner2.x < corner0.x
val invertedY = corner2.y < corner0.y
// Fill image data array with RGB values
val x0 = boundsXY.origin.x
val y0 = boundsXY.origin.y
val argbValues = IntArray(cols * rows)
for (p in with_X_Y(aesthetics.dataPoints())) {
val x = p.x()
val y = p.y()
val alpha = p.alpha()
val color = p.fill()
var col = round((x!! - x0) / stepX).toInt()
var row = round((y!! - y0) / stepY).toInt()
if (invertedX) {
col = cols - (col + 1)
}
if (invertedY) {
row = rows - (row + 1)
}
argbValues[row * cols + col] = SvgUtils.toARGB(color!!, alpha!!)
}
val bitmap = Bitmap(cols, rows, argbValues)
val svgImageElement = SvgImageElementEx(
min(corner0.x, corner2.x), min(corner0.y, corner2.y),
abs(corner0.x - corner2.x), abs(corner0.y - corner2.y),
bitmap
)
root.add(svgImageElement)
}