|
hi. thanks so much for your code. its so helpful for me. bu i have problem with color to.
i remove call function: (Image)ConvertToBitonal((Bitmap)bmp[i])
and sec CompressionNone or CompressionLZW but ths have error and not work
error is : "A generic error occurred in GDI+. Error in saving as multipage"
help me pls
|
|
|
|
|
|
While Saving Jpeg which contains text, the quality of image is reduced very much. Am doing some OCR Work in the image. So if the image quality reduce, then OCR Process cannot be succeed.
Can any one knows the solution ?
|
|
|
|
|
Hi,
I have an image which is a negative TIFF image. When i am trying to save the image, I want to convert it to a normal TIFF image. Can you please tell me how to differentiate between a normal TIFF and a Negative TIFF. I am using C#. Can you please send me the code for checking this. I think we have to change somehting in convertToBitonal(Bitmap original)???
.. I have been trying to find it for a long time.. but in vain... Please help me ASAP.
|
|
|
|
|
You saved me from these 500KB tif files.... Now they are nice and small, 30KB each.
Thanks!
|
|
|
|
|
First I'd like to say Thanks for the great article/code!
My question is if there is a way to specify the DPI of the resulting tiffs?
I have tiffs with 300 DPI B/W and they are ending up as 96 DPI.
Thanks
|
|
|
|
|
Thanks for your appreciation.
To answer your question,
You are getting resulting image with 96DPI but you want it to be 300DIP.
I am not able to understand why it is reducing DPI 96DIP from 300DPI. Can you please try to print your origional image's DPI value before applying any compression. I have the doubts that your image itself is having 96DPI.
I dont know about a way to set DPI for an image but if i get something, i will surely post it.
Thanks
Bijul Soni
|
|
|
|
|
|
I'm having the same issue, the resolution is staying the same but the DPI drops from original 200DPI to 96DPI.
Something weird, is that it appears the first page is what is messed up, and not the second in a multi frame tif.
There isn't any data loss, the viewer just shows the tiff first page, 96 points to an inch verses the 200 points to an inch.
Please let me know if you find anything, I'm still looking myself.
Excellent Artcle-
Thanks,
Jonathan
|
|
|
|
|
In the ConvertToBitonal routine add the line marked below:
// Create destination bitmap
Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
-----> destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
|
|
|
|
|
This really helps a lot. Please be aware though that MS fax printer driver seems to have a problem with CCITT4 encoding at 1728x2200, but not with a smaller size (fatal error even though submitted to the fax server successfully). A little bizarre, but the method of solving this is to use no compression.
|
|
|
|
|
Works perfectly for what I was trying to do. I had something similar to this, but not laid out as well and it was incredibly slow. Very efficient.
|
|
|
|
|
thanks a lot.
|
|
|
|
|
I do have a question. If the original image is in CCITT4 compression and 1bpp, is there a way to break the image up without having to do the bi-tonal conversion? Everything I've tried looses the compression and it seems there should be a way to take them apart and recombine without loosing the page parameters.
Edit: I see gcorgnet is having the same issue as me, please let us know if you come up with a solution to this problem. Thank you!
-- modified at 9:35 Tuesday 14th August, 2007
|
|
|
|
|
I found a solution and I wanted to share. Instead of passing in an array of bitmaps, I'm passing in an array of Images. For some reason (that I haven't researched), the Image.Save and Image.SaveAdd manages to keep the compression of the original tif. My guess is when converting from Image to Bitmap the compression is lost.
I'm going to try to share my code, if it's not clear let me know and if you want to add this to your article go ahead, I know I've spent a lot of time trying to figure this out so if this helps someone else I'm glad to be of service.
First you have to break the image up:
private void SplitTiff()<br />
{<br />
imageFile = Image.FromFile("Path to tif here",true);<br />
<br />
frameDimensions = new FrameDimension(imageFile.FrameDimensionsList[0]);<br />
<br />
numberOfImages = imageFile.GetFrameCount(frameDimensions);<br />
<br />
img = new Image[numberOfImages];<br />
<br />
try<br />
{<br />
for (int intFrame = 0;intFrame < numberOfImages;intFrame++)<br />
{<br />
imageFile.SelectActiveFrame(frameDimensions,intFrame);<br />
img[intFrame] = imageFile;<br />
}<br />
}<br />
catch (Exception _err)<br />
{<br />
}<br />
}
Then you call saveMultipageImage passing in the image array, location of the file to be saved, and the type ("TIFF").
public bool saveMultipageImage(Image[] img, string location, string type)<br />
{<br />
if (img != null)<br />
{<br />
try<br />
{<br />
ImageCodecInfo codecInfo = getCodecForstring(type);<br />
<br />
if (img.Length == 1)<br />
{<br />
<br />
EncoderParameters iparams = new EncoderParameters(2);<br />
Encoder iparam = Encoder.SaveFlag;<br />
EncoderParameter iparamPara = new EncoderParameter(iparam,(long)(EncoderValue.MultiFrame));<br />
iparams.Param[0] = iparamPara;<br />
iparam = Encoder.Compression;<br />
iparamPara = new EncoderParameter(iparam, (long)(EncoderValue.CompressionCCITT4));<br />
iparams.Param[1] = iparamPara;<br />
img[0].Save(location, codecInfo, iparams);<br />
}<br />
else if (img.Length > 1)<br />
{<br />
<br />
Encoder saveEncoder;<br />
Encoder compressionEncoder;<br />
EncoderParameter SaveEncodeParam;<br />
EncoderParameter CompressionEncodeParam;<br />
EncoderParameters EncoderParams = new EncoderParameters(2);<br />
<br />
saveEncoder = Encoder.SaveFlag;<br />
compressionEncoder = Encoder.Compression;<br />
<br />
SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.MultiFrame);<br />
CompressionEncodeParam = new EncoderParameter(compressionEncoder, (long)EncoderValue.CompressionCCITT4);<br />
EncoderParams.Param[0] = CompressionEncodeParam;<br />
EncoderParams.Param[1] = SaveEncodeParam;<br />
<br />
File.Delete(location);<br />
img[0].Save(location, codecInfo, EncoderParams);<br />
<br />
<br />
for (int i = 1; i < img.Length; i++)<br />
{<br />
if (img[i] == null)<br />
break;<br />
<br />
SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.FrameDimensionPage);<br />
CompressionEncodeParam = new EncoderParameter(compressionEncoder, (long)EncoderValue.CompressionCCITT4);<br />
EncoderParams.Param[0] = CompressionEncodeParam;<br />
EncoderParams.Param[1] = SaveEncodeParam;<br />
img[0].SaveAdd(img[i], EncoderParams);<br />
<br />
}<br />
<br />
SaveEncodeParam = new EncoderParameter(saveEncoder, (long)EncoderValue.Flush);<br />
EncoderParams.Param[0] = SaveEncodeParam;<br />
img[0].SaveAdd(EncoderParams);<br />
img[0].Dispose();<br />
}<br />
return true;<br />
}<br />
catch (Exception ee)<br />
{<br />
img[0].Dispose();<br />
throw new Exception(ee.Message + " Error in saving as multipage ");<br />
return false;<br />
}<br />
}<br />
else<br />
return false;<br />
}
-- modified at 11:02 Tuesday 14th August, 2007
|
|
|
|
|
I'm having problems disconnecting the image from the FileStream. I can store the tiff frames into a file no problem, but when I load it I have a problem having a "stand-alone" copy of the image.
Here's some code:
FileStream fs = File.Open(path, FileMode.Open);
Image img = Image.FromStream(fs);
pbox.Image = (Image)img.Clone();
//fs.Close();
When I have the above and change the page using img.SelectActiveFrame I have no problem but when I uncomment fs.Close(); I get a GDI+ generic error. This makes me think that the image is still connected to the stream. I tried to avoid this by making a clone of it, but the clone apparently is also attached to the FileStream. Any help would be appreciated.
|
|
|
|
|
hi
i also faced the same problem. The reason is if you close the filestream and then call selectframe you wont be able to iterate through pages of your multipage tiff file which is stored on the file system.So you have to put your filestream object open to perform operations like selectFrame. So if possible call fs.close() at the last once all the operations are done.
second thing if your intention is to append already saved multipage tiff file,pleaserefer my tricky code specifically the function saveToExistingFile.
|
|
|
|
|
You'd probably be ok if you Dispose of your image first then close the Stream. Remember that everything in .NET should be disposed of in a proper sequence, usually in the opposite order of which you've created them.
FileStream fs = File.Open(path, FileMode.Open);
Image img = Image.FromStream(fs);
pbox.Image = (Image)img.Clone();
img.Dispose();
fs.Close();
|
|
|
|
|
Hi,
I have a bunch of System.Drawing.Image objects that are already bitonal, using PixelFormat.Format1bppIndexed and having a resolution of 200dpi (all of them)
I just want to save them into one unique multipage tiff file.
When I try Image.Save(...) I receive a (very nice) exception : A generic error occured in GDI+...
if I create a new System.Drawing.Bitmap object from the image, the saving actually works but the files is too big (several MB). The cause is that the bitmap that has been created has a 32bpp color depth.
I had a look at your code, that actually works with my images, but I am damn sure there must be a way to avoid all that processing on my images that are already bitonal, etc...
Do you have any idea ?
Thanks,
Guillaume
|
|
|
|
|
Good You have explained your problem in a very nice way.I like that.
Now
As you are saying you are sure that all of your images are bitonal(1bppIndexed),it should work properly for Image.Save method.But as your reference variable is Image object, it is likely that it may convert your bitonal images into 32bpp which was the case while i was working on this code.Therefore it is advisable to convert them into bitonal because sometimes when you put bitonal images into Image/Bitmap object .NET converting them into 32bpp images and that's why you are seeing Generic Exception,
so as per my knowledge only way to tackle this problem is to explicitly convert images into Bitonal.
Still i will try my best to give you proper solution but it will take some time,so currently you can continue with this code
Ok Bye
Take Care
|
|
|
|
|
aha..... thanks again, this saved me from yet another hair-pulling session.
|
|
|
|
|
Images are converted into ccitt4 format. but what about color/gray/jpg images ?
I have *.tif and *.jpg files in the same directory. Now i want to make a multifpage tif image with the same compression. for example if *.tiff files compression is ccitt4 and *.jpg is jpeg then the output file.. which would be multipage tiff, should remain the same compression.
Pls help me,
help
help
help
help
thanks
|
|
|
|
|
Great work -
I'm having problem when convert C# code to vb.net 2005. I'm getting "Arithmetic operation result in an overflow" exception? I get the image to load but I keep get the exception error when saving it to multipage tiff. am I doing something wrong??
|
|
|
|
|
can u tell me in which line of code you are having expection ? means either converting image to bitonal image or calling save/save add function or during setting other parameters of image ?
|
|
|
|
|
The problem occur when calling savemultipage(). Thank you
Public Function saveMultipage(ByVal bmp As Image(), ByVal location As String, ByVal type As String) As Boolean
If Not (bmp Is Nothing) Then
Try
Dim codecInfo As ImageCodecInfo = getCodecForstring(type)
Dim i As Integer = 0
While i < bmp.Length
If bmp(i) Is Nothing Then
' break
End If
bmp(i) = CType(ConvertToBitonal(CType(bmp(i), Bitmap)), Image)
System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
End While
If bmp.Length = 1 Then
Dim iparams As EncoderParameters = New EncoderParameters(1)
Dim iparam As Encoder = Encoder.Compression
Dim iparamPara As EncoderParameter = New EncoderParameter(iparam, CType((EncoderValue.CompressionCCITT4), Long))
iparams.Param(0) = iparamPara
bmp(0).Save(location, codecInfo, iparams)
Else
If bmp.Length > 1 Then
Dim saveEncoder As Encoder
Dim compressionEncoder As Encoder
Dim SaveEncodeParam As EncoderParameter
Dim CompressionEncodeParam As EncoderParameter
Dim EncoderParams As EncoderParameters = New EncoderParameters(2)
saveEncoder = Encoder.SaveFlag
compressionEncoder = Encoder.Compression
SaveEncodeParam = New EncoderParameter(saveEncoder, CType(EncoderValue.MultiFrame, Long))
CompressionEncodeParam = New EncoderParameter(compressionEncoder, CType(EncoderValue.CompressionCCITT4, Long))
EncoderParams.Param(0) = CompressionEncodeParam
EncoderParams.Param(1) = SaveEncodeParam
File.Delete(location)
bmp(0).Save(location, codecInfo, EncoderParams)
i = 1
While i < bmp.Length
If bmp(i) Is Nothing Then
Exit While
End If
SaveEncodeParam = New EncoderParameter(saveEncoder, CType(EncoderValue.FrameDimensionPage, Long))
CompressionEncodeParam = New EncoderParameter(compressionEncoder, CType(EncoderValue.CompressionCCITT4, Long))
EncoderParams.Param(0) = CompressionEncodeParam
EncoderParams.Param(1) = SaveEncodeParam
bmp(0).SaveAdd(bmp(i), EncoderParams)
System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
End While
SaveEncodeParam = New EncoderParameter(saveEncoder, CType(EncoderValue.Flush, Long))
EncoderParams.Param(0) = SaveEncodeParam
bmp(0).SaveAdd(EncoderParams)
End If
End If
Return True
Catch ee As System.Exception
Throw New Exception(ee.Message + " Error in saving as multipage ")
End Try
Else
Return False
End If
End Function
|
|
|
|