I read a Tiff file, and I want to make a tile and save it to Png or Jpg. I successfully did this process saving in Tif format, as shown in the attached code, defining DO_TIFF. But I cannot do the same in Jpeg or Png format. The program always crashes at the location indicated in the comment. I have read various indications in Internet, but I cannot find my mistake. The code should be selfexplaining. The difference is that I used two dimensional array in the Tif case, while a one dimensional one in the JPEG case.
private static void MakeTile(string Original,int X,int Y,int W,int H,string TileName)
{
using (Tiff input = Tiff.Open(Original, "r"))
{
int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt();
int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt();
Rectangle roi = new Rectangle(X*samplesPerPixel, Y, W * samplesPerPixel, H);
int scanlineSize = input.ScanlineSize();
int nz = roi.Width;
if (roi.Left nz > scanlineSize)
{
nz = scanlineSize-roi.Left;
}
#if DO_JPEG
byte[] output = new byte[roi.Height * nz];
#endif
#if DO_TIFF
byte[][] output = new byte[roi.Height][];
#endif
byte[] buffer = new byte[scanlineSize];
W = nz / samplesPerPixel;
for (int i = roi.Top,k=0; i < roi.Bottom; i,k )
{
input.ReadScanline(buffer, i);
#if DO_TIFF
output[k] = new byte[nz];
#endif
for (int j=0;j<nz;j )
{
#if DO_TIFF
output[k][j]= buffer[roi.Left j];
#endif
#if DO_JPEG
output[j k*nz] = buffer[roi.Left j];
#endif
}
}
#if DO_JPEG
using (Image image = Image.FromStream(new MemoryStream(output)))// error here: Patrameter Not Valid
{
image.Save("output.jpg", ImageFormat.Jpeg); // Or Png
}
#endif
#if DO_TIFF
using (Tiff Foutput = Tiff.Open(TileName, "w"))
{
Foutput.SetField(TiffTag.IMAGEWIDTH, W);
Foutput.SetField(TiffTag.IMAGELENGTH, H);
Foutput.SetField(TiffTag.SAMPLESPERPIXEL, samplesPerPixel);
Foutput.SetField(TiffTag.BITSPERSAMPLE, bitsPerSample);
Foutput.SetField(TiffTag.ROWSPERSTRIP, Foutput.DefaultStripSize(0));
Foutput.SetField(TiffTag.PHOTOMETRIC, photo);
Foutput.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
// change orientation of the image
// output.SetField(TiffTag.ORIENTATION, Orientation.RIGHTBOT);
for (int i = 0; i < H; i)
Foutput.WriteScanline(output[i], i);
}
#endif
}
}
}
CodePudding user response:
To save the image as a JPEG or PNG, you'll need to use a different method than the one you are using to save it as a TIFF.
One way to do this is to use the System.Drawing.Bitmap class. This class has a constructor that takes an array of bytes as an argument, so you can pass the output array to the constructor to create a Bitmap object. Then, you can use the Save method of the Bitmap class to save the image to a file in JPEG or PNG format.
#if DO_JPEG
using (var image = new Bitmap(W, H, PixelFormat.Format24bppRgb)) {
var bmpData = image.LockBits(new Rectangle(0, 0, W, H),
ImageLockMode.WriteOnly, image.PixelFormat);
var ptr = bmpData.Scan0;
Marshal.Copy(output, 0, ptr, output.Length);
image.UnlockBits(bmpData);
image.Save("output.jpg", ImageFormat.Jpeg);
}
#endif
To save the image as a PNG, you can use the same code but replace ImageFormat.Jpeg with ImageFormat.Png.
Assuming that the output array contains 24-bit RGB data.