Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / February 2008

Tip: Looking for answers? Try searching our database.

struggling to save a tiff as a PNG and keep filesize down

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
sklett - 28 Feb 2008 21:08 GMT
I have a Tiff (fax) with the following properties:
width: 1728
height: 1090
x resolution: 204
y resolution: 98
bit depth: 1

If I open this tiff in Photoshop and change the resolution to 96 and resize
to 816 x 1056, then save as png the size is 3.1Kb (great!)

If I resize the tiff with gdi+ and save as png (same setting as Photoshop)
the filesize is 31Kb (bad!!!)

Here is the code I'm using to resize and save as png:
<code>
Image img = Bitmap.FromFile("../../2109790117_080129_77862164.tif");
if(img.HorizontalResolution != img.VerticalResolution)
{
   const float resolution = 96F;

   //  get the physical dimensions of the document
   SizeF size = new SizeF(img.Width / img.HorizontalResolution, img.Height
/ img.VerticalResolution);
   Size pixelDimensions = new Size((int)(size.Width * resolution),
(int)(size.Height * resolution));

   Bitmap newImage = new Bitmap(pixelDimensions.Width,
pixelDimensions.Height);
   newImage.SetResolution(resolution, resolution);
   using(Graphics g = Graphics.FromImage(newImage))
   {
       g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
       g.DrawImage(img, new Rectangle(0, 0, pixelDimensions.Width,
pixelDimensions.Height),
           0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
   }

   img = newImage;
}

string fn = Guid.NewGuid().ToString() + ".png";
img.Save(fn, System.Drawing.Imaging.ImageFormat.Png);
</code>

The image quality of the resize using GDI+ is much better than Photoshops.
I'm using NearestNeighbor in both cases but the results are not  the same.

If anyone can shed some light, offer some pointers, whatever I would really
appreciate it.  I need to keep the filesize as small as possible.

Thanks,
Steve
Peter Duniho - 28 Feb 2008 21:51 GMT
> I have a Tiff (fax) with the following properties:
> width: 1728
[quoted text clipped - 10 lines]
> Photoshop)
> the filesize is 31Kb (bad!!!)

The most obvious thing I see is that the image you create isn't a 1 bpp  
image as the original is.  Perhaps Photoshop is preserving that 1 bpp  
color depth, whereas your code is not.

What happens if you create the new image instance as "new  
Bitmap(pixelDimensions.Width, pixelDimensions.Height,  
PixelFormat.Format1bppIndexed)"?

Pete
sklett - 28 Feb 2008 21:57 GMT
>> I have a Tiff (fax) with the following properties:
>> width: 1728
[quoted text clipped - 18 lines]
> Bitmap(pixelDimensions.Width, pixelDimensions.Height,
> PixelFormat.Format1bppIndexed)"?

Hi Peter,

I thought of that as well, but when I try to use a 1bpp image and create a
Graphics instance from it I get the following exception:
"A Graphics object cannot be created from an image that has an indexed pixel
format."

Photoshop is created a 32 BPP image.  Very strange.

Thanks for the suggestion though!
-Steve
Peter Duniho - 28 Feb 2008 22:15 GMT
> [...]
>> What happens if you create the new image instance as "new
[quoted text clipped - 9 lines]
> pixel
> format."

Ah, right.  I forgot about that limitation.

You could resize the image into a 24/32bpp image and then use LockBits()  
on that and a 1 bpp image to copy the data directly.

> Photoshop is created a 32 BPP image.  Very strange.

Are you sure it is?  3K seems awfully small for a file that really was  
saved as 32 bpp.  At 800 x 1000, you're looking at over 3MB of data for a  
32 bpp image.  If so, that'd mean that PNG compression is achieving a  
1000-to-1 compression ratio when you save from Photoshop.

Even JPEG wouldn't normally be able to save an image of that dimension  
without practically destroying the image, and PNG being lossless shouldn't  
be able to come anywhere close to that for a full-color image of any  
reasonable complexity (even the best-case scenarios that one might  
consider are unlikely IMHO and those require careful matching of the input  
data to the specific PNG compression algorithm being used).

It's hard to comment precisely without having a copy of the original  
bitmap and of the Photoshop-created image.  But I still suspect this is a  
color depth issue.

Pete
Steve K. - 28 Feb 2008 23:20 GMT
>> [...]
>>> What happens if you create the new image instance as "new
[quoted text clipped - 21 lines]
> 32 bpp image.  If so, that'd mean that PNG compression is achieving a
> 1000-to-1 compression ratio when you save from Photoshop.

I agree, it "smells" a bit.  This is not a full color image though, the
source TIFF is a 1BPP image.
I will check this some additional ways and see what I can find out.

> Even JPEG wouldn't normally be able to save an image of that dimension
> without practically destroying the image, and PNG being lossless shouldn't
[quoted text clipped - 6 lines]
> bitmap and of the Photoshop-created image.  But I still suspect this is a
> color depth issue.

If we can't resolve this through the NG and you would like the images I
would be happy to send to you ;0)

Thanks for your continued efforts to help me!
-Steve
Peter Duniho - 29 Feb 2008 06:15 GMT
> [...]
>> Are you sure it is?  3K seems awfully small for a file that really was
[quoted text clipped - 6 lines]
> source TIFF is a 1BPP image.
> I will check this some additional ways and see what I can find out.

It's true, it's possible that with the 32 bpp image only have two colors  
PNG is able to compress it dramatically.  But you should definitely  
confirm that's what's going on, given the disparity from what .NET is  
doing.

The only other thing I can think of is that Photoshop is doing a more  
elaborate analysis of the data.  PNG offers a surprisingly wide variety of  
compression options, mainly because how well a particular algorithm will  
compress an image depends a lot on the data in the image.  Fancier PNG  
compression tools (which may include Photoshop) will run multiple  
compressions, using varying options, and choose the best-compressing  
output.

I doubt that .NET does any sort of comparative compression like this, and  
probably just uses some "best average case" options for its compression.  
If that's the reason for the difference, then you're out of luck with  
respect to using the built-in .NET PNG compression.

Other options would include implementing a PNG compressor yourself  
(non-trivial, but not too hard either since the PNG org web site has links  
to sample code), or use some third-party library (I know of at least one  
command-line utility that will do fancier compression...you could access  
the command-line utility from your .NET application to handle the  
compression).

But before you do all that, you really should confirm that you're  
comparing apples to apples.  It would be a shame to do all that work for  
nothing.

Finally, another possibility: you mentioned that Photoshop doesn't resize  
the image with as high quality as you're getting from .NET.  It's possible  
that due to the lower quality, the image Photoshop is compressing really  
is much more highly compressable than the image .NET is compressing.  An  
interesting test would be to open the image Photoshop generates (just read  
the PNG file in as an Image instance), and then resave that as a new PNG.  
That way you know for sure you're compressing the same exact data  
Photoshop is.

That would be another "verify apples to apples" check you could make  
before pursuing alternatives to using .NET's built-in PNG functionality.

> [...]
>> It's hard to comment precisely without having a copy of the original
[quoted text clipped - 4 lines]
> If we can't resolve this through the NG and you would like the images I
> would be happy to send to you ;0)

If you want to share the files, I recommend any of several free file  
upload sites that you can use.  That way you can post the link and easily  
share the files with whomever thinks they might be able to help, without  
any extra effort on your part and without inefficiently transmitting the  
files via email.

Here are three that I think work pretty well:
http://www.filecrunch.com/
http://www.sendspace.com/
http://www.yousendit.com/

They all allow the upload of files for download by others without any  
requirement to register or share email addresses (at least one makes it  
look like they require an email address, but it's really optional, as with  
the others).

> Thanks for your continued efforts to help me!

Well, I'm always happy to speculate.  I wish I had more specific  
information.  And sadly, just based on replies I've seen to other posts  
regarding PNG questions (of which there haven't been many, granted), I  
have some of the most experience with that image file format out of any of  
the folks who normally reply.  And that's not encouraging news for you, as  
I don't really have that much experience with it.  :(

Sorry.  :)  But I'll keep trying to help if I come up with new ideas.  :)

Pete
sklett - 29 Feb 2008 20:25 GMT
> The only other thing I can think of is that Photoshop is doing a more
> elaborate analysis of the data.  PNG offers a surprisingly wide variety of
[quoted text clipped - 3 lines]
> compressions, using varying options, and choose the best-compressing
> output.

Hi Peter,

My latest research seems to indicate that the PNG saved from PS is indeed a
1BPP even though Windows reports it's a 32BPP.  I checked this by opening
the PNG back into PS and it shows the "Mode" as "Bitmap".

The exact operations that I'm performing on the source TIFF in PS are:
1) open TIFF file
2) resize image to 8.5" x 11" with interpolation mode: Nearest Neighbor
3) Change resolution to 96
4) save as PNG

The resizing is required because the "Pixel Aspect ratio" is not square
because the source TIFF resolution is 204 * 98

The .Net code to mimic what I'm doing with PS is
<code>
Image img = Bitmap.FromFile("../../NA_080129_77887111.tif");
if(img.HorizontalResolution != img.VerticalResolution)
{
   const float resolution = 96F;

   SizeF size = new SizeF(8.5F, 11.0F);
   Size pixelDimensions = new Size((int)(size.Width * resolution),
(int)(size.Height * resolution));

   Bitmap newImage = new Bitmap(pixelDimensions.Width,
pixelDimensions.Height);
   newImage.SetResolution(resolution, resolution);
   using(Graphics g = Graphics.FromImage(newImage))
   {
       g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
       g.DrawImage(img, new Rectangle(0, 0, pixelDimensions.Width,
pixelDimensions.Height),
           0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
   }

   img = newImage;
}

string fn = "../../" + Guid.NewGuid().ToString() + ".png";
img.Save(fn, System.Drawing.Imaging.ImageFormat.Png);
</code>

I have created a comparison of a specific (zoomed way in) section of the two
png files
http://www.pmddirect.com/temp/gdi+%20and%20PS%20comparison%20copy.png

When I open the .net saved PNG in PS, the "Mode" is RGB Color/ 8 Bits

SO!  That is a great clue, not sure how I missed this before, apologies if
I've had you barking up the wrong tree.

At this point, I would say my whole problem/challenge is getting .Net to
save a 1BPP png and I bet I would have results on par with that of PS.

> I doubt that .NET does any sort of comparative compression like this, and
> probably just uses some "best average case" options for its compression.
[quoted text clipped - 7 lines]
> the command-line utility from your .NET application to handle the
> compression).

I will look into this, sounds a bit daunting but might be my only option.

> But before you do all that, you really should confirm that you're
> comparing apples to apples.  It would be a shame to do all that work for
[quoted text clipped - 47 lines]
>
> Sorry.  :)  But I'll keep trying to help if I come up with new ideas.  :)

Again, thanks for the great help!  I really appreciate it.  I will do some
research and try to find out if it's possible to save a 1BPP png from code.
I would rather not resort to an external application if I can avoid it.

Gotta run to a meeting, I will update this thread with any additional info I
find in a few hours.

-Steve
Peter Duniho - 29 Feb 2008 22:21 GMT
> [...]
> I have created a comparison of a specific (zoomed way in) section of the  
[quoted text clipped - 3 lines]
>
> When I open the .net saved PNG in PS, the "Mode" is RGB Color/ 8 Bits

Not to mention the doc sizes.  Almost 2.5Mb for the one saved from .NET,  
and only 100K for the one from Photoshop.  :)

> SO!  That is a great clue, not sure how I missed this before, apologies  
> if
> I've had you barking up the wrong tree.

Not really.  I suspected a bit-depth problem all along.  :)

> At this point, I would say my whole problem/challenge is getting .Net to
> save a 1BPP png and I bet I would have results on par with that of PS.

I would hope so.  There's no guarantee, I think it's likely.

Of course, all that said, even the 100-to-1 compression you're getting now  
isn't too shabby.  Obviously, getting the file size down to 3K from 30K  
would be great.  That 10X savings is definitely significant.  But there's  
theoretically a lot of information in that 800x1000(-ish) image, and  
keeping all that information in just 30K is pretty good.

> [...]
> Again, thanks for the great help!  I really appreciate it.  I will do  
> some
> research and try to find out if it's possible to save a 1BPP png from  
> code.
> I would rather not resort to an external application if I can avoid it.

For your first test, you should see if you can load a monochrome image  
into .NET and have it preserve the bit depth.  If .NET does, rather than  
upscaling the color resolution to 24 or 32 bpp, then you have a 1 bpp  
image you can test saving.  If saving that 1 bpp image works, then you can  
spend more time learning how to actually create the necessary 1 bpp image  
with Bitmap.LockBits().

Those two tests, you should be able to code in five or ten minutes.  
They'll give you good information as to whether it's worth pursuing the  
LockBits() solution, which could take longer (I'd guess an hour or two for  
someone who's unfamiliar with LockBits() but knows bitmap formats  
generally, and perhaps anywhere from two to ten times as long or longer  
for someone brand new to the whole topic, depending on their general  
abilities).

In particular, if you can create a 1 bpp image in memory with those test,  
but saving that image doesn't help, then it won't be worth your effort to  
bother figuring out LockBits().

Pete
not_a_commie - 29 Feb 2008 15:50 GMT
> Are you sure it is?  3K seems awfully small for a file that really was
> saved as 32 bpp.  At 800 x 1000, you're looking at over 3MB of data for a
[quoted text clipped - 7 lines]
> consider are unlikely IMHO and those require careful matching of the input
> data to the specific PNG compression algorithm being used).

Huh? JPEG is for photos and nothing else. Don't try to use that on
your screen shot or your 1bpp image. PNG uses a variety of compression
mechanisms. It chooses the best for your current line in the image. So
if you line is all one color it will use RLE compression. Instead of
being 1728 integers in data it will be two intigers in data: one with
1728 and the next with the color. That's a 1728-to-2 compression with
no hard work at all. And if it can use 16bit values for color and run
length it would be smaller yet, etc.
Peter Duniho - 29 Feb 2008 18:17 GMT
> Huh? JPEG is for photos and nothing else. Don't try to use that on
> your screen shot or your 1bpp image.

No one is suggesting that he does.

> PNG uses a variety of compression
> mechanisms. It chooses the best for your current line in the image. So
> if you line is all one color it will use RLE compression. Instead of
> being 1728 integers in data it will be two intigers in data: one with
> 1728 and the next with the color. That's a 1728-to-2 compression with
> no hard work at all.

Yes, for a particular kind of data.  And PNG supports handling that  
compression for horizontal lines or vertical lines (for example).

I already said that for special cases, PNG can compress very well.  But  
those special cases don't usually hold true.  Without knowing anything  
else about the image, the fact is that the chances of any random image  
being able to be compressed by 1000-to-1 is extremely low.

Pete

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.