영상 압축 C# 소스 코드
영상압축 C#소스 코드
- 메뉴를 다음과 같이 추가한다.
- [압축_Load PCX] 메뉴를 더블클릭한 후 private void 압축LoadPCXDCTToolStripMenuItem_Click() 함수를 추가한다.
1234private void 압축LoadPCXToolStripMenuItem_Click(object sender, EventArgs e){f_LoadPCX();}
- PCX_HEADER 구조체를 생성한다.
12345678910111213141516171819202122232425262728[Serializable][StructLayout(LayoutKind.Sequential, Pack = 1)]struct PCX_HEADER{public byte manufacturer;public byte version;public byte encoding;public byte bits_per_pixel;public short xmin;public short ymin;public short xmax;public short ymax;public short hres;public short vres;//[FieldOffset(16)][MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]public byte[] palette16;public byte reserved;public byte color_planes;public short bytes_per_line;public short palette_type;//[FieldOffset(76)][MarshalAs(UnmanagedType.ByValArray, SizeConst = 58)]public byte[] filler;}
- f_LoadPCX() 함수를 생성한다.
PCX파일을 읽어서 그림으로 출력하는 함수 -
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657private void f_LoadPCX(){OpenFileDialog ofnDlg = new OpenFileDialog();ofnDlg.Filter = "pcx files (*.pcx)|*.pcx|pgm files (*.pgm)|*.pgm|jpg files (*.jpg)|*.jpg|png files (*.png)|*.png|bmp files (*.bmp)|*.bmp|All files (*.*)|*.*";ofnDlg.FilterIndex = 1;ofnDlg.RestoreDirectory = true;if (ofnDlg.ShowDialog() == DialogResult.OK){if (ofnDlg.FileName.ToUpper().Contains(".PCX")){PCX_HEADER pcx_header;int header_size = Marshal.SizeOf(typeof(PCX_HEADER));FileStream fs = new FileStream(ofnDlg.FileName, FileMode.Open, FileAccess.Read);BinaryReader br = new BinaryReader(fs);byte[] header = new byte[header_size];br.Read(header, 0, header.Length);GCHandle handle = GCHandle.Alloc(header, GCHandleType.Pinned);pcx_header = (PCX_HEADER)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PCX_HEADER));handle.Free();int imageWidth = pcx_header.xmax - pcx_header.xmin + 1;int imageHeight = pcx_header.ymax - pcx_header.ymin + 1;byte[] data = new byte[imageWidth * imageHeight];byte c;int p = 0;int run_length;while(true){c = br.ReadByte();if ((c & 0xc0) == 0xc0){run_length = c & 0x3f;c = br.ReadByte();while (run_length > 0){data[p++] = c;run_length--;}}else{data[p++] = c;}if (p >= imageWidth * imageHeight) break;}br.Close();Bitmap bmp = f_makeImageFromData(imageWidth, imageHeight, data);f_drawImage(bmp);}}}
- [압축_Save PCX] 메뉴를 더블클릭한 후 private void 압축SavePCXToolStripMenuItem_Click() 함수를 추가한다.
12345678910111213141516private void 압축SavePCXToolStripMenuItem_Click(object sender, EventArgs e){Bitmap bmp = f_OpenBitmapFile();if (bmp == null) return;byte[] data = f_getDataFromImage(bmp);////////////////// Startif (bmp.PixelFormat != PixelFormat.Format8bppIndexed){MessageBox.Show("8bit 색상 모델만 실행 가능합니다.");return;}f_SavePCX(data, bmp.Width, bmp.Height);////////////////// Endf_drawImage(bmp);}
- f_SavePCX() 함수를 생성한다.
영상을 PCX로 압축해서 저장하는 함수
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869private void f_SavePCX(byte[] data, int imageWidth, int imageHeight){SaveFileDialog ofnDlg = new SaveFileDialog();ofnDlg.Filter = "pcx files (*.pcx)|*.pcx|pgm files (*.pgm)|*.pgm|jpg files (*.jpg)|*.jpg|png files (*.png)|*.png|bmp files (*.bmp)|*.bmp|All files (*.*)|*.*";ofnDlg.FilterIndex = 1;ofnDlg.RestoreDirectory = true;if (ofnDlg.ShowDialog() == DialogResult.OK){PCX_HEADER pcx_header = new PCX_HEADER();;pcx_header.manufacturer = 10;pcx_header.version = 5;pcx_header.encoding = 1;pcx_header.bits_per_pixel = 8;pcx_header.xmin = 0;pcx_header.ymin = 0;pcx_header.xmax = (short)(imageWidth-1);pcx_header.ymax = (short)(imageHeight-1);pcx_header.hres = 150;pcx_header.vres = 150;pcx_header.color_planes = 1;pcx_header.bytes_per_line = (short)imageWidth;pcx_header.palette_type = 1;int header_size = Marshal.SizeOf(typeof(PCX_HEADER));byte[] header = new byte[header_size];GCHandle handle = GCHandle.Alloc(header, GCHandleType.Pinned);Marshal.StructureToPtr(pcx_header, handle.AddrOfPinnedObject(), false);handle.Free();FileStream fs = new FileStream(ofnDlg.FileName, FileMode.Create, FileAccess.Write);BinaryWriter bw = new BinaryWriter(fs);bw.Write(header);byte c;byte run_length;for (int y = 0; y < imageHeight; y++){run_length = 0;for (int x = 0; x < imageWidth; x++){c = data[y * imageWidth + x];run_length++;if (x < imageWidth - 1 && c == data[y * imageWidth + x + 1] && run_length < 63){//continue;}else if (run_length > 1 || (0xc0 & c) == 0xc0){byte b = (byte)(0xc0 | run_length);bw.Write(b);bw.Write(c);run_length = 0;}else{bw.Write(c);run_length = 0;}}}bw.Close();}}