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
}
}
}
Related
I'm working on project that encrypting video frames using RC4 algorithm and save these frames in playable video file.
I used a package named Accord.Video.FFMPEG. This package has a classes (VideoFileReader, & VideoFileWriter) that reads and writes video frames.
The first step is reads the video:
VideoHandler v = new VideoHandler();
OpenFileDialog newimag = new OpenFileDialog();
if (newimag.ShowDialog() == DialogResult.OK)
{
textfile = newimag.FileName;
picbox.ImageLocation = textfile;
status1.Text = "loaded";
//MessageBox.Show("your video file have been loaded seccufly"); // is an idea for viwing message
}
bytedata = v.ReadAllFrameBytes(textfile);
The second step is encrypting the frames of video:
byte[] bn = new byte[bytedata.Length];// new array to hold the encryptred file
bn = Encrypt(bytedata, ba);
The last step is saving the encrypted frames:
v.WriteFramesData(newfilepath, bn);
My encrypting algorithm is encrypting and decrypting the cipher with same algorithm and key.
These stpes works on Text, and Images files, but when I use it on video I can't restore the encrypted video. After some testings, I found that VideoFileWriter dosn't write the same input frames. Whyyyyyyy?
Here is my VideoFileHandler I made it:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Drawing.Imaging;
using System.IO;
using Accord.Video.FFMPEG;
namespace imgtobyt_1_in_c
{
class VideoHandler
{
public List<byte[]> data;
public byte[] imagedata;
public int Height, Width;
public byte[] ReadAllFrameBytes(string FileName)
{
// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open(FileName);
Height = reader.Height;
Width = reader.Width;
data = new List<byte[]>();
// read video frames
for (int i = 0; i < 100; i++) //change 100 to reader.FrameCount
{
Bitmap videoFrame = reader.ReadVideoFrame();
byte[] framebytes = GetBytesFromFrame(videoFrame);
data.Add(framebytes);
// dispose the frame when it is no longer required
videoFrame.Dispose();
}
reader.Close();
imagedata = new byte[data.Count * data[0].Length];
int c = 0;
for (int i = 0; i < data.Count; i++)
{
byte[] d = data[i];
for (int x = 0; x < d.Length; x++)
{
imagedata[c] = d[x];
c++;
}
}
return imagedata;
}
public byte[] GetBytesFromFrame(Bitmap Frame)
{
LockBitmap lockBitmap = new LockBitmap(Frame);
lockBitmap.LockBits();
byte[] framebytes = new byte[Frame.Width * Frame.Height * 3];
int z = 0;
for (int x = 0; x < lockBitmap.Height; x++)
for (int y = 0; y < lockBitmap.Width; y++)
{
Color Pixel = lockBitmap.GetPixel(y, x);
framebytes[z] = Pixel.R;
z++;
framebytes[z] = Pixel.G;
z++;
framebytes[z] = Pixel.B;
z++;
}
lockBitmap.UnlockBits();
return framebytes;
//using (var stream = new MemoryStream())
//{
// Frame.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
// return stream.ToArray();
//}
}
public Bitmap GetFrameFromBytes(byte[] Framebytes, ref int offset, int Width, int Height)
{
Bitmap Frame = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
LockBitmap lockBitmap = new LockBitmap(Frame);
lockBitmap.LockBits();
for (int x = 0; x < Height; x++)
for (int y = 0; y < Width; y++)
{
Color Pixel = Color.FromArgb(Framebytes[offset], Framebytes[offset + 1], Framebytes[offset + 2]); offset += 3;
lockBitmap.SetPixel(y, x, Pixel);
}
lockBitmap.UnlockBits();
return Frame;
//Bitmap bmp;
//using (var ms = new MemoryStream(Framebytes))
//{
// bmp = new Bitmap(ms);
//}
//return bmp;
}
public void WriteFramesData(string FileName, byte[] data)
{
// create instance of video writer
VideoFileWriter writer = new VideoFileWriter();
// create new video file
writer.Open(FileName, Width, Height);
int offset = 0;
// write video frames
for (int i = 0; i < 100; i++)
{
// create a bitmap to save into the video file
Bitmap Frame = GetFrameFromBytes(data, ref offset, Width, Height);
writer.WriteVideoFrame(Frame);
}
writer.Close();
}
}
}
Please, I need to make this works.
I changed pixel RGB value for a TIF image, but the generated tif image is not correct.
I use C# since there are some APIS for encoding and decoding TIF image format. My code is shown below.
public partial class Form1 : Form
{
private static int bytesPerPixel = 4;
private int width;
private int height;
byte[] bytes;
BitmapSource bitmapSource;
FormatConvertedBitmap convertedBitmap;
public Form1()
{
InitializeComponent();
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{ .....
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Open the selected file to read.
string fileName = openFileDialog1.FileName;
pictureBox1.Load(fileName);
// Open a Stream and decode a TIFF image
Stream imageStreamSource = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
bitmapSource = decoder.Frames[0];
convertedBitmap = new FormatConvertedBitmap(bitmapSource, PixelFormats.Bgra32, null, 0);
bytesPerPixel = (convertedBitmap.Format.BitsPerPixel + 7) / 8;
width = convertedBitmap.PixelWidth;
height = convertedBitmap.PixelHeight;
bytes = new byte[width * height * bytesPerPixel];
convertedBitmap.CopyPixels(bytes, (convertedBitmap.PixelWidth * convertedBitmap.Format.BitsPerPixel + 7) / 8, 0);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
Color color = GetPixel(bytes, i,j, bytesPerPixel);
if (i < width / 2 || j < height / 2)
setPixel(bytes, i, j, bytesPerPixel, (byte)(0), (byte)(0), (byte)(0));
else {
setPixel(bytes, i, j, bytesPerPixel, (byte)(255), (byte)(255), (byte)(255));
}
}
}
}
}
private static Color GetPixel(byte[] bgraBytes, int x, int y, int width)
{
var index = (y * (width * bytesPerPixel) + (x * bytesPerPixel));
return Color.FromArgb(
bgraBytes[index + 3],
bgraBytes[index + 2],
bgraBytes[index + 1],
bgraBytes[index]);
}
private static void setPixel(byte[] bytes, int x, int y, int width, byte r, byte g, byte b) {
var index = (y * (width * bytesPerPixel) + (x * bytesPerPixel));
bytes[index] = r; bytes[index + 1] = g; bytes[index + 2] = b;
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{ ................
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
int stride = width *8;
// Define the image palette
BitmapPalette myPalette = BitmapPalettes.WebPalette;
// Creates a new empty image with the pre-defined palette
var image = new WriteableBitmap(convertedBitmap);
image.WritePixels(new Int32Rect(0, 0, convertedBitmap.PixelWidth, convertedBitmap.PixelHeight), bytes,
(convertedBitmap.PixelWidth * convertedBitmap.Format.BitsPerPixel + 7) / 8, 0);
FileStream stream = new FileStream(saveFileDialog1.FileName, FileMode.Create);
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.Compression = TiffCompressOption.Zip;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);
stream.Dispose();
}
}
}
In the code, a tif image is read and its pixel RGB is copied to the byte[] bytes which is a class field member. After modifying all pixel RGB color (by 255 -), the bytes is then used to initilize another image and writen to the disk.
There is no error during runtime, but the generated tif image is not the same as i expected. The generated image is the same as original one, which is not correct.
Could anyone explain the reason that the generated image the same as input one? It seems the writePixel() does not take effect. During debug, i do find the bytes parameter in writePixel has been updated. I do not know the reason, as i am not very skill at C#, nor Image format. The original code are from
https://msdn.microsoft.com/en-us/library/aa969817%28v=vs.110%29.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
and
TIFF file parsing in C#
The C# software I'm involved with writing has a component that involves the reading of barcodes from scanned documents. The PDFs themselves are opened using PDFSharp.
Unfortunately we're encountering an issue with the process when it involves Flate Decoding of PDFs. Basically, all we get is a bunch of fuzz, which means there is no barcode to check and the document is not recognised.
Our code (which we shamelessly "borrowed" from another Stack Overflow case!) is as follows:
private FileInfo ExportAsPngImage(PdfDictionary image, string sourceFileName, ref int count)
{
//This code basically comes from http://forum.pdfsharp.net/viewtopic.php?f=2&t=2338#p6755
//and http://stackoverflow.com/questions/10024908/how-to-extract-flatedecoded-images-from-pdf-with-pdfsharp
string tempFile = string.Format("{0}_Image{1}.png", sourceFileName, count);
int width = image.Elements.GetInteger(PdfImage.Keys.Width);
int height = image.Elements.GetInteger(PdfImage.Keys.Height);
int bitsPerComponent = image.Elements.GetInteger(PdfImage.Keys.BitsPerComponent);
var pixelFormat = new PixelFormat();
switch (bitsPerComponent)
{
case 1:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format1bppIndexed;
break;
case 8:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
break;
case 24:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
break;
default:
throw new Exception("Unknown pixel format " + bitsPerComponent);
}
var fd = new FlateDecode();
byte[] decodedBytes = fd.Decode(image.Stream.Value);
byte[] resultBytes = null;
int newWidth = width;
int alignment = 4;
if (newWidth % alignment != 0)
//Image data in BMP files always starts at a DWORD boundary, in PDF it starts at a BYTE boundary.
//Most images have a width that is a multiple of 4, so there is no problem with them.
//You must copy the image data line by line and start each line at the DWORD boundary.
{
while (newWidth % alignment != 0)
{
newWidth++;
}
var copy_dword_boundary = new byte[height, newWidth];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < newWidth; x++)
{
if (x <= width && (x + (y * width) < decodedBytes.Length))
// while not at end of line, take orignal array
copy_dword_boundary[y, x] = decodedBytes[x + (y * width)];
else //fill new array with ending 0
copy_dword_boundary[y, x] = 0;
}
}
resultBytes = new byte[newWidth * height];
int counter = 0;
for (int x = 0; x < copy_dword_boundary.GetLength(0); x++)
{
for (int y = 0; y < copy_dword_boundary.GetLength(1); y++)
{ //put 2dim array back in 1dim array
resultBytes[counter] = copy_dword_boundary[x, y];
counter++;
}
}
}
else
{
resultBytes = new byte[decodedBytes.Length];
decodedBytes.CopyTo(resultBytes, 0);
}
//Create a new bitmap and shove the bytes into it
var bitmap = new Bitmap(newWidth, height, pixelFormat);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
int length = (int)Math.Ceiling(width * bitsPerComponent / 8.0);
for (int i = 0; i < height; i++)
{
int offset = i * length;
int scanOffset = i * bitmapData.Stride;
Marshal.Copy(resultBytes, offset, new IntPtr(bitmapData.Scan0.ToInt32() + scanOffset), length);
}
bitmap.UnlockBits(bitmapData);
//Now save the bitmap to memory
using (var fs = new FileStream(String.Format(tempFile, count++), FileMode.Create, FileAccess.Write))
{
bitmap.Save(fs, ImageFormat.Png);
}
return new FileInfo(tempFile);
}
Unfortunately, all we get out of it is this http://i.stack.imgur.com/FwatQ.png
Any ideas on where we're going wrong, or suggestions for things we might try would be greatly appreciated.
Cheers
Thanks for the suggestions guys. One of the other developers managed to crack it - it was (as Jongware suggested) a JPEG, but it was actually zipped as well! Once unzipped it could be processed and recognised as normal.
I have 10-bits and 12-bits rawbayer (.raw) file. And i want to convert it to Bitmap image but i am unable to change it. 8-bits or 16-bits raw file changed easily but 10-bits or 12-bits can't be changed.
here is the code for 8-bits raw file to Bitmap.
private void DisplayImage08(string fileName) //Raw file name
{
// Open a binary reader to read in the pixel data.
// We cannot use the usual image loading mechanisms since this is raw
// image data.
try
{
BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open));
byte pixByte;
int i;
int iTotalSize = (int)br.BaseStream.Length;
// Get the dimensions of the image from the user
ID = new ImageDimensions(iTotalSize);
width = Convert.ToInt32(ID.txtwidth);
height = Convert.ToInt32(ID.txtheight);
//panel1.Width = width;
//panel1.Height = height;
pictureBox1.Width = width;
pictureBox1.Height = height;
pix08 = new byte[iTotalSize];
//pix08 = new byte[iTotalSize];
for (i = 0; i < iTotalSize; ++i)
{
pixByte = (byte)(br.ReadByte());
pix08[i] = pixByte;
}
br.Close();
int bitsPerPixel = 8;
stride = (width * bitsPerPixel + 7) / 8;
// Single step creation of the image
bmps = BitmapSource.Create(width, height, 96, 96, PixelFormats.Gray8, null,
pix08, stride);
//Bitmap bmp = new Bitmap();
// img.Source = bmps;
Bitmap bt = BitmapFromSource(bmps); //Change Bitmap source to Bitmap
pictureBox1.Image = bt; //Display on pictureBox
pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
}
catch (Exception e)
{
}
}
But i want to change 12-bits or 10 bits raw file to Bitmap.
So please help me on this, that how can i change it?
Thanks
This isn't a complete answer by no means, but this code will convert a 12 or 10 bit image, depending on how the data is packed, to a 8 bit image.
// Input data read from file
var pixels = ...
// Output
var bytes = new byte[width * height];
// Sort data
for (var i = 0; i < bytes.Length; i++)
{
if (i % 2 == 0)
{
var index = i * 3 / 2;
bytes[i] = pixels[index];
}
else
{
var index = (i * 3 + 1) / 2;
bytes[i] = pixels[index];
}
}
I have a problem.
I´m generating a dynamic BMP image and trying to send this to a ZEBRA printer by ZPL commands.
I need to convert my BMP to a GRF image. I think that my Hexadecimal extracted by the BMP image isn´t correct.
The printed image is blurred and incorrect.
This is my code:
string bitmapFilePath = #oldArquivo; // file is attached to this support article
byte[] bitmapFileData = System.IO.File.ReadAllBytes(bitmapFilePath);
int fileSize = bitmapFileData.Length;
Bitmap ImgTemp = new Bitmap(bitmapFilePath);
Size ImgSize = ImgTemp.Size;
ImgTemp.Dispose();
// The following is known about test.bmp. It is up to the developer
// to determine this information for bitmaps besides the given test.bmp.
int width = ImgSize.Width;
int height = ImgSize.Height;
int bitmapDataOffset = 62; // 62 = header of the image
int bitmapDataLength = fileSize - 62;// 8160;
double widthInBytes = Math.Ceiling(width / 8.0);
// Copy over the actual bitmap data from the bitmap file.
// This represents the bitmap data without the header information.
byte[] bitmap = new byte[bitmapDataLength];
Buffer.BlockCopy(bitmapFileData, bitmapDataOffset, bitmap, 0, (bitmapDataLength));
// Invert bitmap colors
for (int i = 0; i < bitmapDataLength; i++)
{
bitmap[i] ^= 0xFF;
}
// Create ASCII ZPL string of hexadecimal bitmap data
string ZPLImageDataString = BitConverter.ToString(bitmap).Replace("-", string.Empty);
string comandoCompleto = "~DG" + nomeImagem + ".GRF,0" + bitmapDataLength.ToString() + ",0" + widthInBytes.ToString() + "," + ZPLImageDataString;
Try the following code. Not tested!
public static string CreateGRF(string filename, string imagename)
{
Bitmap bmp = null;
BitmapData imgData = null;
byte[] pixels;
int x, y, width;
StringBuilder sb;
IntPtr ptr;
try
{
bmp = new Bitmap(filename);
imgData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
width = (bmp.Width + 7) / 8;
pixels = new byte[width];
sb = new StringBuilder(width * bmp.Height * 2);
ptr = imgData.Scan0;
for (y = 0; y < bmp.Height; y++)
{
Marshal.Copy(ptr, pixels, 0, width);
for (x = 0; x < width; x++)
sb.AppendFormat("{0:X2}", (byte)~pixels[x]);
ptr = (IntPtr)(ptr.ToInt64() + imgData.Stride);
}
}
finally
{
if (bmp != null)
{
if (imgData != null) bmp.UnlockBits(imgData);
bmp.Dispose();
}
}
return String.Format("~DG{0}.GRF,{1},{2},", imagename, width * y, width) + sb.ToString();
}
One thing to point out is that the bitmap being converted must be monochrome (that is, 1 bit per pixel). There is an example on Zebra's knowledgebase that demonstrates printing a simple monochrome image in ZPL: https://km.zebra.com/kb/index?page=answeropen&type=open&searchid=1356730396931&answerid=16777216&iqaction=5&url=https%3A%2F%2Fkm.zebra.com%2Fkb%2Findex%3Fpage%3Dcontent%26id%3DSA304%26actp%3Dsearch%26viewlocale%3Den_US&highlightinfo=4194550,131,153#. If you can convert your images into monochrome bitmaps, then you should be able to follow that example.
// Given a monochrome bitmap file, one can read
// information about that bitmap from the header
// information in the file. This information includes
// bitmap height, width, bitsPerPixel, etc. It is required
// that a developer understands the basic bitmap format and
// how to extract the following data in order to proceed.
// A simple search online for 'bitmap format' should yield
// all the needed information. Here, for our example, we simply
// declare what the bitmap information is, since we are working
// with a known sample file.
string bitmapFilePath = #"test.bmp"; // file is attached to this support article
byte[] bitmapFileData = System.IO.File.ReadAllBytes(bitmapFilePath);
int fileSize = bitmapFileData.Length;
// The following is known about test.bmp. It is up to the developer
// to determine this information for bitmaps besides the given test.bmp.
int bitmapDataOffset = 62;
int width = 255;
int height = 255;
int bitsPerPixel = 1; // Monochrome image required!
int bitmapDataLength = 8160;
double widthInBytes = Math.Ceiling(width / 8.0);
// Copy over the actual bitmap data from the bitmap file.
// This represents the bitmap data without the header information.
byte[] bitmap = new byte[bitmapDataLength];
Buffer.BlockCopy(bitmapFileData, bitmapDataOffset, bitmap, 0, bitmapDataLength);
// Invert bitmap colors
for (int i = 0; i < bitmapDataLength; i++)
{
bitmap[i] ^= 0xFF;
}
// Create ASCII ZPL string of hexadecimal bitmap data
string ZPLImageDataString = BitConverter.ToString(bitmap);
ZPLImageDataString = ZPLImageDataString.Replace("-", string.Empty);
// Create ZPL command to print image
string[] ZPLCommand = new string[4];
ZPLCommand[0] = "^XA";
ZPLCommand[1] = "^FO20,20";
ZPLCommand[2] =
"^GFA, " +
bitmapDataLength.ToString() + "," +
bitmapDataLength.ToString() + "," +
widthInBytes.ToString() + "," +
ZPLImageDataString;
ZPLCommand[3] = "^XZ";
// Connect to printer
string ipAddress = "10.3.14.42";
int port = 9100;
System.Net.Sockets.TcpClient client =
new System.Net.Sockets.TcpClient();
client.Connect(ipAddress, port);
System.Net.Sockets.NetworkStream stream = client.GetStream();
// Send command strings to printer
foreach (string commandLine in ZPLCommand)
{
stream.Write(ASCIIEncoding.ASCII.GetBytes(commandLine), 0, commandLine.Length);
stream.Flush();
}
// Close connections
stream.Close();
client.Close();
Please add 2 to widthInBytes - it works!!!
int bitmapDataOffset = int.Parse(bitmapFileData[10].ToString()); ;
int width = 624;// int.Parse(bitmapFileData[18].ToString()); ;
int height = int.Parse(bitmapFileData[22].ToString()); ;
int bitsPerPixel = int.Parse(bitmapFileData[28].ToString()); // Monochrome image required!
int bitmapDataLength = bitmapFileData.Length - bitmapDataOffset;
double widthInBytes = Math.Ceiling(width / 8.0)+2;