Openlaszlo colorTransform Issue - migration

I am using color transformation to set color on a view using this code in OL 3.3 this works perfecty fine.
obj.setColorTransform({ab: 0, aa: 100,
bb: b-rB, ba: 100,
gb: g-rG, ga: 100,
rb: r-rR, ra: 100});
But i am facing the problem when i have upgraded it to 5.0 swf runtime
obj.setAttribute('colortransform',{ab: 0, aa: 100,
bb: b-rB, ba: 100,
gb: g-rG, ga: 100,
rb: r-rR, ra: 100});
The obj here is a view in this format,
<view name="borders"
width="${parent.bg.width}"
height="${parent.bg.height}"
y="10">
<simplelayout axis="x"/>
<view name="left"
resource="border_left"
stretches="height"
height="${parent.height}"
x="5"
y="1">
</view>
<view name="middle"
resource="border_mid"
y="1"
stretches="width"
height="${parent.height - 2}"
width="${parent.width - parent.left.width - parent.right.width}">
</view>
<view name="right"
resource="border_right"
stretches="height"
height="${parent.height}">
</view>
</view>
Any Idea why this is not working?

The API has changed, when the setColorTransform({}) method was deprecated in favor of the .setAttribute('colortransform', {}). Instead of ra or rb the property keys are now redMultiplier, redOffset. See the corresponding doc sections quoted below.
Another change in the API is the values. Quoting the documentation for setColorTransform():
The dictionary has the following possible keys: o.ra: percentage alpha
for red component (-100 to 100); o.rb: offset for red component (-255
to 255); o.ga: percentage alpha for green component (-100 to 100);
o.gb: offset for green component (-255 to 255); o.ba: percentage alpha
for blue component (-100 to 100); o.bb: offset for blue component
(-255 to 255); o.aa: percentage overall alpha (-100 to 100); o.ab:
overall offset (-255 to 255);
Compare that with the documentation of a view's colortransform attribute:
The dictionary has the following possible keys: o.redMultiplier:
multiplier for red component (0 to 1) defaults to 1 o.redOffset:
offset for red component (-255 to 255) defaults to 0
o.greenMultiplier: multiplier for green component (0 to 1) defaults to
1 o.greenOffset: offset for green component (-255 to 255) defaults to
0 o.blueMultiplier: multiplier for blue component (0 to 1) defaults to
1 o.blueOffset: offset for blue component (-255 to 255) defaults to 0
o.alphaMultiplier: multiplier for alpha component (0 to 1) defaults to
1 o.alphaOffset: offset for alpha component (-255 to 255) defaults to
0
As you can see from the docs, the value range for the alpha offset changed from -100 to 100 to 0 to 1. The following syntax works when you use setAttribute:
var transformValues =
{redMultiplier: 0 to 1, redOffset: -255 to 255,
greenMultiplier: 0 to 1, greenOffset: -255 to 255,
blueMultiplier: 0 to 1, blueOffset: -255 to 255,
alphaMultiplier: 0 to 1, alphaOffset: -255 to 255}
this.setAttribute('colortransform', transformValues);

Related

QML Canvas clipping - non rectangular possible?

Is it possible to display non rectangular items in an app?
The top right edge of each element is clipped:
I turned off clipping on the canvas element and set the clipping
region of the context. I even allowed for the stroke drawing outside
the path. Here's what I'm using to draw it:
Canvas
{
//id: root
// canvas size
height: parent.height - 8
width: height
anchors.top: parent.top + 4
clip: false
z: index + 1
// handler to override for drawing
onPaint:
{
// get context to draw with
var ctx = getContext("2d")
ctx.reset();
// path that includes 1 pixel margin on all sides
ctx.beginPath()
ctx.moveTo( 8, 0 )
ctx.lineTo( width + 4, 0 )
ctx.lineTo( width - 4, height )
ctx.lineTo( 0, height )
ctx.closePath()
ctx.clip();
// setup the stroke
ctx.lineWidth = 2
ctx.strokeStyle = "white"
ctx.beginPath()
ctx.moveTo( 9, 1 )
ctx.lineTo( 9 + width, 1 )
ctx.lineTo( 1 + width, height - 1 )
ctx.lineTo( 1, height - 1 )
ctx.closePath()
ctx.fillStyle = (roleStatus.toLowerCase().indexOf("success")!==-1) ? "green" : "red"
ctx.fill()
ctx.stroke()
}
}
This will be used on Windows and android.
Thanks
Yes... You can use PaintedItem to paint directly on items using Native Paint tools from C++ like QPainterPath
check out http://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html
the reason that your canvas is clipping is due to the fact that you are drawing width + 4 which should be (width - 8), but since you move to (8,0) first, then you end up drawing an extra 4 pixels too far. try either moving the item over 4 pixels by doing moveTo(4,0) or make the line shorter by doing just width instead of width + 4
Also check out : anchors.fill: parent which will work better in your case most likely.
The way that I avoid crazy bugs like this is by not ever hard coding width, height, x or y into my application.. instead use percentages such as
(parent.width * 0.25) to get 1/4 of the parent
Here's ONE way you could fix your code...
Canvas
{
//id: root
// canvas size
height: parent.height * 0.95
width: height
anchors.top: parent.top
clip: false
z: index + 1
// handler to override for drawing
onPaint:
{
// get context to draw with
var ctx = getContext("2d")
ctx.reset();
// path that includes 1 pixel margin on all sides
ctx.beginPath()
ctx.moveTo( width * 0.1, 0 )
ctx.lineTo( width * 0.9, 0 )
ctx.lineTo( width * 0.7, height )
ctx.lineTo( 0, height )
ctx.closePath()
ctx.clip();
/* etc etc */
}
}
I was unable to find a way to draw outside the bounds of the item. I was able to achieve the effect I wanted though. I drew the polygon within the bounds of the item and set the 'spacing' property of the ListView to a negative value. This overlaps the drawn items to achieve the desired look:

Vulkan compute shader invisible pixel writes

I am playing around with a compute shader and have a weird behaviour I really cannot explain. I was wondering if you could help me figure it out.
This is a suboptimal use of a compute shader, but I want to understand what is happening...
I have a 64x64 texture and I want to write 4 horizontal pixels from a single invocation of my shader. Therefore I call vkCmdDispatch( 64 / 4, 1, 1 ); with the following shader
#version 450
layout (local_size_x = 1, local_size_y = 1) in;
layout (binding = 0, rgba8) uniform writeonly image2D resultImage;
void main()
{
const uint texPosX = gl_GlobalInvocationID.x * 4;
const uint texPosY = gl_GlobalInvocationID.y;
imageStore( resultImage, ivec2( texPosX + 0, texPosY ), vec4( 1.0f, 0.0f, 0.0f, 1.0f) );
imageStore( resultImage, ivec2( texPosX + 1, texPosY ), vec4( 0.0f, 1.0f, 0.0f, 1.0f) );
imageStore( resultImage, ivec2( texPosX + 2, texPosY ), vec4( 0.0f, 0.0f, 1.0f, 1.0f) );
imageStore( resultImage, ivec2( texPosX + 3, texPosY ), vec4( 1.0f, 1.0f, 1.0f, 1.0f) );
}
I would expect this to write 4 pixels (red green blue and white) in a single row. I would expect the final image to look like vertical lines with a pattern like { red, green, blue, white, red, green, blue, white, ...}
What I get is instead vertical lines with a pattern of { red, green, blue, white, green, blue, white, red, blue, etc... } so it looks like there is a shift by one in the values.
If I instead change the way I compute the texPosX to const uint texPosX = gl_GlobalInvocationID.x * 5; (writing 5 pixels instead of 4) I get the expected result. If I add a fifth write like so
imageStore( resultImage, ivec2( texPosX + 4, texPosY ), vec4( 1.0f, 1.0f, 1.0f, 1.0f) ); // purple color at fifth pixel
the result is exactly the same as previously, meaning the last write is "invisible". My image is really 64x64, but it seems the number of pixels each invocation is working on is 5, with the last one not being invisible... And as far as I know, 64 / 4 = 16 workgroups and 64 / 16 = 4 pixels per workgroup (since my local group size is 1).
I am surely missing something that is obvious, but I have no clue to what it is. I thought I understood the global/local workgroup size, but it does not seem to be the case...
Thanks a lot for your help !

Plot Array as Graph in ImageView

How can I plot an array to an imageview as a graph?
I've been testing this in Playground and it works, but how can plot this as an imageview in an actual project?
let sineArraySize = 64
let frequency1 = 4.0
let phase1 = 0.0
let amplitude1 = 2.0
let sineWave = (0..<sineArraySize).map {
amplitude1 * sin(2.0 * M_PI / Double(sineArraySize) * Double($0) * frequency1 + phase1)
}
func plotArrayInPlayground<T>(arrayToPlot:Array<T>, title:String) {
for currentValue in arrayToPlot {
XCPCaptureValue(title, currentValue)
}
}
plotArrayInPlayground(sineWave, "Sine wave 1")
One way you could do this:
// this function creates a plot of an array of doubles where it scales to the provided width and the x-axis is on half height
func plotArray(arr: [Double], width: Double, height: Double) -> NSImage {
if arr.isEmpty { return NSImage() }
let xAxisHeight = height / 2
let increment = width / Double(arr.count)
let image = NSImage(size: NSSize(width: width, height: height))
image.lockFocus()
// set background color
NSColor.whiteColor().set()
NSRectFill(NSRect(x: 0, y: 0, width: width, height: height))
let path = NSBezierPath()
// line width of plot
path.lineWidth = 5
path.moveToPoint(NSPoint(x: 0, y: arr[0] * increment + xAxisHeight))
var i = increment
for value in dropFirst(sineWave) {
path.lineToPoint(NSPoint(x: i, y: value * increment + xAxisHeight))
i += increment
}
// set plot color
NSColor.blueColor().set()
path.stroke()
image.unlockFocus()
return image
}
var imageView = NSImageView()
imageView.image = plotArray(sineWave, 500, 200)
// have fun

How do I set LinePlot line thickness and style? (DigitalMicrograph script)

The scripting help documentation of DigitalMicrograph offers an example for setting LinePlot styles with respect of colour and fill (see example script below).
However, the ImageDisplay menu for LinePlots also allows setting line styles (dotted, dashed,...) line thickness and transparency. Can somebody give an example on how to set these values, please?
// create image and image document
ImageDocument imageDoc = CreateImageDocument( "New ImageDocument" )
number width = 256
number height = 5
image img := RealImage("Line Plot Test", 4, width, height )
img = sin( irow + icol/100 )
// add LinePlotImageDisplay to ImageDocument
ImageDisplay imgdsp = imageDoc.ImageDocumentAddImageDisplay( img, 3 )
imgdsp.LinePlotImageDisplaySetContrastLimits( -1.1, 1.1 )
imgdsp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
// draw fill and line for slice 0
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(0, 3)
// set line color to red
imgdsp.LinePlotImageDisplaySetSliceComponentColor(0, 0, 1, 0, 0)
// set fill color to yellow
imgdsp.LinePlotImageDisplaySetSliceComponentColor(0, 1, 0.9, 0.9, 0)
// draw fill for slice 1 and 2
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(1, 2)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(2, 2)
// draw line for slice 3 and 4
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(3, 1)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle(4, 1)
imageDoc.ImageDocumentShow()
The commands you are looking for are:
void LinePlotImageDisplaySetSliceLineThickness( LinePlotImageDisplay lpid, Number slice_id, Number lineThickness )
void LinePlotImageDisplaySetSliceLineStyle( LinePlotImageDisplay lpid, Number slice_id, Number lineStyle )
void LinePlotImageDisplaySetSliceTransparency( LinePlotImageDisplay lpid, Number sliceIndex, Boolean doTransparent, Number transparency )
They are demonstrated in the example below. Note that the visibility of line styles depend on the number of points in a LinePlot. If the LinePlot has more data points than displayed pixels, you may not notice the line style as it is defined 'in between' data points:
// create image and image document
ImageDocument imageDoc = CreateImageDocument( "New ImageDocument" )
number width = 64
number height = 10
image img := RealImage("Line Plot Test", 4, width, height )
img = sin( irow + icol / iwidth * 2 * Pi() ) + ( irow < ( height / 2 ) ? 1.5 : -1.5 )
// add LinePlotImageDisplay to ImageDocument
ImageDisplay imgdsp = imageDoc.ImageDocumentAddImageDisplay( img, 3 )
imgdsp.LinePlotImageDisplaySetContrastLimits( -2.6, 2.6 )
imgdsp.LinePlotImageDisplaySetDoAutoSurvey( 0, 0 )
// Line style demo
for ( number i = 0 ; i < height / 2 ; i++ )
{
number index = i + height / 2
// Set Line - drawing (no fill)
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle( index , 1 )
// Set black line
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 0 , 0, 0, 0 )
// Set LineThickness
imgdsp.LinePlotImageDisplaySetSliceLineThickness( index , height / 2 - i + 1 )
// Set LineStyle
imgdsp.LinePlotImageDisplaySetSliceLineStyle( index , i )
}
// Transparecny demo
for ( number i = 0 ; i < height / 2 ; i++ )
{
number index = i
// Set Fill & Line - drawing
imgdsp.LinePlotImageDisplaySetSliceDrawingStyle( index , 1 + 2 )
// Set black fill & red line
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 1 , 0 , 0 , 0 )
imgdsp.LinePlotImageDisplaySetSliceComponentColor( index , 0 , 255 , 0 , 0 )
// Set transparency ( 70% transparency = 30% opacity )
imgdsp.LinePlotImageDisplaySetSliceTransparency( index , 1 , 0.7 )
}
imageDoc.ImageDocumentShow()

Rounded Rectangle Not Accurate

Every sample code I've ever found for drawing rounded rectangles using GDI+ goes something like this (lifted and slightly modified from BobPowell.net):
Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Panel1.Paint
e.Graphics.Clear(SystemColors.Window)
e.Graphics.SmoothingMode = SmoothingMode.None
Call DrawRoundRect(e.Graphics, Pens.Red, 10, 10, 48, 24, 6)
End Sub
Public Sub DrawRoundRect(ByVal g As Graphics, ByVal p As Pen, ByVal x As Single, ByVal y As Single, ByVal width As Single, ByVal height As Single, ByVal radius As Single)
Using gp As New GraphicsPath()
gp.StartFigure()
gp.AddArc(x + width - radius, y, radius * 2, radius * 2, 270, 90)
gp.AddArc(x + width - radius, y + height - radius, radius * 2, radius * 2, 0, 90)
gp.AddArc(x, y + height - radius, radius * 2, radius * 2, 90, 90)
gp.AddArc(x, y, radius * 2, radius * 2, 180, 90)
gp.CloseFigure()
g.DrawPath(p, gp)
End Using
End Sub
This produces a rounded rectangle where only the top left corner is accurate.
AntiAliasing has to be turned off because it is going through a remote desktop connection, and I can't depend on it being available. Besides, I am looking for a crisp rounded rectangle.
I've tried resizing the other corners and changing the pen alignments, but nothing seems to produce a simple, accurate rounded rectangle.
Is there a way to draw a better rounded rectangle than this in good old winforms?
1) Resize your source image to a binary multiple of its original size. Typically, I'll resample to a width and height 4 times greater (or 8, or 16) than the original.
2) Perform all my GDI+ drawing operations (taking into account, of course, that my co-ordinates will need to be multiplied by a factor of 4). There is no need to use any fancy anti-aliasing.
3) Re-sample the image back down to the original dimensions. Shrinking the image results in a nice smoothing effect, and minimizes any rounding errors in lines, curves, etc.
private Bitmap GenerateButton(int overSampling) {
int overSampling = 8;
int width=(48 + 10 + 10 + 6) * overSampling;
int height=(24 + 10 + 10 + 6) * overSampling;
// Draw the button with the rounded corners, but do
// so at 8 times the normal size.
Bitmap bitmap=new Bitmap(width,height);
using (Graphics g = Graphics.FromImage(bitmap)) {
g.Clear(Color.White);
g.SmoothingMode = SmoothingMode.None;
DrawRoundRect(overSampling, g, new Pen(Color.Red, overSampling), 10, 10, 48, 24, 6);
}
// Shrink the image down to its intended size
Bitmap shrunkVersion=new Bitmap(bitmap.Width / overSampling, bitmap.Height / overSampling);
using (Graphics g = Graphics.FromImage(shrunkVersion)) {
// Use hi-quality resampling for a nice, smooth image.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(bitmap, 0, 0, shrunkVersion.Width, shrunkVersion.Height);
}
return shrunkVersion;
}
private void DrawRoundRect(int overSampling, Graphics g, Pen p, float x, float y, float width, float height, float radius)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.StartFigure();
gp.AddArc((x + width - radius) * overSampling, y * overSampling, (radius * 2) * overSampling, (radius * 2) * overSampling, 270, 90);
gp.AddArc((x + width - radius) * overSampling, (y + height - radius) * overSampling, (radius * 2) * overSampling, (radius * 2) * overSampling, 0, 90);
gp.AddArc(x * overSampling, (y + height - radius) * overSampling, radius * 2 * overSampling, radius * 2 * overSampling, 90, 90);
gp.AddArc(x * overSampling, y * overSampling, radius * 2 * overSampling, radius * 2 * overSampling, 180, 90);
gp.CloseFigure();
g.DrawPath(p, gp);
}
}
Without oversampling:
With 8 times oversampling:
I have found the best solution to be just old-school Windows API:
Private Sub DrawRoundRect(ByVal g As Graphics, ByVal r As Rectangle)
Dim hDC As IntPtr = g.GetHdc
Dim hPen As IntPtr = CreatePen(PS_SOLID, 0, ColorTranslator.ToWin32(Color.Red))
Dim hOldPen As IntPtr = SelectObject(hDC, hPen)
SelectObject(hDC, GetStockObject(NULL_BRUSH))
RoundRect(hDC, r.Left, r.Top, r.Right - 1, r.Bottom - 1, 12, 12)
SelectObject(hDC, hOldPen)
DeleteObject(hPen)
g.ReleaseHdc(hDC)
End Sub
This produces the symmetrical rounded rectangle I've been looking for:
Because no-one's answered you yet here is a trick I have used in the past. It works reasonably well, and definitely looks better than the classic implementation with AddArc().
It uses circles and clipping to achieve the result you want. It may show slight artefacts when using pens with a width greater than 1px, but other than that it works well.
I hope it will be good enough for your project.
private void DrawRoundedRectangle(Graphics g, Pen pen, Rectangle rect, int radius)
{
g.DrawLine(pen, rect.Left + radius, rect.Top, rect.Right - radius, rect.Top);
g.DrawLine(pen, rect.Right, rect.Top+radius, rect.Right, rect.Bottom - radius);
g.DrawLine(pen, rect.Left + radius, rect.Bottom, rect.Right - radius, rect.Bottom);
g.DrawLine(pen, rect.Left, rect.Top + radius, rect.Left, rect.Bottom - radius);
g.SetClip(new Rectangle(rect.Left, rect.Top, radius, radius));
g.DrawEllipse(pen, rect.Left, rect.Top, radius * 2, radius * 2);
g.ResetClip();
g.SetClip(new Rectangle(rect.Right-radius, rect.Top, radius+1, radius+1));
g.DrawEllipse(pen, rect.Right - radius * 2, rect.Top, radius * 2, radius * 2);
g.ResetClip();
g.SetClip(new Rectangle(rect.Right - radius, rect.Bottom-radius, radius+1, radius+1));
g.DrawEllipse(pen, rect.Right - radius * 2, rect.Bottom - (radius * 2), radius * 2, radius * 2);
g.ResetClip();
g.SetClip(new Rectangle(rect.Left, rect.Bottom - radius, radius+1, radius+1));
g.DrawEllipse(pen, rect.Left, rect.Bottom - (radius * 2), radius * 2, radius * 2);
g.ResetClip();
}
The method's interface is straightforward, but post a comment if you need assistance.
Edit: Something else that should work is to draw the same arc four times, but flipped using TranslateTransform and TranslateScale. That should mean the arc appears identical in each corner.
private void DrawRoundedRectangle(Graphics g, Pen pen, Rectangle rect, int radius)
{
g.DrawLine(pen, rect.Left + radius, rect.Top, rect.Right - radius, rect.Top);
g.DrawLine(pen, rect.Right-1, rect.Top+radius, rect.Right-1, rect.Bottom - radius);
g.DrawLine(pen, rect.Left + radius, rect.Bottom-1, rect.Right - radius, rect.Bottom-1);
g.DrawLine(pen, rect.Left, rect.Top + radius, rect.Left, rect.Bottom - radius);
g.TranslateTransform(rect.Left, rect.Top);
g.DrawArc(pen, 0, 0, radius * 2, radius * 2, 180, 90);
g.ResetTransform();
g.TranslateTransform(rect.Right, rect.Top);
g.ScaleTransform(-1, 1);
g.DrawArc(pen, 1, 0, radius * 2, radius * 2, 180, 90);
g.ResetTransform();
g.TranslateTransform(rect.Right, rect.Bottom);
g.ScaleTransform(-1, -1);
g.DrawArc(pen, 1, 1, radius * 2, radius * 2, 180, 90);
g.ResetTransform();
g.TranslateTransform(rect.Left, rect.Bottom);
g.ScaleTransform(1, -1);
g.DrawArc(pen, 0, 1, radius * 2, radius * 2, 180, 90);
g.ResetTransform();
}
This is similar to the old Computer Graphics method of drawing a circle, where you'd draw a quarter circle four times to avoid rounding errors such as the one in GDI.
Another alternative is to draw the first arc onto an image, and then draw the image four times, flipping as required. Below is a variation on the second method, using an image to draw the arcs.
private void DrawRoundedRectangle(Graphics g, Pen pen, Rectangle rect, int radius)
{
g.DrawLine(pen, rect.Left + radius, rect.Top, rect.Right - radius, rect.Top);
g.DrawLine(pen, rect.Right - 1, rect.Top + radius, rect.Right - 1, rect.Bottom - radius);
g.DrawLine(pen, rect.Left + radius, rect.Bottom - 1, rect.Right - radius, rect.Bottom - 1);
g.DrawLine(pen, rect.Left, rect.Top + radius, rect.Left, rect.Bottom - radius);
Bitmap arc = new Bitmap(radius, radius, g);
Graphics.FromImage(arc).DrawArc(pen, 0, 0, radius * 2, radius * 2, 180, 90);
g.TranslateTransform(rect.Left, rect.Top);
g.DrawImage(arc, 0, 0);
g.ResetTransform();
g.TranslateTransform(rect.Right, rect.Top);
g.ScaleTransform(-1, 1);
g.DrawImage(arc, 0, 0);
g.ResetTransform();
g.TranslateTransform(rect.Right, rect.Bottom);
g.ScaleTransform(-1, -1);
g.DrawImage(arc, 0, 0);
g.ResetTransform();
g.TranslateTransform(rect.Left, rect.Bottom);
g.ScaleTransform(1, -1);
g.DrawImage(arc, 0, 0);
g.ResetTransform();
arc.Dispose();
}
On occasion, I've used a "low tech" approach to deal with the rounding errors in GDI+
1) Resize your source image to a binary multiple of its original size. Typically, I'll resample to a width and height 4 times greater (or 8, or 16) than the original.
2) Perform all my GDI+ drawing operations (taking into account, of course, that my co-ordinates will need to be multiplied by a factor of 4). There is no need to use any fancy anti-aliasing.
3) Re-sample the image back down to the original dimensions. Shrinking the image results in a nice smoothing effect, and minimizes any rounding errors in lines, curves, etc.