I have an image in my Flash library (called sun.png) and I want to load this directly into an instance of a Bitmap (or equivalent) without using Actionscript linkage and creating its own class.
I have tried:
var sun:Bitmap = flash.utils.getDefinitionByName("sun.png") as Bitmap;
and:
var sun:Bitmap = this.loaderInfo.applicationDomain.getDefinition("sun.png") as Bitmap;
But neither of these work (I believe these functions are used for loading classes)
How can I do this without creating a class or loading from the filesystem?
Or is this even possible?
No, it is impossible. getDefinitionByName is just like getDefinition in current ApplicationDomain, except one of them through error instead of returning null.
Both of they are use finding only linked symbols. If you don't link the bitmap it will not even be compiled into output flash movie.
You can create some aliases in a static object like:
You define them once then use the objects as many times as you want. In the case of Bitmaps, after you get the bitmap, use the bitmapdata in a new Bitmap() because you need more different references with that same bitmapData.
class Refs
{
public static const PNG_0 : Bitmap= flash.utils.getDefinitionByName("com.example.MyImage") as Bitmap;
public static const PNG_1 : Bitmap= flash.utils.getDefinitionByName("com.example.OtherImage") as Bitmap;
}
what i think you want to do: first, make sure the image file is in the same folder as your FLA file (no need to have it in the library). then you can get the bitmap by writing this:
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.net.URLRequest;
bitmap:Bitmap;
ldr = new Loader ();
ldr.load( new URLRequest ( "sun.png" ));
ldr.contentLoaderInfo.addEventListener ( Event.COMPLETE, onloaded );
function onloaded ( e:Event ):void {
e.target.removeEventListener ( Event.COMPLETE, onloaded );
bmd = new BitmapData ( ldr.width, ldr.height );
bmd.draw ( ldr.content );
bitmap = new Bitmap (bmd);
}
Related
We are trying to merge multiple GLTFs on server side and export the merged gltf as final result on server.
Things we have trued that worked and that didn't:
We have used three js GLTFLoader parse method to load multiple gltf files, merge the parent and children of the loaded objects and export the final model using GLTFExporter.
We have used jsdom to resolve the issues related to window, document etc.
Above mentioned points work for gltfs without textures
While Loading GLTF with textures the response gets stuck.
a) We tried hosting the files on server and use the GLTFLoader load method with "localhost:******" as loader path.
b) Internally TextureLoader invoked ImageLoader where the onLoad event was not getting triggered at all . May be jsdom was not invoking this.
c) To solve this we changed ImageLoader to have canvas image :
const { Image } = require("canvas");
const image = new Image();
image.onload = onImageLoad;
image.onerror = onImageError;
d) The load method got resolved after above change.
e) Next step - Exporting the GLTF - We got stuck due to ImageData not found error. We added ImageData from canvas and the GLTF was exported.
f) The exported GLTF is not viewable die to corrupted data in images
"images": [
{
"mimeType": "image/png",
"uri": "data:,"
}
],
If someone loaded and merged GLTfs with texture images purely server side, Please Help!
As three.js is primarily a 3D rendering library for the web, and relies on various web image and WebGL APIs, I'm not sure using THREE.GLTFLoader is the most efficient way to merge glTF files on a Node.js server. I'd suggest this, instead:
import { Document, NodeIO } from '#gltf-transform/core';
import { KHRONOS_EXTENSIONS } from '#gltf-transform/extensions';
const io = new NodeIO().registerExtensions(KHRONOS_EXTENSIONS);
const document = new Document();
const root = document.getRoot();
// Merge all files.
for (const path of filePaths) {
document.merge(io.read(path));
}
// (Optional) Consolidate buffers.
const buffer = root.listBuffers()[0];
root.listAccessors().forEach((a) => a.setBuffer(buffer));
root.listBuffers().forEach((b, index) => index > 0 ? b.dispose() : null);
io.write('./output.glb', document);
It's worth noting that this process will result in a glTF file containing multiple separate scenes. If you want to combine them into a single scene, arranged in some way, you'd need to use the scene API to do that. If the files are not on disk, there are other NodeIO APIs for processing binary or JSON files in memory.
Language: Kotlin,
GUI Library: Swing,
IDE: IntelliJ IDEA
I know that there are similarly phrased questions, but note that I want to add multiple images, not just one, to any type of JComponent that holds other components. For example, I am not concerned with adding an image to a JLabel, I already know how to do that. I want to know how to add an image to a JFrame, JPanel, Container, etc.; all things that hold other Components (and have an add(Component) function). Finally, I don't want that workaround where you add the image to a JLabel with no text and then add that to the container. I would like to just use the Image class or a subset like BufferedImage or URL.
I want to be able to call the add() method from the Container class, jFrame.add(component) for example, where component is some sort of image. I want this to result in an image being displayed on the screen.
The ImageIcon class is not a Component so this can't be input on its own. I think I would have to create some sort of custom Image class that extends from Component or JComponent, but I don't know what I would have to override to get that to display an image on screen when added to another JComponent. There are multiple solutions to this, but to clarify, I don't want some kind of "middle man" where I add a JLabel or JButton or something that only contains an Icon. I don't want to display icons anyway, I want to display full-sized images anywhere on the screen. I will provide a possible example of what I want the final result to look like.
class MyApp() {
fun init() {
var jFrame = JFrame()
jFrame.add(Image("filepath/image.png"))
//Some other JFrame boiler plate
jFrame.isVisible = true
}
}
fun main() {
MyApp().init()
}
The unclear part is the Image class, and whether that's a custom class that inherits JImage, or some already defined class or method I don't know about. I know about ImageIO and BufferedImage and ImageIcon, but none of them directly go into this method, as they don't inherit Component or JComponent.
EDIT:
I tried using Camickr's second solution, but it didn't work. I will post the code to see if a made a simple mistake.
import java.awt.Image as AWTImage
import java.awt.Image.*
//Including these imports as I used name alias so I had to say what it was from.
open class JImage(var point: Point = Point(0, 0), image: AWTImage): JComponent() {
var image: ImageIcon = ImageIcon(image)
override fun paintComponent(g: Graphics?) {
super.paint(g)
g?.drawImage(image.image, point.x.toInt(), point.y.toInt(), null)
}
}
class SplashScreen(image: JImage): Frame() {
init {
//jFrame.isUndecorated = true
jFrame.add(image)
}
}
class MyApp {
fun init() {
var jFrame = SplashScreen(JImage(image = ImageIO.read(Loader().getClassLoader().getResourceAsStream("resources/images/splashscreen/SplashScreen.png"))).getScaledInstance(Size(1000, 1000*3/5)))
jFrame.isVisible = true
}
}
fun main() {
MyApp().init()
}
FINAL EDIT:
Okay, so I did make a simple mistake when trying this solution. I overrode paintComponent() but then inside it, I called super.paint(). Additionally, I realized I didn't have to use the ImageIcon class, which I didn't want to do anyway. This is the Image class I have come up with.
open class JImage(var point: Point = Point(0, 0), var image: AWTImage): JComponent() {
fun getScaledInstance(size: Size, scalingMethods: ScalingMethods = ScalingMethods.DEFAULT): JImage {
val scale: Int = when(scalingMethods) {
ScalingMethods.DEFAULT -> SCALE_DEFAULT
ScalingMethods.FAST -> SCALE_FAST
ScalingMethods.AREA_AVERAGING -> SCALE_AREA_AVERAGING
ScalingMethods.REPLICATE -> SCALE_REPLICATE
ScalingMethods.SMOOTH -> SCALE_SMOOTH
}
return JImage(point, image.getScaledInstance(size.width.toInt(), size.height.toInt(), scale))
}
override fun paintComponent(g: Graphics?) {
super.paintComponent(g)
g?.drawImage(image, point.x.toInt(), point.y.toInt(), null)
}
}
I want to know how to add an image to a JFrame, JPanel, Container, etc.
You don't add an image to a JFrame, JPanel etc. As you said an image is not a component. You add the image to a JLabel and add the label to the panel. This is the easiest and more direct way to display an image at its actual size.
Don't know if Kotlin is any different, but the other option is to do custom painting and paint the image on a JPanel by overriding the paintComponent(…) method and using the Graphics.drawImage(…) method and then add the panel to the frame. Read the Swing tutorial on Custom Painting for painting basics.
You can also check out Background Panel for an example that paints an image as a background of the panel. The image can be:
painted at its real size
scaled to fill the panel
tiled to fill the panel
Just note that the image should NOT be read in the paintComponent() method as painting code should be efficient.
I am making a game engine in haxe/openfl. so far it's just supposed to display the image that belongs to the thing object. what I have built so far runs perfectly on when deployed as a flash application, but closes instantly when I deploy it as a windows application. It just creates a blank screen in html5. I have not tested other targets. I am using HIDE, and every time it crashes, HIDE brings up the message: "File c:\Users\Adu\Documents\HaxeProjects\Downloaded\Export\windows\cpp\bin\Downloaded.exe was changed. Reload?" and gives me the options yes or no. My answer doesn't seem to change the situation. when I manually go into the export directory and run the application, it gives the error: "Error Custom([file_write,stderr]). Here is my code:
Main:
package;
import openfl.display.Graphics;
import openfl.Assets;
import openfl.display.Bitmap;
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.Lib;
import openfl.text.TextField;
import openfl.text.TextFormat;
import openfl.ui.Keyboard;
import openfl.events.*;
class Main
{
static var obj(default,default):ObjectManager; //contains the list that all gameobjects add themselves to
static var stage = Lib.current.stage;
public static function main() // this is the gameloop
{
// static entry point
startUp();
var running = true; // gives me a way to exit the gameloop
while (running)
{
logic();
render();
Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event)
{
if (event.keyCode == Keyboard.ESCAPE)
{
running=false;
}
});
}
}
static function startUp() // runs once, when the game is started
{
obj= new ObjectManager();
stage.align = openfl.display.StageAlign.TOP_LEFT;
stage.scaleMode = openfl.display.StageScaleMode.NO_SCALE;
}
static function logic() // loops, this handles the logic
{
var thing = new GameObject("assets/pixel_thing.png", 1, obj);
var mech = new GameObject("assets/mechwarrior.png", 0, obj);
}
static function render() // runs right after logic and draws everything to the screen
{
for (i in obj.objects) //iterates through a list of gabeobjects and draws them, it is 2 dimensional so that I can draw objects in blocks
{
for (j in i)
{
Lib.current.addChild(j);
}
}
}
}
GameObject:
package ;
import openfl.display.BitmapData;
import openfl.Assets;
import openfl.display.Bitmap;
import openfl.display.Sprite;
import openfl.events.Event;
import openfl.Lib;
import openfl.text.TextField;
import openfl.text.TextFormat;
class GameObject extends Sprite
{
public function new(?image:String, zOrder:Int, objectManager:ObjectManager) // image is the image, zorder is which layer it's drawn on, lower layers are drawn on top objectmanager is just there to help me pass the list to the object
{
super();
var data = Assets.getBitmapData(image);//this is the image data
var bitmap:Bitmap = new Bitmap(data);//this is the actual image
Lib.current.stage.addChild(bitmap);//this sraws the image when the object is instantiated
objectManager.objects[zOrder].push(this);// this adds it to the list of objects
}
}
ObjectManager:
package ;
class ObjectManager
{
public var objects = new Array<Array<GameObject>>();
}
why is it that it works on flash but not windows? How do I fix this?
First off - this doesn't work fine on flash either. Are you running this in the flash debug player? If you don't, which I assume is the case, you won't see any exceptions.
There's a null reference error at this line:
objectManager.objects[zOrder].push(this);// this adds it to the list of objects
You are accessing the array at index zOrder, which doesn't exist. objects is being initialized to [], which does not include the "inner arrays" (it can't, really, how would it know how many of them there should be?).
Now, Windows builds don't give you very helpful debug information by default. A simple way around is to use neko (which mostly behaves the same as hxcpp builds, except it compiles faster and performs worse) for debugging, where you get a stacktrace by default on crashes.
Sure enough, it's the same issue as in flash, the only difference is that native builds crash while flash just "ignores it" and tries to carry on.
Invalid field access : objects
Called from GameObject::new line 92
Called from GameObject::$init line 83
Called from Main::logic line 61
Called from Main::main line 38
Called from Reflect::callMethod line 58
Called from ApplicationMain::main line 91
Called from openfl.Lib::create line 113
For better hxcpp build debug info, you might want to have a look at the crashdumper lib.
For example, right now I have a class called "Balls.as". Here I load 10 different balls-images. You know, like this:
[Embed(source = "/ball1.png")]
[Embed(source = "/ball2.png")]
The problem is that if I spawn 5 balls, these balls images gonna get embeded 5 * 5 times right? Correct me if I'm wrong! So I though, can't I have a ballimageloading class? That loads these images once, and then in Balls.as I can load whatever ball i want for the moment?
You won't need to "load" them, they are embedded. You just have to instantiate the images. It's a good idea to have one class that manage shared ressources, as such:
public class TextureAssets
{
[Embed(source = "../lib/ball1.png")]
private static var Ball1:Class;
[Embed(source = "../lib/ball2.png")]
private static var Ball2:Class;
public static var ball1Texture:BitmapData;
public static var ball2Texture:BitmapData;
public static function init():void
{
ball1Texture = (new Ball1() as Bitmap).bitmapData;
ball2Texture = (new Ball2() as Bitmap).bitmapData;
}
Then you would call TextureAssets.init() once (in the Main.as for example)
and when you need the bitmapData: use new Bitmap(TextureAssets.ball1Texture)
This way your program needs uses only memory required for one bitmapData instead of having many which ends up being the same.
If you need to perform operations on a bitmapData while keeping the original you can use:
var modified:bitmapData = TextureAssets.ballTexture.clone();
Also, if you are instantiating all balls images from within one class it's a good idea to drop static access and instead initialise the bitmapDatas in the constructor, create a new TextureAssets() and call the textures through the variable
(Static field access is slower than direct (.) access : http://jacksondunstan.com/articles/1690)
The best practice is to have an Assets class which will contain static embeded images, like this:
[Embed(source="ball1.png")]
public static var BallImage1:Class;
Then all you'll have to do is declare a variable for your loaded Bitmap and use it, like so:
protected var mBall1:Bitmap = new Assets.BallImage1() as Bitmap;
This will create a Bitmap instance of your loaded image and you can then add it to the display list. Loading will happen only once per image and you'll have all your images at your fingertips, accessible from every class you have.
For the past few hours I have been trying to clone an image in Flex (using the Spark Components, but also trying to convert between Bitmap and BitmapImage).
What I am trying exactly is to create a simple painting application which keeps track of each Brush-Stroke. As soon as the Image on the Canvas has changed, it is to be cloned and then the clone is to be put into the History-Panel on the bottom of the application.
Things I have tried include:
Using ObjectUtils.clone(Object)
Creating BitmapData from Image.content, then making it a Bitmap and simply display it (Image doesn't have a content field, it says)
Performing a byte-copy
and others I could find on the internet, of course.
So basically, how does one clone an Image (Spark Image) in Flex 4.6?
Thank you very much!
-- Danny Nophut
Instead of cloning you can get the image of the drawing and set the bitmap of the image as source to the history image, do some thing like this
private function getBitmapData( target:DisplayObject ) : BitmapData
{
//target.width and target.height can also be replaced with a fixed number.
var bd : BitmapData = new BitmapData( target.width, target.height );
bd.draw( target );
return bd;
}
In some case if the width and height of the target is not working you can use the getbounds method to get the bounds of the object and from the bounds take the width and height.
There's a clone function on a bitmapdata:
public class EZB2ParkObject extends Image implements IEZB2ParkObject
{
public function clone():IEZB2ParkObject{
var n:IEZB2ParkObject = new EZB2ParkObject();
n.id = this.id;
n.source = new Bitmap(BitmapData(this.source.bitmapData).clone());
n.dimensions = this.dimensions;
n.assetId = this.assetId;
return n;
}
}