I need to decrease the pixels in image from 480 X 480 to 30 X 30. This requires downsampling of pixels, i don't see any method to remove individual pixels in a bitmap image.
I need this downsampling because i'm studying distortion in image processing - on the brief side.
Any help in this would be appreciated.
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLRequest;
public class DownSampling extends Sprite
{
private var _loader : Loader;
public function DownSampling()
{
_loader = new Loader;
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImgLoaded);
// Get the bitmap
_loader.load(new URLRequest("https://appharbor.com/assets/images/stackoverflow-logo.png"));
}
private function onImgLoaded(e : Event) : void
{
var currentBitmapdata : BitmapData = Bitmap(_loader.content).bitmapData;
var i : uint = 9;
var downFactor : Number = 0.2;
// this will reduce size by 20%
var downMat : Matrix = new Matrix;
downMat.scale(1 - downFactor, 1 - downFactor);
while(--i)
{
// Create new bitmapdata but smaller
var smallerImg : BitmapData = new BitmapData(currentBitmapdata.width * (1-downFactor), currentBitmapdata.height * (1-downFactor), true, 0);
// Copy and apply scale
smallerImg.draw(currentBitmapdata, downMat);
// Add to stage and set alpha to 50%
addChild(new Bitmap(smallerImg)).alpha = .5;
// Apply the same transform next loop
currentBitmapdata = smallerImg;
}
}
}
}
Result :
Related
I have simple demo project. Image moved along screen follow mouse point.
LibGDX Image instance jump to default x coordinate along x axis, determined inside MainMenuScreen.kt show method, every time i click on screen, and start from default position moving. But i expect Image will continue/start new moving from last position before click on screen. How fix it, and what problem?
Code is simple and short, and i can't understand what can be wrong.
pastebin link to full project code:
https://pastebin.com/4UQDjSWa
github link to project:
https://github.com/3dformortals/demo-libgdx/tree/master/DemoMovingImageOnScreen
full project code:
//-------
//KDA.kt
//-------
package com.kda
import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.GL20
import gui.AnimationSkin as AniSkin
class KDA : Game() {
internal var screenWidth:Float = 0.0f
internal var screenHeight:Float = 0.0f
internal val aniskin:AniSkin = AniSkin() //incuded human.atlas TextureAtlas for animation
override fun create() {
screenWidth = Gdx.graphics.width.toFloat()
screenHeight = Gdx.graphics.height.toFloat()
aniskin.prepare() //call preparing method for connect human.atlas for later using for animation
}
override fun render() {
Gdx.gl.glClearColor(1f, 0f, 0f, 1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
if (Gdx.input.justTouched()){
setScreen(MainMenuScreen(this))
}
super.render()
}
}
//-------------------
//AnimationSkin.kt
//-------------------
package gui
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.g2d.TextureAtlas
import com.badlogic.gdx.scenes.scene2d.ui.Skin
class AnimationSkin : Skin() {
fun prepare(){
addRegions(TextureAtlas(Gdx.files.internal("animation/human.atlas")))
}
}
//----------------------
//MainMenuScreen.kt
//----------------------
package com.kda
import animated.ImageMoving
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.ScreenAdapter
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.scenes.scene2d.Stage
import com.badlogic.gdx.utils.viewport.FitViewport
class MainMenuScreen(private val game: KDA) : ScreenAdapter() {
private val stage: Stage = Stage(FitViewport(game.screenWidth, game.screenHeight))
private val player = ImageMoving(game)
private val sprite = player.viewBox()
override fun show() {
Gdx.input.inputProcessor = stage
stage.isDebugAll = true //turn on frames around objects
sprite.x = 500f
//------------------------------------------------------------------------------------
//later, every mouse click on screen sprite jump to x500 position, and i can't fix it
//if i don't execute `sprite.x = 500f` , then sprite jump to x0 position, every click on screen
//--------------------------------------------------------------------------------------------
stage.addActor(sprite)
}
override fun resize(width: Int, height: Int) {
stage.viewport.update(width, height, true)
}
override fun render(delta: Float) {
super.render(delta)
Gdx.gl.glClearColor(0f, 0.5f, 0.5f, 1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
if(Gdx.input.justTouched()) println("before calculateAction box.x= "+sprite.x.toString()) //500 always
player.calculateAction(delta) //call player method for calculation moving on screen
println(sprite.x) //print normal as expected
stage.act(delta)
stage.draw()
}
}
//-----------------
//ImageMoving.kt
//-----------------
package animated
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.kda.KDA
class ImageMoving(game: KDA) {
fun viewBox() = img
private val img = Image(game.aniskin.getDrawable("move-skin-male-back-R-0"))
fun calculateAction(delta:Float){
if (img.x > Gdx.input.x) img.x-=(100*delta).toInt().toFloat()
else if (img.x < Gdx.input.x) img.x+=(100*delta).toInt().toFloat()
}
}
//----------------------
//DesktopLauncher.kt
//---------------------
package com.kda.desktop
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.kda.KDA
object DesktopLauncher {
#JvmStatic
fun main(arg: Array<String>) {
val config = LwjglApplicationConfiguration()
config.height = 720
config.width = 1280
LwjglApplication(KDA(), config)
}
}
gif animation demo of jumping image to default position x=500 after clicking on screen
I'm trying to run the most basic Haxe program but keep getting errors.
The Main.hx file looks like this:
package;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.Lib;
import flixel.FlxGame;
import flixel.FlxState;
class Main extends Sprite {
var gameWidth:Int = 640; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom).
var gameHeight:Int = 480; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
var initialState:Class<FlxState> = MenuState; // The FlxState the game starts with.
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
var framerate:Int = 60; // How many frames per second the game should run at.
var skipSplash:Bool = false; // Whether to skip the flixel splash screen that appears in release mode.
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
// You can pretty much ignore everything from here on - your code should go in your states.
public static function main():Void
{
Lib.current.addChild(new Main());
}
public function new()
{
super();
if (stage != null)
{
init();
}
else
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
private function init(?E:Event):Void
{
if (hasEventListener(Event.ADDED_TO_STAGE))
{
removeEventListener(Event.ADDED_TO_STAGE, init);
}
setupGame();
}
private function setupGame():Void
{
var stageWidth:Int = Lib.current.stage.stageWidth;
var stageHeight:Int = Lib.current.stage.stageHeight;
if (zoom == -1)
{
var ratioX:Float = stageWidth / gameWidth;
var ratioY:Float = stageHeight / gameHeight;
zoom = Math.min(ratioX, ratioY);
gameWidth = Math.ceil(stageWidth / zoom);
gameHeight = Math.ceil(stageHeight / zoom);
}
addChild(new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen));
}
}
Just the generic template file. When I run it in Terminal (running Mac OS X El Capitan), I get this error:
Main.hx:8: characters 7-21 : Type not found : flixel.FlxGame
Haven't had problems with the installations or anything and I am new to Haxe so I don't know where to start. Any ideas?
Thanks :)
Did you add the library when you try to run your game ?
You can do that by using the command line haxe -lib flixel -main Main ....
Or by writting an hxml file containing all your CLI arguments :
-lib flixel
-main Main
Update after #Gama11 comment :
HaxeFlixel used the OpenFL format for the compilation information (see http://www.openfl.org/documentation/projects/project-files/xml-format/).
So you should include include flixel library using : <haxelib name="flixel" />in your Project.xml file.
I'm trying to do some basic animations, but am failing at the most simple things:
Rectangle rect = new Rectangle(100.0, 10.0);
mainPane.getChildren().add(rect); //so the rectangle is on screen
Animation anim = new Timeline(new KeyFrame(Duration.seconds(30.0),
new KeyValue(rect.widthProperty(), 0.0, Interpolator.LINEAR)));
rect.setOnMouseClicked(e -> {
if (anim.getStatus() == Status.RUNNING) {
anim.pause();
} else {
anim.setRate(Math.random() * 5.0);
anim.play();
System.out.println(anim.getRate());
}
});
The problem I am facing is that when I click the rectangle multiple times, the size will randomly jump around, instead of just changing the speed at which it drops. So for example, I let it run to about 50% size at speed ~2.5 and then stop it. When I start it up again, it will jump to a totally different size, smaller for a lower speed, bigger for a higher speed, so for example to ~20% for ~1.0 speed or ~80% for ~4.5 speed.
At first I thought animation was pre-calculated for the new speed and thus jumped to the position at which it would be, had it been played with the new speed from the beginning for the time that it was already playing before the pause, but it's bigger for a smaller speed, which doesn't really make sense then.
How do I change the speed/rate of an animation without having it jump around?
I think your diagnosis is correct: the current value is interpolated given the current time and current rate. If you decrease the rate without changing the current time, you are then earlier in the animation. Since the animation is shrinking this has the effect of making the rectangle bigger.
The easiest way is probably just to start a new animation each time:
import javafx.animation.Animation;
import javafx.animation.Animation.Status;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class VariableRateAnimation extends Application {
private Animation anim ;
#Override
public void start(Stage primaryStage) {
Pane mainPane = new Pane();
Rectangle rect = new Rectangle(100.0, 10.0);
mainPane.getChildren().add(rect); //so the rectangle is on screen
rect.setOnMouseClicked(e -> {
if (anim != null && anim.getStatus() == Status.RUNNING) {
System.out.println("Paused (" + anim.getTotalDuration().subtract(anim.getCurrentTime())+ " remaining)");
anim.pause();
} else {
Duration duration = Duration.seconds(30.0 * rect.getWidth() / (100 * Math.random() * 5.0));
System.out.println("Starting: ("+duration+ " to go)");
double currentWidth = rect.getWidth() ;
if (anim != null) {
anim.stop();
}
anim = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(rect.widthProperty(), currentWidth, Interpolator.LINEAR)),
new KeyFrame(duration, new KeyValue(rect.widthProperty(), 0.0, Interpolator.LINEAR)));
anim.play();
}
});
primaryStage.setScene(new Scene(mainPane, 600, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
can you please tell me how i can change the color gradient in the following piece of code? In my code im trying to control the color gradient from here:
for( Marker marker : countryMarkers ) {
for( i=0; i<255; i++ ){
marker.setColor(color(255, i, 0));
}
}
Unfortunately im getting one color only. Can you help please?
import de.fhpotsdam.unfolding.mapdisplay.*;
import de.fhpotsdam.unfolding.utils.*;
import de.fhpotsdam.unfolding.marker.*;
import de.fhpotsdam.unfolding.tiles.*;
import de.fhpotsdam.unfolding.interactions.*;
import de.fhpotsdam.unfolding.ui.*;
import de.fhpotsdam.unfolding.*;
import de.fhpotsdam.unfolding.core.*;
import de.fhpotsdam.unfolding.mapdisplay.shaders.*;
import de.fhpotsdam.unfolding.data.*;
import de.fhpotsdam.unfolding.geo.*;
import de.fhpotsdam.unfolding.texture.*;
import de.fhpotsdam.unfolding.events.*;
import de.fhpotsdam.utils.*;
import de.fhpotsdam.unfolding.providers.*;
import java.util.List;
UnfoldingMap map;
void setup() {
size(800, 600);
int i=0,k=15;
map = new UnfoldingMap(this, new Microsoft.AerialProvider());
Location cyprusLocation = new Location(35f, 33f);
map.zoomAndPanTo(cyprusLocation, 11);
float maxPanningDistance = 30; // in km
map.setPanningRestriction(cyprusLocation, maxPanningDistance);
//map = new UnfoldingMap(this);
MapUtils.createDefaultEventDispatcher(this, map);
List<Feature> countries = GeoJSONReader.loadData(this, "Dasos.geo.json");
List<Marker> countryMarkers = MapUtils.createSimpleMarkers(countries);
map.addMarkers(countryMarkers);
/*
for (Marker marker : countryMarkers) {
// marker.setColor(color(255, 0, 0));
}
*/
for (Marker marker : countryMarkers) {
for(i=0;i<255;i++){
marker.setColor(color(255, i, 0));
}
}
}
void draw() {
map.draw();
}
void keyPressed() {
if (key == ' ') {
map.getDefaultMarkerManager().toggleDrawing();
}
}
You have a nested loop, so you are setting each marker with every color, from (255, 0 ,0) until (255, 255, 0), before displaying it. At the end they are all left with the same last color in the inner loop...
You might just use a regular for loop to traverse the array, so you can use the index as part of color(). But you need to mind somehow the maximum numbers, something like:
(note you were missing the int inside regular for loop)
for(int i = 0; i < countryMarkers.length; i++){
countryMarkers[i].setColor(color(255, (i%255), 0));
}
or just use an incremented var inside the for each instead the index...
for (Marker marker : countryMarkers) {
marker.setColor(color(255, (otherVar++)%255, 0));
}
I'm working on a card game based on the NetBeans platform and I'm struggling to get my head around dynamic images. Why dynamic? Well I want the cards to adjust at run time to changes to the page (i.e. name, text, cost, etc).
My first hack at it was creating a component (JPanel) with labels pre-placed where I loaded the text/image based on the card values. That seems to work fine but then it became troublesome when I thought about some pages having a different look in later editions (meaning not everything would be on the same place).
So I'm trying to get an idea about ways to do this based on some kind of template.
Any idea?
There's a follow-up question at: JList of cards?
Finally I got some time to get back to this and was able to figure out a way using Java 2D tutorial.
The pictures are not near what I will use in my application but serves as proof of concept.
package javaapplication3;
import java.awt.*; import java.awt.font.FontRenderContext; import
java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute;
import java.awt.font.TextLayout; import java.awt.image.BufferedImage;
import java.io.File; import java.io.IOException; import
java.net.MalformedURLException; import java.net.URL; import
java.text.AttributedCharacterIterator; import
java.text.AttributedString; import java.util.ArrayList; import
java.util.HashMap; import java.util.logging.Level; import
java.util.logging.Logger; import javax.imageio.ImageIO;
/** * * #author Javier A. Ortiz Bultrón
*/ public class DefaultImageManager {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
// TODO code application logic here
DefaultImageManager manager = new DefaultImageManager();
URL url = DefaultImageManager.class.getResource("weather-rain.png");
manager.getLayers().add(ImageIO.read(url));
url = DefaultImageManager.class.getResource("weather-sun.png");
manager.getLayers().add(ImageIO.read(url));
manager.addText(new Font("Arial", Font.PLAIN, 10), "Many people believe that Vincent van Gogh painted his best works "
+ "during the two-year period he spent in Provence. Here is where he "
+ "painted The Starry Night--which some consider to be his greatest "
+ "work of all. However, as his artistic brilliance reached new "
+ "heights in Provence, his physical and mental health plummeted. ",
200, 150, new Point(0, 0));
manager.generate();
} catch (MalformedURLException ex) {
Logger.getLogger(DefaultImageManager.class.getName()).log(Level.SEVERE,
null, ex);
} catch (IOException ex) {
Logger.getLogger(DefaultImageManager.class.getName()).log(Level.SEVERE,
null, ex);
}
}
/**
* Layers used to create the final image
*/
private ArrayList layers = new ArrayList();
private ArrayList textLayers = new ArrayList();
/**
* #return the layers
*/
public ArrayList<BufferedImage> getLayers() {
return layers;
}
private Dimension getMaxSize() {
int width = 0, height = 0;
for (BufferedImage img : getLayers()) {
if (img.getWidth() > width) {
width = img.getWidth();
}
if (img.getHeight() > height) {
height = img.getHeight();
}
}
return new Dimension(width, height);
}
public void addText(Font font, String text, int height, int width, Point location) {
BufferedImage textImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
HashMap<TextAttribute, Object> map =
new HashMap<TextAttribute, Object>();
map.put(TextAttribute.FAMILY, font.getFamily());
map.put(TextAttribute.SIZE, font.getSize());
map.put(TextAttribute.FOREGROUND, Color.BLACK);
AttributedString aString = new AttributedString(text, map);
AttributedCharacterIterator paragraph = aString.getIterator();
// index of the first character in the paragraph.
int paragraphStart = paragraph.getBeginIndex();
// index of the first character after the end of the paragraph.
int paragraphEnd = paragraph.getEndIndex();
Graphics2D graphics = textImage.createGraphics();
FontRenderContext frc = graphics.getFontRenderContext();
// The LineBreakMeasurer used to line-break the paragraph.
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
// Set break width to width of Component.
float breakWidth = width;
float drawPosY = 0;
// Set position to the index of the first character in the paragraph.
lineMeasurer.setPosition(paragraphStart);
// Get lines until the entire paragraph has been displayed.
while (lineMeasurer.getPosition() < paragraphEnd) {
// Retrieve next layout. A cleverer program would also cache
// these layouts until the component is re-sized.
TextLayout layout = lineMeasurer.nextLayout(breakWidth);
// Compute pen x position. If the paragraph is right-to-left we
// will align the TextLayouts to the right edge of the panel.
// Note: this won't occur for the English text in this sample.
// Note: drawPosX is always where the LEFT of the text is placed.
float drawPosX = layout.isLeftToRight()
? 0 : breakWidth - layout.getAdvance();
// Move y-coordinate by the ascent of the layout.
drawPosY += layout.getAscent();
// Draw the TextLayout at (drawPosX, drawPosY).
layout.draw(graphics, drawPosX, drawPosY);
// Move y-coordinate in preparation for next layout.
drawPosY += layout.getDescent() + layout.getLeading();
}
getTextLayers().add(textImage);
}
public void generate() throws IOException {
Dimension size = getMaxSize();
BufferedImage finalImage = new BufferedImage(size.width, size.height,
BufferedImage.TYPE_INT_ARGB);
for (BufferedImage img : getLayers()) {
finalImage.createGraphics().drawImage(img,
0, 0, size.width, size.height,
0, 0, img.getWidth(null),
img.getHeight(null),
null);
}
for(BufferedImage text: getTextLayers()){
finalImage.createGraphics().drawImage(text,
0, 0, text.getWidth(), text.getHeight(),
0, 0, text.getWidth(null),
text.getHeight(null),
null);
}
File outputfile = new File("saved.png");
ImageIO.write(finalImage, "png", outputfile);
}
/**
* #return the textLayers
*/
public ArrayList<BufferedImage> getTextLayers() {
return textLayers;
}
/**
* #param textLayers the textLayers to set
*/
public void setTextLayers(ArrayList<BufferedImage> textLayers) {
this.textLayers = textLayers;
} }
It still needs some refining specially on the placement of the text but it works. I guess I can implement a xml format to store all this information so is easily configurable. In the example below suns are drawn on top of rain, and the text is on top of all that. For my application each layer will build together the page I want.
Here are the images I used:
And the final result: