ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Feb-28-2021 07:12
Attachments:
Like this?
PlotPoints.png

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Feb-28-2021 22:23
Hi David,

By "bitmaps", do you mean an image in standard bitmap format, such as PNG or JPG?

Below are two examples included in ChartDirector that uses bitmap images as data points:

https://www.advsofteng.com/doc/cdjava.htm#customsymbolline.htm

https://www.advsofteng.com/doc/cdjava.htm#scattersymbols.htm

Basically, you can use DataSet.setDataSymbol2 to set use a bitmap image as the symbol:

https://www.advsofteng.com/doc/cdjava.htm#DataSet.setDataSymbol2.htm

Hope this can help.

Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Mar-01-2021 03:38
Hi Peter;

I have it working. But the images are too small. How do I make them larger?

thanks - dave

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-02-2021 01:48
Hi David,

The images are provided by your code. ChartDirector simply includes the images in the chart in its original size. If you think the images are too small, the normal method is to use bigger images.

In your other messages, I notice you create charts with very large size. For example, the fonts are 33 points in size. However, the screen shot you attached shows the font are quite small (something like 8 or 9 points). This means the image created by ChartDirector may have been resized to a smaller size. If it is a web application, may be some HTML or CSS causes the chart to resize to something like 25% of its original size. In this case, your images will also be resized to 25% of its original size by your browser. You may need to use images that are 4 times larger to compensate for the browser resizing.

You can write code to ask ChartDirector to resize the images, but I think it is better if your images are already of the necessary size. Another alternative is to set up the system (such as to modify the web pages) so that it does not resize the image in the first place.

// Exampe code to generate a new image file that is 4x the original size
DrawArea d = new DrawArea();
d.loadPNG(filename);
d.resize(d.getWidth() * 4, d.getHeight() * 4);
d.outPNG(new_filename);

Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Mar-02-2021 08:37
Hi Peter;

How does your program decide how large to render the image for a chart marker? I created one png file set to 300 DPI and it rendered larger than I expected. Then the problem one's listed above are set to 72 DPI and they render too small.

Are you using the DPI setting in the bitmap? If not, what do you assume the DPI to be?

thanks - dave

ps - We generally render at either 300 DPI (screen output) or 1,200 DPI (printer output) so yes, we have these high resolutions being sent to a chart that is maybe 3" x 3".

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-02-2021 15:16
Hi David,

ChartDirector treats the image file like a digital photograph you take with your camera or smart phone and display on the screen or browser. It does not have a definite DPI and any DPI settings are ignored. The image does have a definite pixel size. One pixel on the image will occupy one pixel on the chart.

For example, if your chart is 1000 x 1000 pixels in size, and the image is 100 x 100 pixels in size, then it will be 10% of the size of your chart in width and height, regardless of any DPI meta data embedded in the image.

For your case, you may determine how many pixels you want the image to have, then create the image at that pixel size.

Hope this can help.

Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Mar-03-2021 05:12
Hi Peter;

That fixes it. But I have a feature suggestion. Add a call setDataSymbol5(InputStream, width, height) where the bitmap is passed in as a stream (we have it in memory as a byte[]) and the width/height are the number of pixels size to render it in.

thanks - dave

  Re: How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Mar-01-2021 03:47
Hi again;

Also, how do I set a different marker for each plot point?

thanks - dave

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-01-2021 23:23
Hi David,

The second example in my previous message is an example with a different marker for each plot point.

https://www.advsofteng.com/doc/cdjava.htm#scattersymbols.htm

Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Mar-02-2021 02:10
Hi Peter;

Ok, part of the problem may be how I am creating datasets. I have:

LineLayer scatterLayer;
// ...
double[] yVals = (double[]) dstDataSet.getSeriesYVals().get(serInd);
DataSet ds = scatterLayer.addDataSet(yVals);
double[] xVals = (double[]) dstDataSet.getSeriesXVals().get(serInd);
scatterLayer.setXData(xVals);

I now want to set different markers for each data point in that just added dataset. I don't see how to do that. The example shows adding one point at a time, each as a unique dataset, then setting the marker for that dataset.

??? - thanks - dave

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-02-2021 13:35
Hi David,

Since every data point can have a different image symbol, that means you must have another array that contains the filenames of the symbols for each of the data points. The code is then the same as in the sample code:

string[] symbols = {... the symbols for the data points ...};

for(int i = 0; i < xVals.Length; ++i) {
    c.addScatterLayer(new double[] {xVals[i]}, new double[] {yVals[i]}).getDataSet(0
         ).setDataSymbol2(symbols[i]);
}

The above is for your symbols. If you also have a line connecting the points, please add the LineLayer as usual after the above code.

I just remembered there is another example which is optimized for the case that there are a lot of data points, but only a few symbol types. (Which means each symbol is shared by multiple data points.)

https://www.advsofteng.com/doc/cdnet.htm#multisymbolline.htm

Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by David Thielen on Mar-03-2021 05:29
Hi Peter;

This will, I think, require a major change in our code. Because we set all the values well before setting the markers. Our code is:

XYChart c;
double[] yVals;
lineLayer = c.addLineLayer2();
DataSet cdDataSet = lineLayer.addDataSet(yVals);
// and I can't find where xVals are assigned

Anyways, is there any way to set these markers after that data has all been set?

thanks - dave

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-03-2021 12:08
Hi David,

I assume at some stage, your code can construct an array of text strings, which are the markers, one for each data point. So at that stage, you can set the symbols by using the addScatterLayer code. You can use Layer.moveFront to move them in front of all layers.

If by the time you can create the markers array, your code cannot access the xVals and yVals, so you cannot add the scatter layer, there is another method. You can add a custom label to the data point, in which the label is the symbol. You can even resize it in the process. It is like:

Layer myLayer = .... the LineLayer you created earlier in other parts of the code ...;

String[] markers = ... the array of text strings as the markers of the data points, or null if the point has no symbol ...;

// Add the markers as a custom label centered on the data point. The labels is of the form
// <*img=filename,width=w,height=h*>
for (int i = 0; i < markers.Length; ++i) {
    if (markers[i] != null) {
        myLayer.addCustomDataLabel(0, i, "<*img=" + markers[i] + ",width=" + desiredWidth + "," height=" + desiredHeight + "*>").setAlignment(Chart.Center);
    }
}

With the above method, you lose the capability to add another data label to the data point, as the label is already used for the symbol. To work around, you can add another transparent line the LineLayer (you can add multiple lines to a LineLayer - see the Multi Line Chart sample code), and add the labels to the transparent line.


Yet another method is to add the scatter layers at the time you have access to the data, and then add the symbols later.

// member variable
ScatterLayer[] markerLayers;

// add the scatter layers when you have access to the data arrays
markerLayers = new ScatterLayer[xVals.Length];
for(int i = 0; i < xVals.Length; ++i) {
    markerLayers[i] = c.addScatterLayer(new double[] {xVals[i]}, new double[] {yVals[i]});
}

.... later you can set the symbols when you no longer have access to the data arrays .....

for (int i = 0; i < markerLayers.Length; ++i)
    markerLayers[i].setDataSymbol2(symbols[i]);


Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-03-2021 12:54
Hi David,

You mentioned you cannot find where the xVals are used. In my previous I used xVals because in your code the xVals are available:

double[] xVals = (double[]) dstDataSet.getSeriesXVals().get(serInd);

In ChartDirector, the xVals are optional. If your code do not use the xVals, the x coordinates will be assumed to be the array index 0, 1, 2, 3, .... So if all layers do not use xVals, their data points will still match and the points will be evenly spaced on the chart, and they will match with the x-axis labels too (the Axis.setLabels also assume the labels to be at 0, 1, 2, 3, ....).

Some ChartDirector APIs, such as addScatterLayer, require x coordinates as inputs. If you do not use x-coordinates, you just need to pass in 0, 1, 2, 3, ... For example:

// The x coordinate is the array index
for(int i = 0; i < yVals.Length; ++i) {
    c.addScatterLayer(new double[] { i }, new double[] {yVals[i]}).getDataSet(0
         ).setDataSymbol2(symbols[i]);
}

Regards
Peter Kwan

  Re: How do I pass bitmaps to use for the plot points?
Posted by Peter Kwan on Mar-03-2021 14:50
Hi David,

Regarding the setDataSymbol5(InputStream, width, height) suggestion, I think again and remember that there is already several sample code included in ChartDirector for resizing symbols without having to create another image file. The following is one of them:

https://www.advsofteng.com/doc/cdjava.htm#bubblescale.htm

Basically, there is a Layer.setSymbolScale method that can be used to change the symbol size. The typical usage is to set each symbol to a different size, and it is common to call this type of a chart a bubble chart. But you can also set all symbols to the same size that is different from its original size.

While I am typing this reply, I remember there is a DataSet.setDataSymbol3 that can directly use the resized DrawArea as a symbol without having to save it as a file first.

You mentioned your symbol is an InputStream. I am not sure how you obtain the InputStream. It is common to store images as resources in a JAR file or at any location that normally store ".class" files, and you can ask ChartDirector to search for those resources too:

https://www.advsofteng.com/doc/cdjava.htm#BaseChart.setSearchPath2.htm

Note that in Java, the ClassLoader in the above mehod can also loads from URLs:

https://docs.oracle.com/javase/7/docs/api/java/net/URLClassLoader.html

The DrawArea can also load an image directly from an InputStream:

DrawArea d = new DrawArea();
d.loadPNG(myInputStream);
d.resize(.......);

layer.getDataSet(0).setDataSymbol3(d);

Regards
Peter Kwan