Drawing an image onto a threepenny-gui Canvas - haskell

I'm having an issue with canvases. I have modified the Canvas.hs example program to draw an image onto the canvas with
canvas # drawImg
right after the canvas setup code; here it is for reference:
canvas <- UI.canvas
# set UI.height canvasSize
# set UI.width canvasSize
# set style [("border", "solid black 1px"), ("background", "#eee")]
where drawImg is
drawImg :: UI.Canvas -> UI ()
drawImg canvas = do
url <- UI.loadFile "image/png" "resources/img.png"
img <- UI.img # set UI.src url
UI.drawImage img (0,0) canvas
which should be the same behavior as the on click function for drawing an image in the original version of the code.
The actual behavior of this code is a blank canvas, just as in the original example before clicking on the draw image button. I would think that it should draw the image on loading. Why is this? Should I instead add this call to the line that sets up the canvas?

Is the canvas part of the DOM? Don't forget to add it to the document body with via getBody #+ [...] or thelike.
There may be another problem, though: Browsers usually load image URLs asynchronously. In fact, I'm not sure if they load image URLs at all if the image is not part of the DOM, as in your example. In both scenarios, if you try to draw an image to a canvas before its URL has been loaded, nothing will be drawn. (The easiest way to check whether this problem is the relevant one in your code is to draw polygons instead of an image.)

Related

Pixi.js Container.width does not return width

I'm having a bit of a problem: I'm trying to access the width of a container in which I've added a sprite to, but it seems to return as 1. However, when I inspect the object in the console, it gives me the proper width.
I wrote up a code pen showing the issue, but it goes something like this:
var container = new PIXI.Container();
app.stage.addChild(container);
var sprite = PIXI.Sprite.fromImage('https://i2.wp.com/techshard.com/wp-
content/uploads/2017/05/pay-1036469_1920.jpg?ssl=1&w=200');
container.addChild(sprite);
console.log(container.height);
console.log(container);
The first console log returns 1, while if I go into the object in the second log it gives me 141.
I'm trying to center the container like in the demo. The demo container returns the proper width, unless you try and do it for only one "bunny" (replacing bunny texture with internet image, also the for loop is commented out).
Any suggestions on a proper approach for this?
Cheers
There's a few things to address here.
Firstly, what the problem in your codepen is:
You're creating a texture from an image that has yet to be loaded.
Until the image loads pixi will not be able to give you the dimensions of it, and the container reports a width and height of 1 when you immediately query them. If you put the same console.log statement in a timeout then it will report the dimensions after the image has loaded and thus the dimensions will be accurate.
Logging out the object itself seems to work because when you examine the contents of it they've been updated to the correct values because the image has loaded by that point.
If the texture is already in the cache at the point that you create a new sprite using it then you won't have to wait before you can access its true dimensions.
Secondly, why the bunny example on pixi's site doesn't have the same problem:
Actually, it does. You just don't notice it.
The magic is in the bunny.anchor.set(0.5);. It lines 25 sprites with width and height of 1 out in a grid. By spacing them out, their container now has width and height of 160.
This container is now centered immediately based on its current dimensions, and then when the sprite textures finish loading and the sprites are updated with their new dimensions. Due to their anchor being set to 0.5, however, this means they remain centered despite their container now being larger.
You can play around with using a larger image than the bunny to exaggerate things and changing the anchor value, along with using the rerun code button rather than just refreshing the page. If you rerun the code the image being used for the texture remains cached by pixi so you get different results.
Lastly, how you would resolve this issue:
Loading your assets before creating sprites with them.
(Or at least waiting before they're loaded before querying their dimensions to position things)
You can find an example of the resource loader that pixi has here: http://pixijs.io/examples/?v=next-interaction#/basics/spritesheet.js

Using PathMenu with SVG in a Paintcode StyleKit

I need to change the image programmatically that PathMenu uses to design.
I have a PaintCode generated StyleKit which draws .SVG files, not an image in a Asset.xcassets.
PathMenu uses something like this to take the images:
let menuItemImage = UIImage(named: "bg-menuitem")!
but I need to make something like
let menuItemImage = myImageFromMyStyleKit
How can I make this work?
In PaintCode document, select canvas and in Inspector, select StyleKit Image Method from dropdown menu in Code Export section.
This canvas will then generate imageOfCanvas... method, instead of drawCanvas... method. This way, you can then simply obtain image of this canvas and use it in the menu item.
PathMenuItem(image: StyleKit.imageOfCanvas)

Generate an image of all widgets within a scrollarea

BACKGROUND:
I have a python program that is being used by a number of engineers. It indicates the status of some piece of equipment under test.
I am using a QScrollArea() to contain a QGridLayout which is packed with alot of information.
bit_grid = QtGui.QGridLayout()
...
scroll = QtGui.QScrollArea()
info = QtGui.QWidget()
info.setLayout(bit_grid)
scroll.setWidget(info)
There are quite a few status indicators on the GUI and as such the scrollbar is used to ensure the GUI fits on one screen.
When an engineer want's to describe a failure what they are doing right now is taking multiple screenshot, one for each new displayed area of the ScrollArea. They are then stitched together to make one large image.
Is there a way to generate a png (or an img format) of the area that could be display within a ScrollArea?
Try this:
pixmap = QtGui.QPixmap.grabWidget(scroll)
pixmap.save('path/to/file.png', None, 100)
This snippet will take a snapshot of whatever is inside the scrollArea and save that as a png image to path/to/ folder as file.png
ok solved.
widget = self.scroll.widget()
pixmap = QtGui.QPixmap(widget.size())
widget.render(pixmap)
pixmap.save(filename, 'PNG', 100)
The key was to grab the widget that is in scroll as this could then be (virtually) rendered. The resultant pixmap could then be saved.

ImageOverlay and Rectangle Z index issue

I have a function that adds an imageOverlay and a semitransparent Rectangle on top of that image (so as to tint the image, and draw a keyline around it).
activeUserImage = new L.imageOverlay(imageUrl, imageBounds).addTo(map);
activeUserTile = new L.rectangle(imageBounds, {stroke: true, color: "#ffffff", opacity:1, weight: 1, fillColor: "#003572", fillOpacity: 0.7, clickable:true}).addTo(map);
this works great, but then I want to remove the image and rectangle with:
map.removeLayer(activeUserImage);
map.removeLayer(activeUserTile);
This seems to work well...
However when I try and add a second Image & Rectangle (using the same function) the rectangle SVG is being rendered underneath the image, so I don't see the colored overlay.
This seems to be because the element is being left behind from the first creation, and then when the image is being added a second time it appears in front of the SVG.
Q:
Is this a bug? Should the SVG element not be cleared too?
Can I adjust z-index of the image or SVG on creation?
should i be containing to rectangle in a different layer to the images? How?
Many Thanks
OK, so the Leaflet bringToFront() method didn't work, but instead I have used a bit of JQuery to force the same approach.
svgObj = $('.leaflet-overlay-pane svg');
svgObj.css('z-index', 9999);
This works, but still feels like a hack... however if (?) there is a bug in LEaflet, then maybe this will have to do???
Any better ideas?
The bringToFront() function alows you to bring layer to the top.
Search it in the docs.

overlap one image over another

I want to add image and some text on another image and create a single image. I have got to add text but not able to figure out that how to add image. Any help?
This snippet assumes you have UIImage's named bottomImage for the base image to be drawn upon, and topImage that will be drawn ON (above) the bottomImage. xpos,ypos are floats to describe the target x,y (top left) position where topImage will be drawn, and targetSize the size in which topImage will be drawn on bottomImage.
...
UIGraphicsBeginImageContext( bottomImage.size );//create a new image context to draw offscreen
[bottomImage drawInRect:CGRectMake(0,0,bottomImage.size.width,bottomImage.size.height)];//draw bottom image first, at original size
[topImage drawInRect:CGRectMake(xpos,ypos,targetSize.width,targetSize.height) blendMode:kCGBlendModeNormal alpha:1];//draw the image to be overlayed second, at wanted location and size
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();//get newly drawn image context into a UIImage
UIGraphicsEndImageContext();//stop drawing to the context
return newImage;//return/use the newly created image
This is not thread safe - creating a UIImage in a thread is not recommended.

Resources