Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » Draw, Display, Images, Bitmaps, Icons » How to set the dpi (dots per inch) of an image
How to set the dpi (dots per inch) of an image [message #27377] Thu, 15 July 2010 11:07 Go to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello all

I have loaded a scanned image, processed it and saved it. The original image had 300 x 300 dpi, but saved image has 96 x 96 dpi.

Is it possible to set the saved image to 300 x 300 dpi?



Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #27423 is a reply to message #27377] Sat, 17 July 2010 09:58 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Thu, 15 July 2010 05:07

Hello all

I have loaded a scanned image, processed it and saved it. The original image had 300 x 300 dpi, but saved image has 96 x 96 dpi.

Is it possible to set the saved image to 300 x 300 dpi?




RasterEncoder::SetDots - you set the "physical" dimensions of Image there.

The only problem is that real encoder has to use this value. I did now a quick review, looks like bmp and png do, jpg has it commented out for whatever reason, gif ignores the value. But all seems to provide it for Raster::GetInfo.

Mirek

[Updated on: Sat, 17 July 2010 09:58]

Report message to a moderator

Re: How to set the dpi (dots per inch) of an image [message #27465 is a reply to message #27423] Mon, 19 July 2010 10:03 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
luzr wrote on Sat, 17 July 2010 09:58

koldo wrote on Thu, 15 July 2010 05:07

Hello all

I have loaded a scanned image, processed it and saved it. The original image had 300 x 300 dpi, but saved image has 96 x 96 dpi.

Is it possible to set the saved image to 300 x 300 dpi?




RasterEncoder::SetDots - you set the "physical" dimensions of Image there.

The only problem is that real encoder has to use this value. I did now a quick review, looks like bmp and png do, jpg has it commented out for whatever reason, gif ignores the value. But all seems to provide it for Raster::GetInfo.

Mirek

Hello Mirek

I have tested it only with .png files using different SetDots values and the result is always the same:

- In Microsoft Paint it always appears 96 dpi hor. and 96 dpi vert.
- In XnView, it is like there is no resolution info (while original unprocessed .png file has dpi info).


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #27562 is a reply to message #27465] Fri, 23 July 2010 11:37 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Mon, 19 July 2010 04:03

luzr wrote on Sat, 17 July 2010 09:58

koldo wrote on Thu, 15 July 2010 05:07

Hello all

I have loaded a scanned image, processed it and saved it. The original image had 300 x 300 dpi, but saved image has 96 x 96 dpi.

Is it possible to set the saved image to 300 x 300 dpi?




RasterEncoder::SetDots - you set the "physical" dimensions of Image there.

The only problem is that real encoder has to use this value. I did now a quick review, looks like bmp and png do, jpg has it commented out for whatever reason, gif ignores the value. But all seems to provide it for Raster::GetInfo.

Mirek

Hello Mirek

I have tested it only with .png files using different SetDots values and the result is always the same:

- In Microsoft Paint it always appears 96 dpi hor. and 96 dpi vert.
- In XnView, it is like there is no resolution info (while original unprocessed .png file has dpi info).


Do you think you can look into the issue?

I believe that what is missing is just one call to

http://refspecs.freestandards.org/LSB_3.1.0/LSB-Desktop-gene ric/LSB-Desktop-generic/libpng12.png.set.phys.1.html

in

void PNGEncoder::Data::Start(Stream& stream, Size size_, int bpp, ImageKind kind_, bool interlace_,

Mirek
Re: How to set the dpi (dots per inch) of an image [message #27584 is a reply to message #27562] Sat, 24 July 2010 11:08 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
luzr wrote on Fri, 23 July 2010 11:37

koldo wrote on Mon, 19 July 2010 04:03

luzr wrote on Sat, 17 July 2010 09:58

koldo wrote on Thu, 15 July 2010 05:07

Hello all

I have loaded a scanned image, processed it and saved it. The original image had 300 x 300 dpi, but saved image has 96 x 96 dpi.

Is it possible to set the saved image to 300 x 300 dpi?




RasterEncoder::SetDots - you set the "physical" dimensions of Image there.

The only problem is that real encoder has to use this value. I did now a quick review, looks like bmp and png do, jpg has it commented out for whatever reason, gif ignores the value. But all seems to provide it for Raster::GetInfo.

Mirek

Hello Mirek

I have tested it only with .png files using different SetDots values and the result is always the same:

- In Microsoft Paint it always appears 96 dpi hor. and 96 dpi vert.
- In XnView, it is like there is no resolution info (while original unprocessed .png file has dpi info).


Do you think you can look into the issue?

I believe that what is missing is just one call to

http://refspecs.freestandards.org/LSB_3.1.0/LSB-Desktop-gene ric/LSB-Desktop-generic/libpng12.png.set.phys.1.html

in

void PNGEncoder::Data::Start(Stream& stream, Size size_, int bpp, ImageKind kind_, bool interlace_,

Mirek

Hello Mirek

You have do it all. Adding this in Start function it works:

unsigned xdpi = 300;
unsigned ydpi = 300;
unsigned xres = unsigned(xdpi / 0.0254 + 0.5);
unsigned yres = unsigned(ydpi / 0.0254 + 0.5);
	
png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER);


The question is how to set xdpy and ydpi in U++ code.


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #27616 is a reply to message #27584] Mon, 26 July 2010 09:50 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Likewise, the same dpi detection would have to be added when reading a png file in bool PNGRaster::Init(), after png_read_info():

	png_read_info(data->png_ptr, data->info_ptr);
/// Begin
	png_uint_32 xres, yres;
	int unitType = PNG_RESOLUTION_METER;
	png_get_pHYs(data->png_ptr, data->info_ptr, &xres, &yres, &unitType);
	unsigned xdpi = unsigned(xres*0.0254);
	unsigned ydpi = unsigned(yres*0.0254);
/// End
	return true;


Here the question is where to put readed xdpy and ydpi in U++ code.


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28024 is a reply to message #27616] Fri, 13 August 2010 11:13 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Mon, 26 July 2010 03:50

Likewise, the same dpi detection would have to be added when reading a png file in bool PNGRaster::Init(), after png_read_info():

	png_read_info(data->png_ptr, data->info_ptr);
/// Begin
	png_uint_32 xres, yres;
	int unitType = PNG_RESOLUTION_METER;
	png_get_pHYs(data->png_ptr, data->info_ptr, &xres, &yres, &unitType);
	unsigned xdpi = unsigned(xres*0.0254);
	unsigned ydpi = unsigned(yres*0.0254);
/// End
	return true;


Here the question is where to put readed xdpy and ydpi in U++ code.


If you have this tested and working, please submit files as patch...

Mirek
Re: How to set the dpi (dots per inch) of an image [message #28035 is a reply to message #28024] Fri, 13 August 2010 13:46 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
luzr wrote on Fri, 13 August 2010 11:13

koldo wrote on Mon, 26 July 2010 03:50

Likewise, the same dpi detection would have to be added when reading a png file in bool PNGRaster::Init(), after png_read_info():

	png_read_info(data->png_ptr, data->info_ptr);
/// Begin
	png_uint_32 xres, yres;
	int unitType = PNG_RESOLUTION_METER;
	png_get_pHYs(data->png_ptr, data->info_ptr, &xres, &yres, &unitType);
	unsigned xdpi = unsigned(xres*0.0254);
	unsigned ydpi = unsigned(yres*0.0254);
/// End
	return true;


Here the question is where to put readed xdpy and ydpi in U++ code.


If you have this tested and working, please submit files as patch...

Mirek


Hello Mirek

Now xdpy and ydpi do not exist internally. It would be necessary to define how to get/set them, prior to adding the code.


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28201 is a reply to message #28035] Sun, 22 August 2010 23:51 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

I mean now there are no methods to set or get the vertical or horizontal dpi of an image.

Can I propose new functions for PNG only or to be used for all Raster types?


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28591 is a reply to message #28201] Wed, 08 September 2010 09:17 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Sun, 22 August 2010 17:51

Hello Mirek

I mean now there are no methods to set or get the vertical or horizontal dpi of an image.



But there are are!

Raster::GetInfo returns Info, which in turn has "dots" member, which is physical size of image (in dots).

Combine with "GetSize" and you get dpi information.

The other way is RasterEncoder::SetDots. (Again, combined with SetSize, you have dpi info).

The only issue is that plugins might be lacking the support of this information.

Well, now thinking, perhaps we could add Raster::GetDpi a RasterEncoder::SetDpi methods, but that would only be very oneliners/helpers. Plus, SetDpi would need Create to be called first. Hm, perhaps there should be alternate Create with dpi info.

Anyway, these would really be just helpers. The basic info and interface is already there!

Mirek
Re: How to set the dpi (dots per inch) of an image [message #28668 is a reply to message #28591] Fri, 10 September 2010 11:41 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

Quote:

Raster::GetInfo returns Info, which in turn has "dots" member, which is physical size of image (in dots).


Perhaps instead of in "dots" do you mean in meters?. This way info.dots would be the physical image Size in meters.


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28670 is a reply to message #28668] Fri, 10 September 2010 13:42 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
koldo wrote on Fri, 10 September 2010 11:41

Hello Mirek

Quote:

Raster::GetInfo returns Info, which in turn has "dots" member, which is physical size of image (in dots).


Perhaps instead of in "dots" do you mean in meters?. This way info.dots would be the physical image Size in meters.


Hello Mirek

I have seen that in U++ a dot is 1/600 of a pixel.

Now U++ stores for an image the Size in pixels and in dots.

This cause problems as if I rescale an image or set a new image with part of other, the Size in dots is lost or remains the same, so the image really has badly changed its resolution Sad.

Really if an image is scanned, the size in dots and in pixels is the same... The only thing that is different is the size of the dot in inches or meters.

Would not be better to store image Size in pixels and resolution in dpi or dpm?. This way if we process an ImageBuffer, the size will change but the resolution will remain (but if we explicitly want to change it)


Best regards
Iñaki

[Updated on: Fri, 10 September 2010 13:52]

Report message to a moderator

Re: How to set the dpi (dots per inch) of an image [message #28711 is a reply to message #28670] Mon, 13 September 2010 17:33 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
koldo wrote on Fri, 10 September 2010 07:42

koldo wrote on Fri, 10 September 2010 11:41

Hello Mirek

Quote:

Raster::GetInfo returns Info, which in turn has "dots" member, which is physical size of image (in dots).


Perhaps instead of in "dots" do you mean in meters?. This way info.dots would be the physical image Size in meters.


Hello Mirek

I have seen that in U++ a dot is 1/600 of a pixel.

Now U++ stores for an image the Size in pixels and in dots.

This cause problems as if I rescale an image or set a new image with part of other, the Size in dots is lost or remains the same, so the image really has badly changed its resolution Sad.

Really if an image is scanned, the size in dots and in pixels is the same... The only thing that is different is the size of the dot in inches or meters.

Would not be better to store image Size in pixels and resolution in dpi or dpm?. This way if we process an ImageBuffer, the size will change but the resolution will remain (but if we explicitly want to change it)


Everything has some tradeoff. It is true that if it gets stored as dpi, it holds after scaling.

OTOH, if you ever are going to scale the image, usually the original size either does not matter, or you just use dots as basis for scaling. In fact, any true WYSIWIG works in dots and effectively in dot = pixel mode, you tend to place images in target dots coordinates (which, for screen, are somewhat rescaled), so it is not a big deal.

In any case, it is a bit too late to change this now, even if dpi info might be somewhat better.
Re: How to set the dpi (dots per inch) of an image [message #28725 is a reply to message #28711] Mon, 13 September 2010 21:56 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
luzr wrote on Mon, 13 September 2010 17:33

koldo wrote on Fri, 10 September 2010 07:42

koldo wrote on Fri, 10 September 2010 11:41

Hello Mirek

Quote:

Raster::GetInfo returns Info, which in turn has "dots" member, which is physical size of image (in dots).


Perhaps instead of in "dots" do you mean in meters?. This way info.dots would be the physical image Size in meters.


Hello Mirek

I have seen that in U++ a dot is 1/600 of a pixel.

Now U++ stores for an image the Size in pixels and in dots.

This cause problems as if I rescale an image or set a new image with part of other, the Size in dots is lost or remains the same, so the image really has badly changed its resolution Sad.

Really if an image is scanned, the size in dots and in pixels is the same... The only thing that is different is the size of the dot in inches or meters.

Would not be better to store image Size in pixels and resolution in dpi or dpm?. This way if we process an ImageBuffer, the size will change but the resolution will remain (but if we explicitly want to change it)


Everything has some tradeoff. It is true that if it gets stored as dpi, it holds after scaling.

OTOH, if you ever are going to scale the image, usually the original size either does not matter, or you just use dots as basis for scaling. In fact, any true WYSIWIG works in dots and effectively in dot = pixel mode, you tend to place images in target dots coordinates (which, for screen, are somewhat rescaled), so it is not a big deal.

In any case, it is a bit too late to change this now, even if dpi info might be somewhat better.

Hello Mirek

No problem Smile.

Do you let me include a GetDPI() and SetDPI functions applicable to Raster, ImageBuffer and Image (in this case, only GetDPI) ?


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28731 is a reply to message #28725] Tue, 14 September 2010 09:51 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

It is done. Here a sample code using GetDPI() and SetDPI():

include <Core/Core.h>
#include <plugin/png/png.h>

using namespace Upp;

CONSOLE_APP_MAIN
{
	Image img = StreamRaster::LoadFileAny(AppendFileName(GetDesktopFolder(), "demo.png"));
	if (!img) 
		puts("No image");
	else {
		ImageBuffer image(img);
		
		Size dpi = image.GetDPI();
		puts(Format("Image DPI are %d/%d", dpi.cx, dpi.cy));
		image.SetDPI(Size(600, 600));
		puts("New DPI values will be 600/600");
		
		PNGEncoder png;
		png.SaveFile(AppendFileName(GetDesktopFolder(), "demo2.png"), image);	
		puts("Done");
	}
	getchar();
}


The DPI is only effectively set in "PNG" format files.

I will include the changed files today. They are a few.


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28747 is a reply to message #28731] Wed, 15 September 2010 09:17 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

Here I enclose you the changed files and changes list:

In Draw
Image.cpp and Image.h
Added
void ImageBuffer::SetDPI(Size dpi)
Size ImageBuffer::GetDPI()
Size Image::GetDPI()

RasterEncoder.cpp and Raster.h
Added in RasterEncoder
void SetDPI(Size sz);
Size GetDPI();

Modified in RasterEncoder
virtual void Start(Size sz, Size dots) = 0;
void Create(Size sz, Size dots);
void Create(int cx, int cy, Size dots)
void Create(Size sz, Size dots, const RGBA *palette);
void Create(int cx, int cy, Size dots, const RGBA *palette);
void Create(Size sz, Size dots, Raster& pal_raster);
void Create(int cx, int cy, Size dots, Raster& pal_raster);
virtual void Start(Size sz, Size dots);

In plugin/png
pngupp.cpp and png.h
Added
static void SetDotSize(Size pixel_size, Size dots_size, png_uint_32 &x_ppm, png_uint_32 &y_ppm, int unit_type)

Modified
bool PNGRaster::Create()
class PNGEncoder::Data
void PNGEncoder::Data::Start(Stream& stream, Size size_, Size dots_, int bpp, ImageKind kind_, bool interlace_, const RGBA *imgpal)
void PNGEncoder::Start(Size sz, Size dots)
  • Attachment: changes.7z
    (Size: 12.16KB, Downloaded 231 times)


Best regards
Iñaki

[Updated on: Wed, 15 September 2010 09:19]

Report message to a moderator

Re: How to set the dpi (dots per inch) of an image [message #28754 is a reply to message #28747] Wed, 15 September 2010 13:38 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

Now there is dpi support for all main image formats. Here it is a demo to test file write and read.

The demo output is:

Image DPI are 0/0
New DPI values will be 1200/1200
Saved .png image DPI are 1200/1200
Saved .jpg image DPI are 1200/1200
Saved .tif image DPI are 1200/1200
Saved .bmp image DPI are 1200/1200
Saved .gif image DPI are 72/72
Done

(GIF is only 72x72)

The demo code is:

#include <Core/Core.h>
#include <plugin/png/png.h>
#include <plugin/jpg/jpg.h>
#include <plugin/tif/tif.h>
#include <plugin/bmp/bmp.h>
#include <plugin/gif/gif.h>

using namespace Upp;

void PrintDPI(String fileName, String format) {
	Image img = StreamRaster::LoadFileAny(fileName + format);
	Size dpi = img.GetDPI();
	puts(Format("Saved " + format + " image DPI are %d/%d", dpi.cx, dpi.cy));	
}

CONSOLE_APP_MAIN
{
	Image img = StreamRaster::LoadFileAny(AppendFileName(GetDesktopFolder(), "demo.png"));
	if (!img) 
		puts("No image");
	else {
		ImageBuffer image(img);
		
		Size dpi = image.GetDPI();
		puts(Format("Image DPI are %d/%d", dpi.cx, dpi.cy));
		image.SetDPI(Size(1200, 1200));
		puts("New DPI values will be 1200/1200");
		
		img = image;
		String fileName = AppendFileName(GetDesktopFolder(), "demo2");
		
		PNGEncoder png;
		png.SaveFile(fileName + ".png", img);	
		PrintDPI(fileName, ".png");
		
		JPGEncoder jpeg;
		jpeg.SaveFile(fileName + ".jpg", img);	
		PrintDPI(fileName, ".jpg");
		
		TIFEncoder tiff;
		tiff.SaveFile(fileName + ".tif", img);	
		PrintDPI(fileName, ".tif");

		BMPEncoder bmp;
		bmp.SaveFile(fileName + ".bmp", img);			
		PrintDPI(fileName, ".bmp");
				
		GIFEncoder gif;
		gif.SaveFile(fileName + ".gif", img);			
		PrintDPI(fileName, ".gif");
		
		puts("Done");
	}
	getchar();
}


In few hours I will include additional changed files.


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28756 is a reply to message #28754] Wed, 15 September 2010 15:02 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

In addition to the previous changes, these files have also been changed.

In plugin/bmp
bmpwrite.cpp and bmp.h
void PNGEncoder::Start(Size sz, Size dots)

In plugin/gif
gifupp.cpp and gif.h
class GifEncode::Data
bool GIFRaster::Data::Create()
void GifEncode::Data::Start(Size sz, Size dots, bool ignore_alpha, String comment, const RGBA *palette);
void GIFEncoder::Start(Size sz, Size dots)

In plugin/jpg
jpgupp.cpp and jpg.h
class JPGEncoder::Data
void JPGEncoder::Data::Start(Stream& stream, Size size, Size dots, int quality);
void JPGEncoder::Start(Size sz, Size dots)

In plugin/tif
tifupp.cpp and tif.h
class TIFEncoder::Data
void TIFEncoder::Data::Start(Size size, Size dots, int bpp, const RGBA *palette);
void TIFEncoder::Start(Size sz, Size dots)

It is enclosed a file with all changes.
  • Attachment: changes.7z
    (Size: 28.00KB, Downloaded 228 times)


Best regards
Iñaki
Re: How to set the dpi (dots per inch) of an image [message #28789 is a reply to message #28756] Thu, 16 September 2010 23:49 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 13975
Registered: November 2005
Ultimate Member
Well, this is a great job, but I really dislike the idea of adding 'dots' parameter to RasterEncoder methods.

First, doing so we would break all existing code. Second, I believe that the interface already has means how to handle with this - it is not necessarry to change the interface here. Setting dpi is no different from setting palette or hotspot IMO...
Re: How to set the dpi (dots per inch) of an image [message #28797 is a reply to message #28789] Fri, 17 September 2010 09:58 Go to previous messageGo to previous message
koldo is currently offline  koldo
Messages: 3354
Registered: August 2008
Senior Veteran
Hello Mirek

Done!. I will post it today.


Best regards
Iñaki
Previous Topic: Icon at right side of the menuBar
Next Topic: GetExifThumbnail doc
Goto Forum:
  


Current Time: Thu Mar 28 10:18:50 CET 2024

Total time taken to generate the page: 0.01083 seconds