I need to print a Bitmap on a PDF Document without loosing the image quality.
The thing is Bitmap has always few times large width & height than the A4 sheet. So there may be two options to achieve the expected output.
Scaled the Bitmap and then print on A4 size PDF Page.
Print the Bitmap as it is on a PDF page and the scaled down the PDF Page.
Option No.1 is not gave the result as what I expected. Yes it print on A4 size PDF with correct dimensions and the position, but the image quality is worst and it's totally unusable after scale the Bitmap.
Option No.2 will work (at least I hope so), but the thing is I don't know how to scaled down the PDF page with the content on it.
So please give me help to get the output as I expected.
Option 1 Codes Sample
//boolean img1_SetImage - used to check Img1 is available or not
//img1_Uri - Uri of Img1
if (img1_SetImage) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false;
Bitmap bmp = BitmapFactory.decodeFile(img1_Uri.getPath(), opt);
int[] xyImg = xy(bmp.getWidth(), bmp.getHeight(), 298, 175);
PdfDocument.PageInfo myPageInfo2 =
new PdfDocument.PageInfo.Builder(595, 842, 1).create();
PdfDocument.Page myPage2 = myPDFDoc.startPage(myPageInfo2);
Canvas myCanvas2 = myPage2.getCanvas();
Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, xyImg[0], xyImg[1], false);
myCanvas2.drawBitmap(scaledBmp, xyImg[2], xyImg[3], new Paint(Paint.FILTER_BITMAP_FLAG));
bmp.recycle();
scaledBmp.recycle();
}
private int[] xy(float width, float height, float left, float top) {
int finalWidth, finalHeight, finalLeft, finalTop;
float wScale, hScale, scaleFactor;
wScale = (436 / width);
hScale = (270 / height);
if (wScale >= hScale) {
scaleFactor = hScale;
} else {
scaleFactor = wScale;
}
finalWidth = (int) (width * scaleFactor);
finalHeight = (int) (height * scaleFactor);
finalLeft = (int) (left - (finalWidth / 2));
finalTop = (int) (top - (finalHeight / 2));
int[] returnValues = {finalWidth, finalHeight, finalLeft, finalTop};
return returnValues;
}
Thanks.
I'm remaking the design of an old javafx app and I need to include an icon for the wifi strength. The designer sent me an svg icon for that, and I thought it was smarter to just keep one icon and use different fill colors for the 3 bars depending of the said wifi strength.
I found a nice approach for that, and it works quite well until you need to resize the wifi icon. It seems like even if I change the -fx-pref-width (or height, or min/max) the svg icon keeps its size.
I also tried to resize each svg path one by one but it only goes messy with the spaces between them. And using a unique shape to resize later is not an option, as I need at least 2 colors. FYI the goal is to apply a 5em or 3em size depending of the context.
Here's the code I currently have, where everything looks great if you don't matter the icon size :
public class WifiStrengthRegion extends Pane {
public WifiStrengthRegion() {
getStyleClass().setAll("wifi-strength");
SVGPath round = new SVGPath();
SVGPath bar1 = new SVGPath();
SVGPath bar2 = new SVGPath();
SVGPath bar3 = new SVGPath();
round.setContent("M253.5,336.5c-18.9,0-34.2,15.3-34.2,34.1c0,18.8,15.4,34.1,34.2,34.1c18.9,0,34.2-15.3,34.2-34.1 C287.7,351.8,272.4,336.5,253.5,336.5z");
bar1.setContent("M337,290.1c-22.3-22.3-51.9-34.5-83.5-34.5c-31.4,0-61,12.2-83.3,34.3c-9,9-9,23.5,0,32.5 c4.4,4.4,10.2,6.8,16.3,6.8c6.2,0,11.9-2.4,16.3-6.7c13.6-13.5,31.6-20.9,50.7-20.9c19.2,0,37.3,7.5,50.8,21 c4.4,4.4,10.2,6.8,16.3,6.8c6.2,0,11.9-2.4,16.3-6.7C346,313.6,346,299,337,290.1z");
bar2.setContent("M389.3,238c-36.3-36.2-84.5-56.1-135.8-56.1c-51.2,0-99.3,19.9-135.6,55.9c-4.4,4.3-6.8,10.1-6.8,16.3 c0,6.1,2.4,11.9,6.7,16.3c4.4,4.3,10.2,6.7,16.3,6.7c6.2,0,11.9-2.4,16.3-6.7c27.5-27.4,64.1-42.5,103-42.5 c39,0,75.6,15.1,103.1,42.6c4.4,4.4,10.2,6.8,16.3,6.8c6.2,0,12-2.4,16.3-6.7c4.4-4.3,6.8-10.1,6.8-16.3 C396,248.1,393.6,242.3,389.3,238z");
bar3.setContent("M444.3,183.2c-50.9-50.8-118.7-78.8-190.8-78.8c-72,0-139.7,27.9-190.6,78.6c-9,9-9,23.5,0,32.5 c4.4,4.3,10.2,6.7,16.3,6.7c6.2,0,12-2.4,16.3-6.7c42.2-42,98.3-65.2,158-65.2c59.7,0,115.9,23.2,158.1,65.3 c4.4,4.3,10.2,6.7,16.3,6.7c6.2,0,11.9-2.4,16.3-6.7C453.2,206.7,453.3,192.1,444.3,183.2z");
round.getStyleClass().add("wifi-base");
bar1.getStyleClass().add("wifi-bar1");
bar2.getStyleClass().add("wifi-bar2");
bar3.getStyleClass().add("wifi-bar3");
this.getChildren().addAll(round, bar1, bar2, bar3);
}
public void setWifiStrength(Integer strength) {
if (strength == null) {
setManaged(false);
setVisible(false);
} else {
setManaged(true);
setVisible(true);
getStyleClass().removeAll("wifi-excellent", "wifi-good", "wifi-fair", "wifi-weak", "wifi-off");
if (strength < 0 && strength >= -100) {
if (strength >= -50) {
getStyleClass().add("wifi-excellent");
} else if (strength >= -70) {
getStyleClass().add("wifi-good");
} else if (strength >= -80) {
getStyleClass().add("wifi-fair");
} else {
getStyleClass().add("wifi-weak");
}
} else {
getStyleClass().add("wifi-off");
}
}
}
}
(and then a css stylesheet applies -fx-fill to each .wifi-barX depending of the main element class)
And here is an example of how the svg icon looks like:
I'm a very beginner in Java (and obv JavaFX), so any constructive criticism will be appreciated!
If you want to resize only (I hope this works):
public void resize(SVGPath svg, double width, double height) {
this.width = width;
this.height = height;
double originalWidthR = svg.prefWidth(-1);
double originalHeightR = svg.prefHeight(originalWidthR);
double scaleXr = width / originalWidthR;
double scaleYr = height / originalHeightR;
svg.setScaleX(scaleXr);
svg.setScaleY(scaleYr);
}
And if you want to set bounds use this:
public void setBounds(SVGPath svg, double width, double height, double x, double y) {
this.width = width;
this.height = height;
double originalWidthR = svg.prefWidth(-1);
double originalHeightR = svg.prefHeight(originalWidthR);
double scaleXr = width / originalWidthR;
double scaleYr = height / originalHeightR;
svg.setScaleX(scaleXr);
svg.setScaleY(scaleYr);
svg.setLayoutX((originalWidthR - width) + x);
svg.setLayoutY((originalHeightR - height) + y);
}
I am struggling to bind some text specified coordinates so that when I resize the window the text follows suit. Here is the portion of my code:
for (int i = 0; i < petrolStations.size() / 2; i++) {
int j = i + 1;
Text text1 = new Text(petrolStations.get(i), petrolStations.get(j), "1");
text1.setFont(Font.font("Courier", FontWeight.BOLD, FontPosture.ITALIC, 10));
text1.xProperty().bind(pane.widthProperty().divide(2));
text1.yProperty().bind(pane.heightProperty().divide(2));
pane.getChildren().add(text1);
To explain: petrolStations is an array of coordinates that are used to place a letter 1 on the page.
Here is the current output, as you can see all the 1's are combining in the middle rather than being in their specified coordinates.
EDIT:
I've changed the 1's to circles and managed to scale up the size but I still have the same problem, since all the coordinates are under 100 they sit up the top left, I need them to encompass the whole window and expand and separate as the window is resized larger.
for (int i = 0; i < petrolStations.size() / 2; i++) {
int j = i + 1;
Circle circle1 = new Circle();
circle1.setCenterX(petrolStations.get(i));
circle1.setCenterY(petrolStations.get(j));
circle1.setRadius(1);
circle1.setStroke(Color.BLACK);
circle1.setFill(Color.WHITE);
circle1.setScaleX(3);
circle1.setScaleY(3);
pane.getChildren().add(circle1);
}
http://i.imgur.com/JkV3LiW.png
Why not take the ratio of x and y with respect to the width/height? Take a look at this:
Pane pane = new Pane();
Text text = new Text(250,250,"1");
pane.getChildren().add(text);
double width = 150;
double height = 150;
Scene scene = new Scene(pane, width, height);
double x = 50;
double y = 50;
double xRatio = x / width; //GET THE RATIO
double yRatio = y / width; //GET THE RATIO
text.xProperty().bind(pane.widthProperty().multiply(xRatio));
text.yProperty().bind(pane.heightProperty().multiply(yRatio));
stage.setTitle("Hello World!");
stage.setScene(scene);
stage.show();
When I run this code, the initial state is:
Upon resizing:
For context: I am going to analyze the breathing movement of parents during kangaroo mother care and I wish to respect their privacy by not recording them, but only the movement of stickers I placed on their chest and stomach.
So far, I'm able to track 2 colours based on webcam input through the code below. However, I would like to record only the tracked colours instead of the webcam feed as to preserve the privacy of the parent.
Does anybody know how to add a background colour, whilst still being able to track colour?
import processing.video.*;
Capture video;
final int TOLERANCE = 20;
float XRc = 0;// XY coordinate of the center of the first target
float YRc = 0;
float XRh = 0;// XY coordinate of the center of the second target
float YRh = 0;
int ii=0; //Mouse click counter
color trackColor; //The first color is the center of the robot
color trackColor2; //The second color is the head of the robot
void setup() {
size(640,480);
video = new Capture(this,640,480);
video.start();
trackColor = color(255,0,0);
trackColor2 = color(255,0,0);
smooth();
}
void draw() {
background(0);
if (video.available()) {
video.read();
}
video.loadPixels();
image(video,0,0);
float r2 = red(trackColor);
float g2 = green(trackColor);
float b2 = blue(trackColor);
float r3 = red(trackColor2);
float g3 = green(trackColor2);
float b3 = blue(trackColor2);
int somme_x = 0, somme_y = 0;
int compteur = 0;
int somme_x2 = 0, somme_y2 = 0;
int compteur2 = 0;
for(int x = 0; x < video.width; x++) {
for(int y = 0; y < video.height; y++) {
int currentLoc = x + y*video.width;
color currentColor = video.pixels[currentLoc];
float r1 = red(currentColor);
float g1 = green(currentColor);
float b1 = blue(currentColor);
if(dist(r1,g1,b1,r2,g2,b2) < TOLERANCE) {
somme_x += x;
somme_y += y;
compteur++;
}
else if(compteur > 0) {
XRc = somme_x / compteur;
YRc = somme_y / compteur;
}
if(dist(r1,g1,b1,r3,g3,b3) < TOLERANCE) {
somme_x2 += x;
somme_y2 += y;
compteur2++;
}
else if(compteur2 > 0) {
XRh = somme_x2 / compteur2;
YRh = somme_y2 / compteur2;
}
}
}
if(XRc != 0 || YRc != 0) { // Draw a circle at the first target
fill(trackColor);
strokeWeight(0.05);
stroke(0);
ellipse(XRc,YRc,20,20);
}
if(XRh != 0 || YRh != 0) {// Draw a circle at the second target
fill(trackColor2);
strokeWeight(0.05);
stroke(0);
ellipse(XRh,YRh,20,20);
}
}
void mousePressed() {
if (mousePressed && (mouseButton == RIGHT)) { // Save color where the mouse is clicked in trackColor variable
if(ii==0){
if (mouseY>480){mouseY=0;mouseX=0;}
int loc = mouseX + mouseY*video.width;
trackColor = video.pixels[loc];
ii=1;
}
else if(ii==1){
if (mouseY>480){mouseY=0;mouseX=0;}
int loc2 = mouseX + mouseY*video.width;
trackColor2 = video.pixels[loc2];
ii=2;
}
}
}
Try adding the background(0); right before you draw the first circle. It should cover the video and you can draw the circles on top of it.
Regards
Jose
I'm trying to create a scrollView, but I don't know how to determine the maximum range of the scroll (or even better, the maximum scroll position).
This is what I have tried to do without any positive results:
void Update()
{
//get the amount of space that my text is taking
textSize = gs.CalcHeight(new GUIContent(text), (screenWidth/2));
if(Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved && Input.GetTouch(0).tapCount==1)
{
var touch = Input.touches[0];
//check if touch is within the scrollView area
if(touch.position.x >= (screenWidth/2) && touch.position.x <= (screenWidth) && touch.position.y >= 0 && touch.position.y <= (screenHeight))
{
if(touch.phase == TouchPhase.Moved)
{
scrollPosition[1] += touch.deltaPosition.y;
if(scrollPosition[1] < 0)
{
scrollPosition[1] = 0;
}
//I subtracted this cause i read that the scrollbars take 16px
if(scrollPosition[1] > (textSize-scrollViewRect.yMax-16)) //scrollViewRect is a Rect with the size of my scrollView
{
scrollPosition[1] = textSize-scrollViewRect.yMax-16;
}
}
}
}
}
void OnGUI()
{
screenWidth = camera.pixelWidth;
screenHeight = camera.pixelHeight;
GUILayout.BeginArea(new Rect(screenWidth/2, 0, screenWidth/2, screenHeight));
GUILayout.BeginScrollView(scrollPosition/*, GUILayout.Width (screenWidth/2), GUILayout.Height (screenHeight/2)*/, "box");
GUILayout.Label (new GUIContent(text), gs);
// End the scrollview
GUILayout.EndScrollView ();
scrollViewRect = GUILayoutUtility.GetLastRect();
GUILayout.EndArea();
}
This was done assuming that the scrollView is on the right half of the screen.
Can you guys help me out on this?
Thanks in advance.
As shown in the API documentation for GUI.BeginScrollView, you can assign a Vector2 to the declaration of BeginScrollView to track and update where the box has been scrolled to.
I'll give an example:
using UnityEngine;
using System.Collections;
public class ScrollSize : MonoBehaviour {
private int screenBoxX = Screen.width;
private int screenBoxY = Screen.height;
private int scrollBoxX = Screen.width * 2;
private int scrollBoxY = Screen.height * 3;
public Vector2 scrollPosition = Vector2.zero;
void Awake()
{
Debug.Log ("box size is " + scrollBoxX + " " + scrollBoxY);
}
void OnGUI()
{
scrollPosition = GUI.BeginScrollView(new Rect(0, 0, screenBoxX, screenBoxY),
scrollPosition, new Rect(0, 0, scrollBoxX, scrollBoxY));
GUI.EndScrollView();
// showing 4 decimal places
Debug.Log ("Box scrolled # " + scrollPosition.ToString("F4"));
}
}
For the explanation of this example, let's assume that the screen resolution is 800 by 600.
Therefore the viewable scrollbox on the screen will be 800 wide and 600 high, with the internal area of the scrollbox being 1600 by 1800.
We create the scrollbox by assigning Gui.BeginScrollView() as the value of Vector2, scrollPosition. As the scrollbox is scrolled horizontally and vertically, the Vector2 will update with the scrolled value.
If the scrollbox is scrolled to the top-leftmost position, the value of scrollPosition will be 0,0.
If the scrollbox is scrolled to the bottom-rightmost position, the value of scrollPosition will be 816, 616, the size of the box on screen plus the thickness of the scroll bars.
I know this is 3 years later but maybe it will help others too...
I found that setting the scrollPosition to a very high number will force the scrollbar to the bottom:
scrollPosition.y = 999.9f;
Then you can read the position like this:
scrollPosition = GUILayout.BeginScrollView(scrollPosition,
GUILayout.Width(370),
GUILayout.Height(135));
And it will be set to whatever the maximum is.
Hope this helps!