JavaFX ImageView without any smoothing - javafx

Is it possible to render a scaled image in an ImageView in JavaFX 2.2 without any smoothing applied? I'm rendering a 50x50 image into a 200x200 ImageView, with setSmooth(false), so each pixel in the source image should map to a 4x4 square on the screen.
However, the resulting render still smooths the source pixel across all 16 destination pixels. Does anyone know of a way to do this without manually copying over each pixel into a new image?

In JavaFX 2.2 ImageView is always going to do some smoothing regardless of the smooth hint you provide to the ImageView.
(Based on testing using Java 7u15 and Windows 7 with an ATI HD4600 graphics card).
Perhaps it is a bug that ImageView will always smooth the Image, but the documentation doesn't really specify exactly what smoothing does or doesn't do, so it's hard to say what its real intent is. You may want to post a reference to this question to the openjfx-dev mailing list or log an issue in the JavaFX issue tracker to get a more expert opinion from a developer.
I tried a few different methods for scaling the Image:
Scale in the Image constructor.
Scale in ImageView with fitWidth/fitHeight.
Scale by using the scaleX/scaleY properties on an ImageView.
Scale by sampling the Image with a PixelReader and creating a new Image with a PixelWriter.
I found that methods 1 & 4 resulted in a sharp pixelated image as you wish for and 2 & 3 resulted in a blurry aliased image.
Sample code to generate the above output.
Update with ideas on implementing your own image filter
A JavaFX Effect is not the same as the Filter used for the Image loading routines, though an Effect to filter an image could be created. In JavaFX 2.2 publicly documented API to support creation of custom effects, so creating of a custom effect may prove difficult.
The native code for image support was recently open sourced as part of the openjfx project, so you could look at that to see how the filtering is currently implemented.
You may also want to file a feature request against the JavaFX runtime project to "allow us to make our own 2D filters".

I know this is a bit older, but I recently had a need for such ImageView, and the following little hack does exactly what I want on my (Windows) machine. No guarantees that it works everywhere.
import com.sun.javafx.sg.prism.NGImageView;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.prism.Graphics;
import com.sun.prism.Texture;
import com.sun.prism.impl.BaseResourceFactory;
import com.sun.prism.Image;
import javafx.scene.image.ImageView;
#SuppressWarnings("restriction")
public class PixelatedImageView extends ImageView {
#Override protected NGNode impl_createPeer() {
return new NGImageView() {
private Image image;
#Override public void setImage(Object img) {
super.setImage(img);
image = (Image) img;
}
#Override protected void renderContent(Graphics g) {
BaseResourceFactory factory = (BaseResourceFactory) g.getResourceFactory();
Texture tex = factory.getCachedTexture(image, Texture.WrapMode.CLAMP_TO_EDGE);
tex.setLinearFiltering(false);
tex.unlock();
super.renderContent(g);
}
};
}
}
The trick here is that the texture gets re-used, so the linear filtering setting remains "sticky". Why NGImageView couldn't simply pass the "smooth" flag to the texture's linear filtering setting is beyond me however.

No fix for ImageView, but it helped me a lot.
After searching for ages, I stumbled upon this post: How can I disable antialiasing on a JavaFX Canvas?
For drawing the image on a canvas, the smoothing can be disabled since JavaFX 12
canvas.getGraphicsContext2D().setImageSmoothing(false);

When you add the following constructor to Martin Sojka's answer you can simply pass the javafx Image to the constructor. Also despite the warnings about deprecated functions his answer still works fine (on JDK 1.8_121).
public PixelatedImageView (javafx.scene.image.Image image) {
super(image);
}

Related

Pixelated gif in QT

I'm trying to show a gif file in QT app, using the approach provided in the link: https://code.qt.io/cgit/qt/qtbase.git/tree/examples/widgets/widgets/movie?h=5.15
Approach makes use of QMovie object set in a QLabel.
The example works well and fine.
But if I enable High DPI scaling for the app, the gif becomes all pixelated. Please see the screenshots below.
This is the line that I add to enable High DPI scaling.
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
Any ideas to get this fixed ?
I have tried the following fixes already:
setScaledSize for the QMovie object
setScaledContents(true) for the QLabel
QT version I'm using is 5.15.2 and platform is Windows.
A GIF picture cannot have more than 256 unique colours. When you load such an image into Qt, it is internally represented in that exact format with the palette (of 256 colours) from the GIF representation, even if your hardware might be able to display many more colours.
This also means that when you scale such an image, Qt is not allowed to extend the colour space to render in-between colours - This means that scaled GIF pictures generally have to look much worse than scaled high-colour images.
The solution to this is either to transform the QImage you created from a GIF picture into a format with a larger colour space before scaling it (with QImage::convertToFormat) or, better still, don't use GIF images at all. After all, GIF is a format developed 30 years ago and has never really been updated to adapt to modern hardware, and using it, you artificially limit your programs to the capabilities of that format.
It seems at this moment there is no way to render sharp gifs when scaled using QMovie and QLabel. I have filed a bug for the same in QT bug tracker.
Meanwhile I have found a workaround that works fine. It is done making use of QML in the QWidget system, using QQuickWidget.
Let me add the full steps here, so that it is helpful to anyone else who run into this problem:
First we need to add support for Qml and QuickWidgets. I use CMake and Visual Studio. Hence I add the below lines in the CMakeLists.txt file. Equivalent changes needs to be made in the .pro file, if QT Creator is used instead.
# I'm only adding the relevant lines for brevity
find_package(Qt5 COMPONENTS Qml QuickWidgets)
target_link_libraries(${APP_TARGET_NAME}
Qt5::Qml
Qt5::QuickWidgets)
# Note the --qmldir switch
add_custom_command (TARGET ${APP_TARGET_NAME} POST_BUILD
COMMAND ${QTDIR}/bin/windeployqt
--qmldir ${CMAKE_CURRENT_SOURCE_DIR}/qml
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${APP_TARGET_NAME}.exe)
Then create a spinner.qml file inside a folder named qml:
import QtQuick 2.15
Rectangle {
width: 12
height: 12
AnimatedImage {
y: 5
width: 12
height: 12
id: spinner
source: "img/spinner.gif"
speed: 1.0
}
}
And then load the qml file using QQuickWidget and add the QQuickWidget instance to the QWidget layout.
QHBoxLayout *main_layout = new QHBoxLayout();
auto *spinner_gif = new QQuickWidget(QUrl::fromLocalFile(":/spinner.qml"));
main_layout->addWidget(spinner_gif);
this->setLayout(main_layout);
The gif that shows up won't be pixelated even when scaled and we can see the GPU in use, in the Task Manager, as expected for a QQuickWidget.

Generate thumbnail from stage for react-konva

I have created a react app Which is very similar to office whiteboard. I would like to generate a thumbnail or card preview of each whiteboard and wondering how to go about it.
My initial thought was to just create a card component and render the shapes to that the same way I do for the real whiteboard. However, the points for each shape will be outside the stage and I can't think of how I can scale it down.
Any ideas?
Take a look at the official canvas thumbnail demo from Konva.
You can use a similar approach with react-konva.
Create a special component for the preview.
I think this approach will work better and probably more performant (depending on your app). You just need to create another Stage and draw all objects into it. It will be better if you can draw simplified versions of the shape, because the drawing is much smaller, so not all details are visible.
You will have to calculate your own scale ratio.
Use image preview
Instead of making a full components tree for the whiteboard, you can just export the main stage into an image and show it. You have to do reexport from time to time.

How do I make content within a JavaFX Scene transparent?

The program below is an example of what I'm actually trying to achieve.
I'm trying to do is recreate the picture above in JavaFX. However I am having difficulties because when I set the content of my stage to transparent it doesn't actually go transparent it still remains white.
#Override
public void start(Stage stage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root,400,400);
root.setStyle("-fx-background-color: rgba(0,0,0,0);");
scene.setFill(Color.TRANSPARENT);
stage.setScene(scene);
stage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
The stage is visible from this code. I also set the content to transparent and changed the default style of the root pane to transparent.
I don't understand why this doesn't work, I'm setting the content to transparent but the background is still not transparent.
The result from the code I posted shows this, as you can see it's not transparent.
This question is almost a duplicate of:
how to make transparent scene and stage in javafx?
The difference being that it is also asking to retain native window decorations, which is not possible with StageStyle.TRANSPARENT.
If you look closely at the sample windows provided in the question, the decoration areas differ slightly (e.g. one includes a stage icon in the upper left and the other does not). My guess is that the transparent window pictured in the question isn't actually using the OS window decorations at all, but is instead rendering its own decorations which look much like the OS window decorations (that is just a guess though).
Anyway, to achieve a similar effect with JavaFX, it is necessary that JavaFX be used to render the window decorations rather than the OS window manager. To do that, refer to the following question:
JavaFX entirely customized windows?
In particular take a look at the Undecorator library:
https://github.com/in-sideFX/UndecoratorBis
You will never be able to get the window decorations to exactly match the OS Window manager decorations, but you can create something that looks different and provides similar functionality. If you work at it, you might be able to achieve something that matches the OS window decorations pretty closely, similar to the window screenshot in your question. Though, if it were me, I would just go for a different look which was still clean and easily comprehensible by the user, similar to the default look provided by Undecorator.
Do you think this could be pulled off by creating an ImageView and using some sort of stage listener so when the stage is moved the imageview displays a new image of what's behind the application? Or is that overly complicating it?
The background capture to imageView approach is a reasonable alternate approach.
If you do want to use the imageView capture approach, you can use some of the ideas from the following answer:
JavaFX effect on background
Note that the imageView capture type answer linked above won't completely accomplish what you wish and you still need to do some additional custom work to get exactly the effect you need as you move the stage around or as the desktop or windows under your window change. Possibly you may need to resort to logic outside of JavaFX to fully realize your goal, and discussion of how to do that is outside the scope of what I would be prepared (or able) to discuss here.
It's complicated no matter what you do, I don't really have a recommendation between the undecorator or the imageView capture approach.
Maybe if you mix JavaFX and Swing/AWT you may be able to do this by using a JFXPanel and the AWT PERPIXEL_TRANSPARENT feature. I haven't tried this combo, but per pixel settings for AWT are demonstrated in this oracle sample as discussed in How to Implement Per-Pixel Translucency.

Flex - Subclassing VBox in MXML to use as a base component, advice needed

I'd like to extend VBox to add some "defaults" and a bit of boilerplate-ish code (let's call it "VBoxSub" here), the idea being that "pages" in the application would extend this VBox subclass.
This seems to work fine except that the final classes extending "VBoxSub" don't inherit the width/height settings set in VBoxSub when in Flash Builder's design mode. When switching to design mode with the component empty, all it shows is a tiny plain box instead of a larger 1000x700 working area with the default VBox css background color. What's going on here? (Yeah I've tried refreshing/restarting design view.)
I'd like to have each of these components all be exactly the same size so that when laying out the UI I know exactly how much space I have to work with - preferably without having to copy/paste the width and height attributes into every darn mxml file (and having to worry about updating each one if the w/h ever change!). (Using Flash Builder 4, SDK 4.1)
I've tried doing this to get it to work, but still no good in Design View:
override protected function measure():void {
super.measure();
measuredWidth=1000;
measuredMinWidth=1000;
measuredHeight=700;
measuredMinHeight=700;
}
Do I really need to hard code width/height in every component "page" within the application?
Flash Builder doesn't execute Actionscript in design mode. Since the AS code doesn't get executed, the VBox doesn't get measured in design mode.
You need to use declarative MXML in such a situation.

Advanced Image cropping and image resizing in Flex

I have created a image cropping tool in flex using core copyPixel method.
croppedBitmapData.copyPixels(croppedBitmapData, clipCan, new Point(0, 0));
I have to crope area of dementions 20*20 and show this cropped area in an image of demention 250*350.
Every thing going well.
My problem is image distortion.
Even i am using this method for smoothing image contents on complete.
private function smoothImage(event:Event):void
{
var bitmap: Bitmap = ((event.target as Image).content as Bitmap);
if (bitmap != null)
{
bitmap.smoothing = true;
}
}
I want to get the result of this site. http://www.yourplayingcards.com/builder/
Please help me to get ride of image distortion.
Can we show bitmapdata of 20*20 into image of 250*350 without distotion?
What you call 'distortion' is probably what I think you mean by pixelation. The reason why that website can zoom in without pixelation is because it's using vector shapes, not bitmaps, to show the graphics. Vector shapes can be scale infinitely without loss of quality because it doesn't store pixel information, but spline information.
In essence, if you want to imitate the zooming of the the website you have shown, you will have to create your own vector shape. You can use Flex 4's built in FXG format or use something like Degrafa if you're still in Flex 3. You can also leverage Flash Catalyst to import vector graphics made in Illustration into Flex.
I am not sure about that but it is done in VectorMagic may be they are using server side too any ways, you may also interested in Actionscript SVG renderer
Hopes that helps

Resources