|
case not dpi 96.. |
Posted by Ji-hyeon Choi on Jun-27-2024 12:52 |
|
I am writing to inform you about an issue we have encountered with our image rendering process. Specifically, we have observed that when the DPI (dots per inch) setting is not set to 96, the resulting images appear slightly distorted or broken. When the screen magnification is 150%, it becomes 144 dpi, and the attached picture is the view of the chart being viewed at that time.
void KCDChart::SetChart(BaseChart* pBaseChart)
{
m_ChartViewer->setChart(pBaseChart);
FreeImgChart();
if(m_ChartViewer->m_block.len > 0)
{
m_imgChart = GlobalAlloc(GMEM_FIXED, m_ChartViewer->m_block.len);
if(m_imgChart)
memcpy(m_imgChart, m_ChartViewer->m_block.data, m_ChartViewer->m_block.len);
}
}
|
Re: case not dpi 96.. |
Posted by Peter Kwan on Jun-27-2024 16:55 |
|
Hi Ji-hyeon Choi,
Would you mind to clarify how do you create the 144dpi chart?
The two charts in your message are different charts. For example, the x-axis of the 96 dpi chart is {0, 1, 2, 3, 4, 5}, but in the 144dpi chart it is {0, 0.5, 1, 1.5, 2 .....}. Also, the 144dpi chart should be 150% bigger, but it is only around 130% bigger, so it is not really 144dpi.
If ChartDirector is used to resize the chart, the two charts should be similar (the x-axis labels should be the same) and it should be exactly 150%.
I have attached a chart resized by ChartDirector for your reference. It is based on the original Soft Bar Shading sample code:
https://www.advsofteng.com/doc/cdcpp.htm#softlightbar.htm
I use the bmpscale option with ChartDirector 7 to generate the chart images:
c->setOutputOptions("bmpscale=1.5");
c->makeChart("cd_144dpi.png");
c->setOutputOptions("bmpscale=1");
c->makeChart("cd_96dpi.png");
As you may notice, the text in the 144dpi chart should be quite sharp and not blurred. The two charts are generated using exactly the same chart object, so they should look the same (have the same x-axis labels).
For MFC projects, if the MFC project is configured as high dpi aware, the CChartViewer should automatically resize the chart to match the DPI, just like other MFC controls.
In your message, you also have some code in KCDChart. The KCDChart does not appear to be our code. The m_ChartViewer inside seems differernt from the CChartViewer included in ChartDirector. (The CChartViewer does not have a property called m_block.) It is not clear to me how it works to resize the chart.
Best Regards
Peter Kwan
|
Re: case not dpi 96.. |
Posted by Ji-hyeon Choi on Jul-01-2024 08:11 |
|
MemBlock CStaticHelper::renderChart(BaseChart* c)
{
if(0 == c)
return MemBlock();
int dpi = getDPI();
if(96 != dpi)
{
char buffer[1024];
sprintf_s(buffer, sizeof(buffer), "+dpi=%d", dpi);
c->setOutputOptions(buffer);
}
MemBlock m = c->makeChart(Chart::BMP);
c->setOutputOptions("-dpi");
return m;
}
The first picture is taken when the value of getDPI() in the renderChart function is 144 and the second picture is 96.
void CChartViewer::setChart(BaseChart* c)
{
// In case the user forgets to check the "Notify" check box in the Dialog editor, we set it
// ourselves so the CChartViewer control can receive mouse events.
if((GetStyle() & SS_NOTIFY) == 0)
ModifyStyle(0, SS_NOTIFY);
if((GetStyle() & SS_TYPEMASK) != SS_BITMAP)
ModifyStyle(SS_TYPEMASK, SS_BITMAP);
if(m_currentChart != c)
setImageMap(0);
m_currentChart = c;
delete m_imageMapChart;
m_imageMapChart = c ? new BaseChart(c) : 0;
if(0 != c)
{
commitPendingSyncAxis(c);
if (m_delayUpdateChart != NO_DELAY)
m_block = c->makeChart(Chart::BMP);
}
updateDisplay();
}
This is how the statichelper class declares Memblock as a member variable and uses it. |
Re: case not dpi 96.. |
Posted by Peter Kwan on Jul-02-2024 13:28 |
|
Hi Ji-hyeon,
I understand the DPI changes from 96 to 144. The issue is what is the charting code. Is the charting code drawing the same chart no matter what the DPI is? For example, is the charting code using the same plot area width, the same chart size, etc, no matter it is 96dpi or 144dpi?
I have written an example that tries to draw a similar chart. It is based on the MFC helloworld sample code. To try the example, please use ChartDirector for C++ 7.l. In it, there is some MFC sample code in ChartDirector/mfcdemo/helloworld. Please remove the original helloworld folder, and replace it with the helloworld folder in the attached helloworld.zip.
You can use Windows 10 Settings/System to set set your display to 100% (100% is 96dpi). Open the sample code using Visual Studio, and compile and run the helloworld project. You should see a window and a chart like in the helloworld_96.png.
Then please shutdown Visual Studio. In Windows 10 Settings/System, change the display to 150% (150% is 144dpi). Then open the sample code using Visual Studio again, and run the helloworld sample code. You should see a window and a chart like in the helloworld_144.png.
If you do not see the charts like the attached images, please take a screenshot by of the helloworld window only by using "Alt PrintScreen". Then open Windows Paint and paste the screen shot, and save it as PNG. Do not modify the screen shot (do not cut out certain parts, resize it, etc).
If the above still cannot solve the problem, is it possible to modify the helloworld sample code to reproduce the problem, and send the code to me so I can try to reproduce it? (My email is pkwan@advsofteng.net)
Best Regards
Peter Kwan
|
Re: case not dpi 96.. |
Posted by Ji-hyeon Choi on Jul-03-2024 14:46 |
|
Thank you for your response.
If you increase the size in the sample code you sent me, the phenomenon seems to occur. If you increase the size and substitute the dpi 144 fixed value in the renderchart() function, it will be reproduced like the attached image.
new XYChart(400, 400, 0xffffff, 0xffffff, Chart::softLighting(Chart::Top, 14));
layer->setBorderColor(Chart::Transparent, Chart::softLighting(Chart::Top, 14));
|
Re: case not dpi 96.. |
Posted by Peter Kwan on Jul-03-2024 18:09 |
|
Hi Ji-hyeon,
Unluckily, the artifact you see is due to using fractional scale factor (144dpi = 1.5 scale factor). The second argument of softLighting is the border width. Currently, the border shading effect is achieved by using multiple 1-pixel borders, one inside the other and with a slight different color.
At 1.5 scale factor, the 1-pixel borders become 1.5-pixel border. ChartDirector currently cannot draw line with fractional width. So the border can only be drawn as 1 pixel wide and there are gaps between the borders. The issue would not occur in 192dpi (= 2.0 scale factor) or 288dpi (= 3.0 scale factor).
If the monitor is 144dpi, normally the pixel is very small, and if the border is not too thick it will be hard to notice the artifact. (Our test code uses 4 pixel thickness while you code uses 14 pixel thickness.)
Previously, I am focused on the abnormal coloring of your chart. (See the blue arrow in the attached chart.) I just tried to confirm it does not happen.
Regards
Peter Kwan
|
Re: case not dpi 96.. |
Posted by Ji-hyeon Choi on Jul-05-2024 15:35 |
|
Hi Peter Kwan
I found the reason why the image is drawn like that. The size of the chart drawn according to the screen magnification should be large, but the size of the chart was set to a fixed value, so the image was drawn like that. Is there a way to solve the problem without changing the size of the chart?
Regards
ji hyoen |
Re: case not dpi 96.. |
Posted by Ji-hyeon Choi on Jul-05-2024 15:59 |
|
Hi Peter Kwan
When I set it to 192dpi, the image of the chart being drawn seems to be drawn larger than the magnification of the screen. And when I double-click on the chart being drawn, it seems that the chart that should be drawn originally appears.
Regards
ji hyoen
|
Re: case not dpi 96.. |
Posted by Peter Kwan on Jul-05-2024 19:41 |
|
Hi Ji-hyeon,
I noticed in one of your earlier messages that you have upgraded from ChartDirector 5 to 7. The CChartViewer in ChartDirector 5 will not automatically resize to fit the dpi. The CChartViewer in ChartDirector 7 will automatically resize if the MFC project is set to be "high dpi aware".
I also noticed in one of your message that there is a KCDChart, and in KCDChart::SetChart, it copies the chart image from the CChartViewer to a global memory block. (See https://www.chartdir.com/forum/download_thread.php?site=chartdir&bn=chartdir_support&thread=1719463935)
So my guess is that the KCDChart is originally designed for ChartDirector 5, and it does not know that ChartDirector 7 will automatically resize the chart. The KCDChart may copy the chart image to resize the image itself. The double resizing causes the chart image to become too big. Later, the KCDChart wants to resize is back to the correct size, but its resize code is incorrect when resizing down the image.
May be you can try one of the following:
(a) You may try to examine the KCDChart or your other code to see if it resizes the image itself, and try to disable it.
(b) You may force CChartViewer to always use 96dpi (that is, no resize) no matter what is the actual dpi. The code is:
m_ChartViewer.setDPI(96);
For more information, you may refer to the "High DPI Support' section of the ChartDirector 7 release note:
https://www.advsofteng.com/release70.html#changes
Best Regards
Peter Kwan |
|