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  |
 |
koldo
Messages: 3432 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   |
 |
mirek
Messages: 14255 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 #27562 is a reply to message #27465] |
Fri, 23 July 2010 11:37   |
 |
mirek
Messages: 14255 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   |
 |
koldo
Messages: 3432 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 #28024 is a reply to message #27616] |
Fri, 13 August 2010 11:13   |
 |
mirek
Messages: 14255 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   |
 |
koldo
Messages: 3432 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 #28591 is a reply to message #28201] |
Wed, 08 September 2010 09:17   |
 |
mirek
Messages: 14255 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 #28670 is a reply to message #28668] |
Fri, 10 September 2010 13:42   |
 |
koldo
Messages: 3432 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 .
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   |
 |
mirek
Messages: 14255 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 .
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   |
 |
koldo
Messages: 3432 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 .
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 .
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 #28747 is a reply to message #28731] |
Wed, 15 September 2010 09:17   |
 |
koldo
Messages: 3432 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 284 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   |
 |
koldo
Messages: 3432 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   |
 |
koldo
Messages: 3432 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 304 times)
Best regards
Iñaki
|
|
|
|
|
Goto Forum:
Current Time: Fri Apr 25 15:10:52 CEST 2025
Total time taken to generate the page: 0.03126 seconds
|