Month: September 2009

การ Restore Image ของ Harddisk ด้วยแผ่น System Rescue LiveCD (ตอนที่ 2)

  • System Rescue Live CD เป็น Live CD ที่สร้างมาจาก Gentoo Linux (ดิสโทรตัวจริงของ Gentoo นี่ผมยังไม่เคยลองเลย) ส่วนระบบกราฟฟิคเปลี่ยนมาใช้ Xfce v.4 เป็น Desktop environment จากเดิมเคยใช้ JVM และ WMaker
  • จากตอนที่ 1 เมื่อเราเขียน  image พาร์ทิชั่นของฮาร์ดดิสค์เก็บไว้แล้ว เช่นพาร์ทิชั่นของวินโดส์ ผู้ใช้ linux อาจจะมีพาร์ทิชั่น Ubuntu, PCLos, Opensuse ตามแต่ distro ที่ใช้ ตอนที่แล้วผมแนะนำให้เขียนเก็บไว้ที่ external harddisk เนื่องจากสะดวกและราคาไม่แพง
  • ส่วนแผ่นบู๊ตแนะนำให้ใช้ USB Flash drive แทน CD เพื่อลดความสิ้นเปลืองและรักษาสิ่งแวดล้อม ตอนนี้เราจะใช้ USB Flash drive ที่ติดตั้ง System Rescue LiveCD ไว้ทำการบู๊ตเครื่องคอมพิวเตอร์ ก่อนการบู๊ตจัดการต่อ External harddisk ผ่านทางช่อง USB ให้เรียบร้อย และไม่ลืมเสียบ USB Flash drive แผน่บู๊ตของเรา  ขณะทำการเปิดเครื่องช่วงอ่าน BIOS ให้กดคีย์เช่น คีย์ F12 เพื่อเลือก Multiboot จะมีทางเลือกให้เช่นบู๊ตจาก internal harddisk, CD-Rom หรือ USB Flash drive ให้เลือก USB Flash drive
  • เมื่อบู๊ตด้วย System Rescue Live CD เรียกสั้นๆว่า Sysrescd ถ้าไม่มีปัญหาอะไรจะมาหยุดอยู่ที่ prompt ของ command line คล้ายๆกับรูปด้านล่าง (เอามาจาก website Sysrescd)
เมื่อบู๊ตด้วย System Rescue Live CD สำเร็จ
เมื่อบู๊ตด้วย System Rescue Live CD สำเร็จ
  • พิมพ์คำสั่ง startx เพื่อบู๊ตเข้าโหมดกราฟฟิคroot@sysresccd /root % startx

root@sysresccd /root % startx

  • เมื่อบู๊ตเข้าไปในโหมดกราฟฟิคแล้ว เราจะสร้างไดเรคทอรีเพื่อจะเมาท์ (รายละเอียดการสร้างไดเรคทอรีและการเมาท์ ดูได้จากตอนที่ 1) เมื่อสร้างเสร็จแล้วก็เมาท์ ก่อนจะทำการเมาท์ตรวจสอบ device ของฮาร์ดดิสค์ด้วย GParted ดังที่ได้กล่าวไปแล้ว ใช้คำสั่งดังต่อไปนี้

root@sysresccd /root % cd /mnt

root@sysresccd /mnt % mkdir pjdiskimages

root@sysresccd /mnt % ntfs-3g /dev/sdc2 /mnt/pjdiskimages

วิธีสร้างไดเรคทอรีและเมาท์พาร์ทิชั่น

 

  • เมื่อเมาท์แล้วไม่ลืมที่จะตรวจด้วยการเรียกใช้โปรแกรม Midnight commander ด้วยการคลิก Start > Misc > Midnight commander เมื่อเปิดโปรแกรมแล้ว browse ไปที่ /mnt/pjdiskimages ของผมเก็บ image ไว้ที่ /mnt/pjdiskimages/win_images/Acer4920G
ตรวจสอบไดเรคทอรีที่เก็บไฟล์ image ด้วย Midnight Commander
ตรวจสอบไดเรคทอรีที่เก็บไฟล์ image ด้วย Midnight Commander
  • เมื่อเราสร้างไฟล์ image ตั้งชื่อตอนสร้าง win_im.gz โปรแกรม Partimage จะสร้าง extension ต่อให้อัตโนมัติ จะเห็นไฟล์ win_im.gz.000, win_im.gz.001,win_im.gz.002,……,win_im.gz.011 ไฟล์ชุดนี้เราจะมา restore เพื่อเขียน image ของวินโดส์ ขั้นตอนต่อไปเปิดโปรแกรม Partimage

root@sysresccd /mnt % partimage

การตั้งค่าให้ System Rescue CD เพื่อ restore image

  • สำคัญมากการตั้งค่าหน้านี้ของ Partimage จากรูปด้านบนเลือก sda1 ก็คือ /dev/sda1 เป็นพาร์ทิชั่นฮาร์ดดิสค์ของวินโดส์ ที่ Image file to create/restore เลือก image file ที่เขียนไว้ตอนที่ 1 คือ /mnt/pjdiskimages/win_images/Acer4920G/win_im.gz.000 สังเกตชื่อไฟล์ตอนสร้างในตอนที่ 1 เราตั้งชื่อ win_im.gz แต่การ restore ให้อ้างชื่อให้เต็มโดยมีจุด 000 ต่อท้ายด้วย และที่สำคัญอีกที่หนึ่งคือ Action to be done : เลือกบรรทัดที่สองคือ (*) Restore partition from an image file เมื่อเรียบร้อยกด F5 เพื่อไปหน้าต่อไป

 

แสดง comment ที่เราพิมพ์ไว้เมื่อตอนสร้าง image
แสดง comment ที่เราพิมพ์ไว้เมื่อตอนสร้าง image
  • จากรูปด้านบนจะเห็น comment ผมเขียน password แสดงไว้ด้วยเผื่อกรณีที่เปลี่ยน password ในวินโดส์หลายครั้งจนลืม กด OK เพื่อไปหน้าต่อไป

Simulation or not

  • จากรูปด้านบนมี options ให้เลือกเช่นต้องการ Simulate แสดงการ restore ไฟล์ image แต่ไม่มีการเขียนจริง และเมื่อ Partimage ทำการเสร็จแล้ว (If finished successfully:) จะให้ปิดเครื่องไปเลยหรือปล่าว หรือต้องการรีบู๊ต กด F5 ผ่านไปใช้ค่าปริยาย

Warning

  • โปรแกรม Partimage จะแสดงรายละเอียดของ image file ที่เราจะ restore พร้อมกับเตือนเล็กน้อยดังรูปด้านบน กด OK เพื่อไปต่อ

NTFS InformationsFinished Successfully

  • สุดท้ายก่อนจะ restore ไฟล์ image โปรแกรม Partimage จะแสดงรายละเอียดของไฟล์ image ดังรูปข้างบน กด Ok เพื่อเริ่มการ restore ลงพาร์ทิชั่น sda1

Restoring image file to harddisk.

  • ขั้นตอนนี้โปรแกรม Partimage จะเริ่ม restore ไฟล์ของ image ที่เขียนไว้ที่ External harddisk (ในที่นี้ device คือ /dev/sdc2) จะ restore ลงไปยัง internal harddisk ของเครื่องโน๊ตบุ๊คของผมคือ /dev/sda1 ซึ่งเป็นพาร์ทิชั่นของวินโดสFinished Successfully
  • ตอน restore ไฟล์ image นี่ไม่ต้องรอนานเหมือนตอนเขียนไฟล์ เสร็จแล้วก็กด Ok เพื่อออกจากโปรแกรม Partimage ถ้าทุกอย่างเรียบร้อยแล้วก็ออกจากด้วยคำสั่ง

root@sysresccd /mnt % shutdown -r now

  • เมื่อบู๊ตเครื่องลองเข้าวินโดส์ว่า OK หรือไม่ เท่าที่ผมใช้มานานแล้วไม่เคยพบว่า Restore แล้วจะเข้าวินโดส์ไม่ได้เลย ก็ขอให้โชคดีและสนุกกับการเขียน image file พาร์ทิชั่นฮาร์ดดิสค์เก็บไว้และ Restore image file

 

 

How to import Vector file (DWG/Shape file) to Google Earth.

  • หลายๆคนที่เคยใช้ Google Earth คงประทับใจในการพัฒนาของโปรแกรมที่สามารถใช้ในงานได้หลากหลายมากขึ้น โดยเฉพาะงาน Presentation การสร้าง Path แล้วจำลองบินดูลักษณะภูมิศาสตร์เป็น 3D  แล้ว save เป็นไฟล์วีดีโอ ด้วยการใช้งานที่ง่าย Google Earth จึงเป็นโปรแกรมยอดนิยม ที่ทำให้การเรียนเรื่องภูมิศาสตร์สำหรับนักเรียนประถมและมัธยมไม่ใช่เรื่องที่น่าเบื่อเหมือนสมัยก่อน
  • หลายๆโอกาส ถ้าเรามีไฟล์ลายเส้นหรือ vector เช่น Autocad dwg, Shape file จะนำเข้าไปใน Google Earth เพื่อการแสดงผลได้อย่างไร ปัจจุบันที่ผมทราบโปรแกรมด้าน Cad เช่น ProgeCad (ทางเลือกแทน Autocad) ก็สามารถเขียนไฟล์ DWG ไปเป็นฟอร์แมตของ Google Earth คือ KMZ หรือ KML ได้เลย  แต่ที่จะขอแนะนำตอนนี้คือ Global Mapper V.10

แสดงภาพลายเส้น Autocad บน Google Earth

Global Mapper V.10

  • ผมยังไม่เคยเห็นโปรแกรมไหนที่จะอ่าน Vector และ Raster ไฟล์ ได้หลากหลาย format เท่ากับ Global mapper มาก่อนทั้ง DEM, รูปภาพทั้ง Geotiff,  Mrsid, Erdas Imagine หรือพื้นๆอย่าง Jpeg และในส่วน vector file สามารถอ่าน Autocad DWG, Microstation DGN, ESRI Shape file หรือแม้กระทั่งไฟล์ของ GPS เช่น Garmin (ต้อง save จาก Mapsource หรือ OziExplorer)
  • สิ่งที่สำคัญที่ต้องตระหนักว่าไฟล์ DWG ที่จะนำมา import เข้า Google Earth นั้นจะต้องมีระบบพิกัดเป็นจริงตามภูมิศาสตร์ ที่ง่ายที่สุดคือมีค่าพิกัดเป็นระบบยูทีเอ็ม (UTM) ในประเทศไทยเราใช้ระบบพิกัดนี้อยู่มีอยู่ 2 Zone เท่านั้นคือ Zone 47 และ Zone 48 และอีกอย่างที่สำคัญไม่แพ้กันคือต้องมีระบบพิกัดอ้างอิงอยู่กับพื้นหลักฐาน WGS84 ประเทศไทยเรา ก่อนหน้านี้เราใช้พื้นหลักฐาน Indian 1975 แต่หน่วยงานราชการบ้านเราบางหน่วยงานก็หันไปใช้ WGS84 กันมากขึ้น (ที่จริงหลักฐาน Indian 1975 ก็สามารถใช้ได้แต่ต้องต้องตั้งค่า Projection ให้กับ Global Mapper ซึ่งผมจะไม่กล่าวในที่นี้)
  • เมื่อเรามีไฟล์ Autocad DWG ที่มีระบบพิกัดจริง คือที่เรียกว่า Georeference เปิดไฟล์ด้วย Autocad แต่ตอนนี้ผมใช้ Bricscad ดังรูปข้างล่าง

เปิดไฟล์ DWG ด้วย Bricscad

  • ผมแนะนำให้เปิดไฟล์ขึ้นมาเพื่อทำการ Optimize ให้ไฟล์มีรายละเอียดให้น้อยลง ลบ layer บาง layer ออก ลบเส้นบางอย่างออก เอาไว้เฉพาะรายละเอียดที่สำคัญ ที่ำสำคัญคือ load เข้า Google Earth ได้เร็วขึ้น เมื่อ Optimize แล้วให้ทำการ save เป็น DWG เหมือนเดิม
  • เปิดโปรแกรม Global Mapper ขึ้นมาใช้เมนู File >Open Data File(s)… เลือกไฟล์ DWG ที่เราเซฟไว้แล้ว โดยให้เลือก file of type เป็น DWG files เมื่อเปิดมาแล้ว Global mapper จะถามระบบพิกัดของไฟล์ DWG
Georeference parameters
Georeference parameters
  • จากรูปด้านบนเลือก Projection เป็น UTM เลือก Zone เป็น 48 เลือก Datum เป็น WGS84 หน่วยเป็นเมตร ตาม default กด OK จะเห็นรูป DWG file ปรากฎบน Global mapper เข้าพิกัดได้อย่างถูกต้อง

Global Mapper อ่านไฟล์ DWG

  • เราจะใช้ Global Mapper เป็นสะพานในการแปลงไฟล์จาก DWG ไปเป็น KMZ ซึ่งเป็นฟอร์แมตของ Google earth ที่เมนูของ Global mapper คลิก File > Export Vector Data > Export KML/KMZ… ดังรูปด้านล่าง

Export to KMZ format.

  • Global mapper จะถาม options ของ KMZ format เลือกตอบ default และเซฟไฟล์เป็นฟอร์แมตของ Google earth
  • เปิด Google earth ที่เมนูคลิก File > Open… เลือกไฟล์ KMZ ที่เราเซฟไว้ข้างต้นจะเห็นภาพดังรูปด้านล่าง

Google earth

  • ที่ Google earth ปรับทิศเหนือให้ได้มุมที่ต้องการ ปรับมุมเอียงให้ได้ภาพ 3D แต่อย่าลืมเลือก Layers “Terrain” ที่ Side bar ของ Google earth ด้วยการติ๊กถูก เพื่อให้ Google earth จำลองภาพสามมิติได้ ตัวอย่างดังรูปด้านล่าง
3D on Google earth
3D on Google earth

How to draw rotated text on Lazarus

  • ความจริงถ้าเป็น Delphi การเขียนตัวหนังสือแบบหมุนเอียงเป็นเรื่องง่ายๆ ด้วยการเรียกใช้ Win API ฟังก์ชั่นที่เรียกใช้คือ SetTextAlign, และ TextOut แต่ผมประหลาดใจว่า Lazarus  หรือ Freepascal ทำไมไม่มี SetTextAlign เข้าใจว่า Lazarus มัน cross-platform ตัวกราฟฟิคนอกจากขึ้นกับ OS แล้วยังขึ้นกับ Widgets ที่เราใช้อยู่ด้วยเช่นบน Linux มี Gtk2 บน Mac OS มี Qt, Carbon และบนวินโดส์เองใช้ Win API แต่ละ Widgets จะมีไลบรารีกราฟฟิคของตนเป็นเอกเทศ เรื่องง่ายๆจึงเป็นเรื่องยาก ผมเห็นโปรแกรมเมอร์ถามกันมากบนฟอรั่มของ Lazarus เรื่องการเขียนตัวหนังสือแบบหมุนเอียง แต่ไม่มีใครตอบได้น่าพอใจ
  • ในฐานะที่ผมตอนเรียนมหาวิทยาลัย วิชาที่เรียนเกี่ยวข้องกับคณิตศาสตร์เรื่องตรีโกณมิติ เรื่องพิกัด เรื่องแกน ไล่ไปจนถึงสัณฐานของโลกที่เป็นทรงรี (Ellipsoid) การสามเหลี่ยมแบบโค้งบนทรงกลม และ Geodesy ผมจึงนำคณิตศาสตร์ที่เป็นพื้นฐานง่ายๆ คือการย้ายแกน X,Y และหมุนแกน มาช่วยเพื่อให้การเขียน Rotated Text ทำได้ง่ายๆถ้าเรียกใช้ฟังก์ชั่นที่ผมเขียนและจะได้กล่าวต่อไป

ตัวอย่างการเขียนตัวหนังสือแบบหมุนเอียง (Rotated Text)

  • จากรูปข้างบนเป็นโครงการ OpenGPS ที่เขียนรูปจำลองท้องฟ้า โดยที่ด้านบนคือทิศเหนือ (N) และไล่ตามทิศทางตามเข็มนาฬิกา มาที่มุม 30 องศา, 60 องศา และ 90 องศาคือทิศตะวันออก (E) เป็นเช่นนี้จนถึงทิศใต้ (S) ทิศตะวันตก (W)  มุมนี้ในทางวิชาการสำรวจเรียกว่าอะซิมัท (Azimuth) เป็นมุมกวาดตามเข็มนาฬิกาจากทิศเหนือ ในโครงการ OpenGPS ผมเอาไว้วาดสัญลักษณ์ GPS ที่ปรากฎอยู่บนท้องฟ้าในขณะนั้น
  • เปิดโปรแกรม Lazarus ตัวอย่างที่ผมจะเขียนจะอยู่บน Ubuntu แต่ถ้าใช้ Windows ก็ไม่ต่างกัน ที่เมนเมนูคลิกที่ Project > New Project… จะพบ dialog ถามชนิดของโปรแกรมที่จะเขียน เลือก Application แล้วกด OK
  • ตรง Main Form จะเป็นฟอร์มเปล่าๆ ตรง Palette เลือก Additional คลิกที่ไอคอน TPaintBox แล้วมาคลิกลงบนฟอร์ม ตั้งขนาด Width และ Height เท่ากับ 360 จะได้ฟอร์มที่มี TPaintBox อยู่บนฟอร์มดังรูปข้างล่าง ส่วน properties อื่นๆ ไม่ต้องตั้งค่าอะไรให้ทั้งสิ้นใช้เป็นค่าดีฟอลท์

Lazarus บน Ubuntu

  • คัดลอก pascal code ข้างล่างไปแปะ (paste) ทับตรง Unit1 ทั้งหมด คลิกที่ฟอร์ม จากนั้นที่ Object Inspector ตรงแท็บ Event หา OnCreate คลิกไปที่ปุ่มเล็กๆที่มีจุดสามจุดเพื่อจะได้ลิงค์มายังมายัง TForm1.FormCreate และคลิกที่ PaintBox ที่ Object Inspector ตรงแท็บ Event หา OnPaint เช่นเดียวกันคลิกที่ปุ่มเล็กๆ เพื่อเชื่อมมายัง code ที่เราเพิ่งแปะไป
//=========================================================================================
unit Unit1;

<p> </p>

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
ExtCtrls, Types;

const
DEGREETORADIANS = 0.0174532925199433;
PI = 3.14159265358979;

type
//Transformation parameters
TTransformPara = record
TX1 : double; //Translation X1
TY1 : double; //Translation Y1
RotationAngle : double;
ScaleX : double;
end;

//Text alignment
THozAlignment = (haLeft, haRight, haCenter);
TVerAlignment = (vaTop, vaBottom, vaCenter);

//TRotationText type for example of rotation texts.
TRotationText = record
FaceName : string;
Color : longint;
Height : longint;
Weight : TFontStyle;
Text : string;
RotationAngle : double;
HozAlignment : THozAlignment;
VerAlignment : TVerAlignment;
end;

const
//Array of TRotationText.
SkyPlotBackground : array[0..11] of TRotationText = (
(FaceName:'Sans';Color:clBlue;Height:11;Weight:fsBold;
Text:'N';RotationAngle:90;HozAlignment:haCenter;VerAlignment:vaBottom),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:' 30';RotationAngle:30;HozAlignment:haLeft;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:' 60';RotationAngle:60;HozAlignment:haLeft;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlue;Height:11;Weight:fsBold;
Text:' E';RotationAngle:90;HozAlignment:haLeft;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:' 120';RotationAngle:120;HozAlignment:haLeft;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:' 150';RotationAngle:150;HozAlignment:haLeft;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlue;Height:11;Weight:fsBold;
Text:'S';RotationAngle:90;HozAlignment:haCenter;VerAlignment:vaTop),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:'210 ';RotationAngle:30;HozAlignment:haRight;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:'240 ';RotationAngle:60;HozAlignment:haRight;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlue;Height:11;Weight:fsBold;
Text:'W ';RotationAngle:90;HozAlignment:haRight;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:'300 ';RotationAngle:120;HozAlignment:haRight;VerAlignment:vaCenter),
(FaceName:'Sans';Color:clBlack;Height:10;Weight:fsBold;
Text:'330 ';RotationAngle:150;HozAlignment:haRight;VerAlignment:vaCenter)
);

type

{ TForm1 }

TForm1 = class(TForm)
PaintBox1: TPaintBox;
procedure FormCreate(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
private
{ private declarations }
FTransfrm : TTransformPara;
FSkyHalf, FSkyMargin : double;
function SetTransformationPara(Tx, Ty, Scale, RotatedAng : double) : TTransformPara; function Polar2Cartesian(Radius : double; Azimuth : double) : TPoint; function User2Pixel(sp : TPoint; tsf : TTransformPara) : TPoint;
function DrawRotatedText(cv : TCanvas; Txt : string; InsertPt : TPoint;
RotateAngle : double; HozAlign : THozAlignment;
VerAlign : TVerAlignment): boolean;
function DrawCircle(cv : TCanvas; Center : TPoint; cRadius : integer) : boolean; public
{ public declarations }
end;

var
Form1: TForm1;

implementation

procedure TForm1.FormCreate(Sender: TObject);
var
dtx, dty, dScale, dAng : double;
begin
//Left, right, top, bottom margin of the area to draw the sky.
FSkyMargin := 30;
FSkyHalf := (PaintBox1.Width - 2 * FSkyMargin) / 2;

//Translate or move from image system to center of image (TPaintBox).
dtx := FSkyHalf + FSkyMargin;
dty := FSkyHalf + FSkyMargin;
dscale := 1.0;
dAng := 0.0;
//Set transformation by Calling SetTransformationPara.
FTransfrm := SetTransformationPara(dtx, dty, dscale, dAng);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
var
dRad, dAng : double;
i : integer;
fnt : TFont;
sk1, sk2, cen : TPoint;
img1, img2 : TPoint;
begin
dRad := FSkyHalf;
dAng := 0; //Accumulated angle.
with PaintBox1 do
begin
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := clWhite;
Canvas.FillRect(0, 0, Width, Height);

//Set brush style to clear to disable fill for drawing circle.
Canvas.Brush.Style := bsClear;
//Center of Sky Plot
sk1 := Point(0, 0);
cen := User2Pixel(sk1, FTransfrm);
Canvas.Pen.Color := clRed;
//Elevation = 0 (horizone line)
DrawCircle(Canvas, cen, trunc(dRad));
Canvas.Pen.Color := clRed;
//Elevation at 30 degree
DrawCircle(Canvas, cen, trunc(dRad / 3));
Canvas.Pen.Color := clBlack;
//Elevation at 60 degree
DrawCirCle(Canvas, cen, trunc(dRad * 2 / 3));

//Middle horizontal line
sk1 := Polar2Cartesian(dRad, 90);
sk2 := Polar2Cartesian(dRad, 270);
img1 := User2Pixel(sk1, FTransfrm);
img2 := User2Pixel(sk2, FTransfrm);
Canvas.MoveTo(img1.X, img1.y);
Canvas.LineTo(img2.X, img2.y);

//Middle vertical line
sk1 := Polar2Cartesian(dRad, 0);
sk2 := Polar2Cartesian(dRad, 180);
img1 := User2Pixel(sk1, FTransfrm);
img2 := User2Pixel(sk2, FTransfrm);
Canvas.MoveTo(img1.X, img1.y);
Canvas.LineTo(img2.X, img2.y);

//Azimuth line from 30 degree to 210 degree.
sk1 := Polar2Cartesian(dRad, 30); //Azimuth 30 degree.
img1 := User2Pixel(sk1, FTransfrm);
//the opposite of point sk1 which azimuth = 30 is 210 (30 + 180) degree.
sk2 := Polar2Cartesian(dRad, 210); //Azimuth 210 degree.
img2 := User2Pixel(sk2, FTransfrm);
Canvas.Pen.Color := clBlack;
Canvas.MoveTo(img1.X, img1.y);
Canvas.LineTo(img2.X, img2.Y);

//Azimuth line from 60 degree to 240 degree.
sk1 := Polar2Cartesian(dRad, 60); //Azimuth 60
img1 := User2Pixel(sk1, FTransfrm);
sk2 := Polar2Cartesian(dRad, 240); //Azimuth 240
img2 := User2Pixel(sk2, FTransfrm);
Canvas.MoveTo(img1.X, img1.y);
Canvas.LineTo(img2.X, img2.Y);

//Azimuth line from 120 degree to 300 degree.
sk1 := Polar2Cartesian(dRad, 120); //Azimuth 120
img1 := User2Pixel(sk1, FTransfrm);
sk2 := Polar2Cartesian(dRad, 300); //Azimuth 300
img2 := User2Pixel(sk2, FTransfrm);
Canvas.MoveTo(img1.X, img1.y);
Canvas.LineTo(img2.X, img2.Y);

//Azimuth line from 150 degree to 330 degree.
sk1 := Polar2Cartesian(dRad, 150); //Azimuth 150
img1 := User2Pixel(sk1, FTransfrm);
sk2 := Polar2Cartesian(dRad, 330); //Azimuth 330
img2 := User2Pixel(sk2, FTransfrm);
Canvas.MoveTo(img1.X, img1.y);
Canvas.LineTo(img2.X, img2.Y);
for i := Low(SkyplotBackground) to High(SkyplotBackground) do
begin
try
with SkyplotBackground[i] do
begin
fnt := TFont.Create;
fnt.Name := FaceName;
fnt.Style := fnt.Style + [Weight];
fnt.Color := Color;
fnt.Height := Height;;
Canvas.Font := fnt;
sk1 := Polar2Cartesian(dRad, dAng);
DrawRotatedText(Canvas, Text, sk1, RotationAngle, HozAlignment, VerAlignment);
dAng := dAng + 30;
end;
finally
fnt.Free;
end;
end;
end;
end;

function TForm1.User2Pixel(sp : TPoint; tsf : TTransformPara) : TPoint;
var
dQ, dS : double;
dY, dX : double;
begin
dS := tsf.ScaleX;
dQ := DEGREETORADIANS * tsf.RotationAngle;
dY := -1 * (dS * sp.X * Sin(dQ) + dS * sp.Y * Cos(dQ)) + tsf.TY1;
dX := dS * sp.X * Cos(dQ) - dS * sp.Y * Sin(dQ) + tsf.TX1;
result.X := trunc(dX);
result.Y := trunc(dY);
end;

function TForm1.Polar2Cartesian(Radius : double; Azimuth : double) : TPoint;
var
x, y : double;
begin
x := Sin(PI / 180 * Azimuth) * Radius;
y := Cos(PI / 180 * Azimuth) * Radius;
result.X := trunc(x);
result.Y := trunc(y);
end;

function TForm1.SetTransformationPara(Tx, Ty, Scale, RotatedAng : double) : TTransformPara;
begin
with result do
begin
TX1 := Tx;//(Width - 2 * FMargin) / 2.0 + FMargin;
TY1 := Ty;//(Height - 2 * FMargin) / 2.0 + FMargin;
ScaleX := Scale;
RotationAngle := RotatedAng;
end;
end;

function TForm1.DrawRotatedText(cv : TCanvas; Txt : string; InsertPt : TPoint;
RotateAngle : double; HozAlign : THozAlignment;
VerAlign : TVerAlignment): boolean;
var
dRad : double; //Rotation angle in radian mode.
dtsx, dtsy : double;
dshfx, dshfy : double; //Shift x, Shift y to align text.
dtx, dty : double; //Translation x, Translation Y.
dxp, dyp : double;
dnewx, dnewy : double;
dtang : double; //rotation text angle to lforientation.
cnew : TPoint; //user coordinates (cartesian coordinates).
img : TPoint; //pixel coordinates.
orient : longint;//property of ratation text (counter-clockwise x 10).
txts : TSize;
begin
//We need double type for math computation.
dinx := InsertPt.X; //Insertion point (x) of original text.
diny := InsertPt.y; //Insertion point (y) of original text.
txts := cv.TextExtent(txt); //Text size of rotation text.
dtsx := txts.cx; //Convert text size from integer to double.
dtsy := txts.cy;

//Manage shift cooridantes to the user alignment.
//First check the horizontal alignment.
case HozAlign of
//default of Canvas.Textout is horizontal left align.
haLeft : dshfx := 0;
//Right alignment shift insertpoint point to left direction with the length of text size.
haRight : dshfx := -1 * dtsx;
//Center alignment shift insertpoint point to left direction with the half length of text size.
haCenter : dshfx := -1 * dtsx / 2.0;
end;
//Secord check the vertical alignment.
case VerAlign of
//default of Canvas.Textout is vertical top align.
vaTop : dshfy := 0;
//Bottom alignment shift insertpoint point to up direction with the height of text size.
vaBottom : dshfy := dtsy;
//Center alignment shift insertpoint point to up direction with the half height of text size.
VaCenter : dshfy := dtsy / 2.0;
end;

dxp := dshfx;
dyp := dshfy;

//Need the angle in azimuth term. Clockwise angle from North(Y-Axis)
dRad := (90 - Rotateangle);
if (dRad < 0) then
dRad := 360 + dRad
else if (dRad > 540) then
dRad := dRad - 540
else if (dRad > 360) then
dRad := dRad - 360;

dRad := dRad * DEGREETORADIANS;
//Calculate the new insert point for new alignment by Multiply the matrix.
dnewx := dxp * cos(dRad) - dyp * sin(dRad) + dtx;
dnewy := dxp * sin(dRad) + dyp * cos(dRad) + dty;
cnew.X := trunc(dnewx);
cnew.y := trunc(dnewy);
//From X,Y origin at the center of image convert to pixel coordinates.
img := User2Pixel(cnew, FTransfrm);

//RotateAngle is counter-closewise angle convert to clockwise angle.
dtang := 90 - RotateAngle;
//if rotation is minus angle, change to plus angle.
if (dtang < 0) then dtang := 360 + dtang;
orient := trunc(dtang * 10);
cv.Font.Orientation := orient;
cv.TextOut(img.x, img.y, Txt);
end;

//Draw circle
function TForm1.DrawCircle(cv : TCanvas; Center : TPoint; cRadius : integer) : boolean;
var
StartPt, EndPt : TPoint;
dStartRadians : double; // Start angle in radians
dEndRadians : double; // End angle in radians
dDep,dLat : double;
r : TRect;
begin
dStartRadians := 0 * DEGREETORADIANS;
dEndRadians := 360 * DEGREETORADIANS;
//Calculate a point on the starting radial line via
// polar -> cartesian conversion
dDep := cRadius * cos(dStartRadians);
dLat := cRadius * sin(dStartRadians);
StartPt.X := Center.X + trunc(dDep);
StartPt.Y := Center.Y - trunc(dLat);

// Calculate a point on the ending radial line via
// polar -> cartesian conversion
dDep := cRadius * cos(dEndRadians);
dLat := cRadius * sin(dEndRadians);
EndPt.X := Center.X + trunc(dDep);
EndPt.Y := Center.Y - trunc(dLat);

r := Rect(Center.x-cRadius,Center.Y-cRadius,Center.x+cRadius,Center.Y+cRadius);
// Draw the circle
cv.Ellipse(r);
end;

initialization
{$I unit1.lrs}

end.
//=========================================================================================
  • ผมจะอธิบายบางอย่างที่สำคัญ ผม declare type

TTransformPara = record
TX1 : double; //Translation X1
TY1 : double; //Translation Y1
RotationAngle : double;
ScaleX : double;
end;

  • เป็น record type ง่ายๆ มีฟิลด์ TX1, TY1 เป็นค่าที่เรียกว่า Translation เวลาเราย้ายแกน X,Y ไปยังแกนใหม่ ระยะที่เลื่อนไปตามแกน X เรียกว่า Translation X ส่วนระยะที่เลื่อนไปตามแกน Y คือ Translation Y บางโอกาสแกนที่ย้ายไปใหม่อาจจะต้องหมุนด้วย มุมที่แกนใหม่กับแกนเก่าเรียกว่า Rotation angle ฟิลด์ RotationAngle คือมุมที่ว่านั้นเอง และมากไปกว่านั้นแกนใหม่อาจจะยืดหรือหดไม่เท่ากับแกนเก่า ฟิลด์ ScaleX คือสเกลที่มารองรับดังกล่าว
  • ในการจัดรูปแบบตัวหนังสือ (Text alignment) ในแนวราบก็มีจัดชิดซ้าย กลาง และชิดขวา ส่วนในแนวดิ่งก็มี บน กลางและล่าง ผมตั้ง enumerate type ดังโค๊ดข้างล่าง

//Text alignment
THozAlignment = (haLeft, haRight, haCenter);
TVerAlignment = (vaTop, vaBottom, vaCenter);

  • ส่วน TRotationText เป็น type ที่ตั้งขึ้นมาเพื่อเก็บชุดของตัวหนังสือที่จะนำมาหมุน ชุดของตัวหนังสือจะ declare เป็น constant คือ SkyplotBackground เป็น Array ขนาด 12 members  เพื่อให้ใช้ for loop เขียนตัวหนังสือแบบหมุนเอียงได้ง่ายๆ
  • มาดูที่ TForm1 ผมตั้งตัวแปรแบบ Private มา 2 ตัวคือ FSkyHalf และ FSkyMargin เพื่อเป็นตัวช่วยเรื่องขนาดพื้นที่ที่จะวาดวงกลมและเขียนตัวหนังสือ ส่วน FSkyMargin เป็นขนาดกั้นซ้าย ขวา บน และล่างไม่ให้ตัวหนังสือที่จะเขียนตกขอบ PaintBox
  • ฟังก์ชั่นที่จะมาเกี่ยวข้องในการย้ายหมุนแกนคือ User2Pixel ซึ่งพารามิเตอร์จะส่งไปให้ก็คือ Transformation parameter ที่ผมกล่าวมาแล้ว ผมใส่ให้เป็นฟังก์ชั่นในส่วน Private ด้วย
function TForm1.User2Pixel(sp : TPoint; tsf : TTransformPara) : TPoint;
var
dQ, dS : double;
dY, dX : double;
begin
dS := tsf.ScaleX;
dQ := DEGREETORADIANS * tsf.RotationAngle;
dY := -1 * (dS * sp.X * Sin(dQ) + dS * sp.Y * Cos(dQ)) + tsf.TY1;
dX := dS * sp.X * Cos(dQ) - dS * sp.Y * Sin(dQ) + tsf.TX1;
result.X := trunc(dX);
result.Y := trunc(dY);
end;
  • ฟังก์ชั่น User2Pixel ข้างบน เราจะส่งพารามิเตอร์ไปให้ตัวแรกคือ TPoint เป็นค่าพิกัดแกนเดิมในที่นี้คือแกนกลางรูปของ PaintBox แกนใหม่เป็นค่าพิกัดระบบ pixel ของรูปที่มีจุด origin (0,0) อยู่ที่มุมบนซ้าย แกน X ชี้ไปด้านขวามือ แกน Y ชี้ลงด้านล่าง เพื่อจะได้นำค่าพิกัดที่ฟังก์ชั่นส่งกลับไปเขียนด้วยเมธอดของ Canvas เช่น Textout, Line, Arc,…
  • บนระบบพิกัดกลางรูป PaintBox แกน Y ชี้ขึ้นแกน X ชี้ไปด้านขวา ผมจะอ้างอิงระบบพิกัดนี้ ค่าพิกัด origin (0,0) จะอยู่ที่กึ่งกลางรูป มุมที่ใช้ในการหมุนตัวหนังสือจะวัดจาก แกน X หมุนทวนเข็มนาฬิกาไปหาแกน Y
  • แต่ในการคำนวณด้านวิชาสำรวจ จะไม่ใช้มุมที่วัดจากแกน X ทวนเข็ม แต่จะใช้มุมอะซิมัท (azimuth) ที่วัดจากแกน Y หรือทิศเหนือวัดตามเข็มลงมาหาแกน X บางฟังก์ชั่นจึงมีการแปลงมุมที่วัดจากแกน X ทวนเข็มนาฬิกาไปเป็นมุมที่วัดจากแกน Y ตามเข็มนาฬิกา
  • ส่วนฟังก์ชั่น Polar2Cartesian จะเป็นการแปลงพิกัดจากระบบพิกัดวงกลม (Radius, Angle) ไปเป็นระบบพิกัดกริด (X,Y) เนื่องจากผมต้องการวาดท้องฟ้าเพื่อแสดงสัญลักษณ์ GPS จะง่ายถ้าใช้ระบบพิกัดวงกลม ที่ผมต้องใช้พิกัดนี้เนื่องจากการอ่านข้อมูลของ GPS ที่เรียกว่า NMEA จะได้ตำแหน่งของ GPS ที่อยู่ในรูป Azimuth และ รัศมี จึงจำเป็นต้องใช้ระบบพิกัดนี้ ผมจะแปลงระบบพิกัดวงกลมไปเป็นพิกัดกริด (X,Y) แล้วค่อยแปลงไปเป็นระบบพิกัดรูป (pixel) เพื่อจะได้ใช้ Canvas ในการวาดทั้งหลาย สรุปก็คือ Polar2Cartesian => User2Pixel
function TForm1.Polar2Cartesian(Radius : double; Azimuth : double) : TPoint;
var
x, y : double;
begin
x := Sin(PI / 180 * Azimuth) * Radius;
y := Cos(PI / 180 * Azimuth) * Radius;
result.X := trunc(x);
result.Y := trunc(y);
end;
  • มาดูกันที่ TForm1.FromCreate อันเป็นจุดเริ่มของโปรแกรมทดสอบนี้ ตั้งค่าพื้นที่ในการวาดไม่ให้ล้นกรอบรูป PaintBox ด้วยตัวแปร FSkyMargin ส่วน FSkyHalf คือครึ่งหนึ่งของขนาดความกว้างพื้นที่หักขนาดขอบ (FSkyMargin) จากนั้นตั้งค่า Transformation ระหว่างพิกัดของรูป (pixel) และพิกัดกริด X,Y ที่จะย้ายไปคำนวณที่กึ่งกลางรูป PaintBox
procedure TForm1.FormCreate(Sender: TObject);
var
dtx, dty, dScale, dAng : double;
begin
//Left, right, top, bottom margin of the area to draw the sky.
FSkyMargin := 30;
FSkyHalf := (PaintBox1.Width - 2 * FSkyMargin) / 2;

//Translate or move from image system to center of image (TPaintBox).
dtx := FSkyHalf + FSkyMargin;
dty := FSkyHalf + FSkyMargin;
dscale := 1.0;
dAng := 0.0;
//Set transformation by Calling SetTransformationPara.
FTransfrm := SetTransformationPara(dtx, dty, dscale, dAng);
end;
  • การวาดวงกลมท้องฟ้าและตัวหนังสือวางไว้ที่อีเวนท์ OnPaint ของ PaintBox ขอให้ดู Code ของ Unit1 ด้านบนค่อนข้างยาว ผมจะไม่นำแสดงใหม่ เริ่มจากการระบายสีรูปสี่เหลี่ยมของ PaintBox ด้วยการตั้งค่าแปรง สี และสไตล์การวาด และไม่ลืมตั้งค่าแปรง เป็น bsClear เพื่อการวาดวงกลมภายหลังจะไม่ถูกระบายสี
  • แล้ววงกลมท้องฟ้าที่เส้นขอบฟ้า Elevation = 0 ต่อด้วยวงกลมที่ค่าระดับ Elevation = 30 องศา (มุมนี้วัดจากแนวราบที่เส้นขอบฟ้าขึ้นไปยังเหนือศรีษะจะเท่ากับ 90 องศา) แล้ววาดวงกลมค่าระดับ 60 องศา เป็นอันเสร็จ
  • ผมเขียนฟังก์ชั่น DrawCircle ขึ้นมาใหม่ เพื่อให้ง่ายต่อการวาดวงกลมและที่สำคัญคือเป็นธรรมชาติ ต้องการพารามิเตอร์ แค่ค่าพิกัดจุดศูยน์กลางวงกลมและระยะรัศมี ถ้ายังจำการได้การเขียนวงกลมเมื่อสมัยเรียนประถม เรามีวงเวียนและไม้บรรทัด กางวงเวียนวัดรัศมีจากไม้บรรทัด จุดขาของวงเวียนแล้วก็หมุนลากเส้นเป็นอันจบ แต่ผมไม่เข้าใจว่าฟังก์ชั่นการเขียนวงกลมใน Win API จึงดูยุ่งยากคือจะต้องใช้ Canvas.Arc ที่รับพารามิเตอร์เป็นกรอบสี่เหลี่ยม มุมเริ่มต้น และมุมสิ้นสุด  มุมเริ่มต้นเท่ากับศูนย์และมุมสิ้นสุดคือ 360 องศา (หรือเท่ากับ 2*PI เรเดียน) การจะวาดวงกลมในรูปแบบ Canvas.Arc ถ้าเป็นเด็กประถม เราจะต้องจุดมุมสี่เหลี่ยมแล้วลากเส้นทแยงเพื่อหาจุดตัดก็คือจุดศูนย์กลางแล้วค่อยกางวงเวียนวาดวงกลม มันจึงดูพิกล ผมจำได้เคยอ่านหนังสือ Hard Core Visual Basic ที่แต่งโดย Bruce Mckinney ท่านเรียกฟังก์ชั่นพรรค์นี้ว่า function from hell (FFH)
  • ต่อไปเป็นการลากเส้นตรงที่เป็นเส้นแสดงอะซิมัท โดยการแปลงค่าพิกัดของเส้นแสดงอะซิมัทที่อยู่ในรูป Polar ไปเป็นระบบกริด (Cartesian)
  • สุดท้าย Array of constant ที่ผม assign ไว้แล้วใช้ for loop มาอ่านแล้วเขียนตัวหนังสือแบบหมุนเอียงตามทิศทางของเส้นอะซิมัท ใน Array นี้จะมีชื่อฟอนต์ ขนาดตัวอักษร การจัดวางตัวอักษร มุมที่ใช้หมุน เรียกใช้ DrawRotatedText ซึ่งเป็นตัวเอกในตอนนี้ ภายใน DrawRotatedText ผมใช้วิธีการจัดวางตัวหนังสือและมุมที่ใช้หมุนตัวอักษร มาคำนวณหา insert point ของตัวหนังสือใหม่ ใช้วิธีคำนวณจากคณิตศาสตร์พื้นฐานที่ผมได้กล่าวไปแล้วในตอนต้นๆบทความ สุดท้ายก็ใช้ Canvas.TextOut วาดตัวหนังสือออกมา
  • กด F9 เพื่อ Run โปรแกรมจะได้ผลลัพธ์ ดังรูปข้างล่าง (ใช้ Compiz fusion บน Ubuntu ด้วย)

the reesult of how to draw rotated text.

  • ต้องขอบอกอีกนิดหนึ่งว่า Lazarus ที่ผมใช้งานอยู่ใช้เป็น Freepascal 2.5.1 และ Lazarus 0.9.29 beta ต้องเอาใจช่วย ผู้พัฒนา Freepascal และ Lazarus ให้โครงการนี้ได้เดินไปจนถึงจุดที่ความเสถียรใกล้เคียง กับ Delphi V.7 เป็น Opensource ตัวหนึ่งที่น่าสนับสนุนมาก

Download sourcecode

  • sourcecode ของตอนนี้สามารถ download ได้ที่นี่ RotatedTextProj.zip

การเขียน Image ของ Harddisk ด้วยแผ่น System Rescue Live CD (ตอนที่ 1)

เกริ่นนำ

  • เป็นที่ทราบกันดีว่าการติดตั้ง Windows หรือ Linux เป็นอะไรที่น่าเบื่อมากแค่ไหน ไหนจะต้องติดตั้งโปรแกรมที่ใช้งาน บางที่เป็นวันเลยก็มี แต่ถ้าเราเขียน image ของ harddisk ได้จะทุ่นเวลาไปมาก เพราะตอนนำ image มาเขียนกลับลง harddisk จะใช้เวลาแค่ไม่เกินชั่วโมง
  • เป็น Linux Live CD ที่ผมชอบมาก ใช้บ่อยตอนเขียน image ของ harddisk เลือก partition ที่ต้องการได้ ต้องสารภาพจริงๆว่าไม่เคยใช้โปรแกรมหรือ tools อื่นๆเช่น Norton ghost เลยก็ไม่รู้ความยากง่ายต่างกันแค่ไหน วิธีการใช้ก็ง่าย แค่คำสั่ง command line พื้นฐานไม่กี่บรรทัด
  • แต่ที่สำคัญคือเป็นของฟรี

สิ่งที่ต้องเตรียม

  • แผ่น CD -R หรือ USB Flash drive ขนาดมากกว่า 1 GB สำหรับเขียน System Rescue Live CD
  • ถ้าเป็นไปได้แนะนะให้ใช้ External harddisk สำหรับเขียน Image ของ Harddisk ตอนนี้เห็นคนใช้กันมากส่วนใหญ่ ก๊อปปี้หนัง เพลง ข้อมูลกันไว้ได้มาก หรือถ้าแย่ที่สุดก็เขียนลงใน Harddisk ตัวเดียวที่จะอ่าน Image มาเซฟไว้นั่นแหละ ภาษาวินโดส์ อาจจะพูดว่า อ่าน Image ของ Drive C (Windows) มาเก็บไว้บน Drive D (ไดรฟ์ข้อมูล) อะไรประมาณนี้ แต่ใน Linux จะไม่มองเป็น Drive เรียงตัวอักษรภาษาอังกฤษจาก A, B, C, … จะอย่างไรค่อยว่ากัน
  • Partition Harddisk ที่ต้องการเขียน Image ถ้าเป็น Windows ใช้ระบบไฟล์เป็น NTFS หรือไม่ถ้าเก่าหน่อยก็เป็น Fat32 ส่วน Linux ถ้าอาจจะเป็น ext3 หรือ ext4 ผมใช้ Ubuntu 9.04 อยู่แต่ใช้ ext3 เพราะตอนลงเที่ยวแรกใช้ ext4 ปรากฎว่า PCLinuxOS ที่เคยเข้าไปอ่านไฟล์ของ Ubuntu ได้ตรง file systems หรือแม้กระทั่ง partition Home (ที่ผมแยกให้อยู่ต่าง Partition) ก็ฟอร์แม็ตเป็น ext4 เรียบร้อยเลย PCLinuxOS ที่ยังใช้ ext3 เข้าไม่ได้แบบสนิท มาเจ็บอีกครั้งตอนเขียน image ของ Harddisk เพราะเพื่อนรัก PartImage (ตัวนี้จะเป็นตัวเอกที่จะได้กล่าวต่อไปคือเป็นตัวเขียน Image ของ Harddisk) ไม่รู้จัก ext4 ซะงั้น หันไปใช้ FSAchiever ที่อยู่ในแผ่นเดียวกันก็คือ System Rescue Live CD กลับไม่เวิร์คมาตายตอนอ่าน Image ที่เขียนจาก FSArchiver ตัวเดียวกันนี่แหละ ก็เลยไม่เคยลองอีกเลย แต่อย่างไรก็ตามถ้า Partimage หยุด suppoert แค่ ext3 อนาคตต้องหันไปคบกับ FSArchiver อย่างหลีกเลี่ยงไม่พ้น

ดาวน์โหลดและเบิร์น

  • ไปที่ website http://www.sysresccd.org/Download จะพบ link ให้ Download เวอร์ชั่นล่าสุดตอนที่เขียนนี้อยู่ที่ 1.2.3 เลือกดาวน์โหลดบน plat form  “i486/amd64” ขนาดไฟล์ประมาณ 236 MB ก็ไม่ถือว่าใหญ่มากนักในยุค hispeed internet
  • เมื่อ Download ได้ไฟล์ ISO มาแล้วจัดการเบิร์นลงแผ่น CD เมื่อเสร็จแล้วพร้อมจะนำไป Bootเครื่องคอมพิวเตอร์เราเป็น Live CD
  • ทางเลือกอื่นๆถ้าไม่ต้องการเบิร์นลงแผ่น CD ถ้าต้องการ Boot ด้วย USB Flash drive ผมแนะนำให้ไป Download “UnetBootin” เป็นของฟรีเช่นเดียวกันที่ http://unetbootin.sourceforge.net/ ทีสำคัญคือมีทั้งเวอร์ชั่นเป็น Windows และ Linux ถ้าเป็นวินโดส์ ก็ไม่ต้องติดตั้ง double click ไฟล์ที่ดาวน์โหลดมาก็รันได้เลย และที่สำคัญคือฟรี
  • ถ้าเป็น Ubuntu ใช้คำสั่ง

$sudo ./unetbootin-linux-356 (unetbootin-linux-356 คือไฟล์ที่ดาวน์โหลดมา)

Select ISO image file for UNetbootin
Select ISO image file for UNetbootin
  • ในwebsite ของ UNetbootin จะมีภาพ snapshot screen แสดงวิธีใช้ทำให้เข้าใจได้ง่ายๆ
  • ในยุครักษ์สิ่งแวดล้อม การประหยัดแผ่น CD ก็ถือเป็นเรื่องดี เขียน image iso ลง USB Flash drive เมื่อไม่ใช้ boot ก็เอาไปฟอร์แมท เขียนข้อมูลอื่นได้ตามปกติ ต้องการ boot เมื่อไหร่ก็ค่อยมาใช้โปรแกรม UnetBootin เขียน image iso เป็นแผ่น boot อีกครั้ง
  • การตั้ง BIOS ปัจจุบันเครื่องคอมพิวเตอร์ไม่ว่า PC หรือ Notebook ก็สามารถตั้ง Bios ให้ Boot จาก CD rom หรือ USB Flash drive ได้ ถ้าให้ดีตั้งให้กดคีย์เช่น F12 เพื่อเลือกจะ Boot จาก Harddisk, CD rom หรือ USB Flash drive ถ้าทำบู๊ตจาก UNetbootin ด้วย USB Flash drive โปรแกรม UNetbootin จะสร้างเมนูให้หลายๆอย่าง ส่วนใหญ่ผมจะเลือก VMLinuz2 บางเครื่องที่พบจะเลือกบรรทัด Vesa แต่ถ้าเป็น CD เข้าไปเลยไม่มีถามอะไร
  • ทำการ Boot จาก USB Flash drive หรือ CD เครื่องจะทำการบูต ครั้งแรกจะถาม layout ของ คีย์บอร์ด เลือกกด Enter เป็น default คือภาษาอังกฤษ  สุดท้ายจะมาหยุดที่ command line ให้พิมพ์คำสั่งเพื่อเข้าโหมดกราฟฟิค

root@sysrescd /root % startx

เข้าสู่โหมดกราฟฟิค

System Rescue Live CD

  • ดูเรียบง่ายมีเมนูบาร์คล้ายๆ วินโดส์ มีเมนู Start แต่อย่างไรก็ตามกำแพงขวางกั้นสำหรับคนไม่คุ้นกับ Linux เลยคือระบบไฟล์ของ Linux คำถามที่พบของมือใหม่คือ Drive C หรือ Drive D ของผมอยู่ที่ไหน ถ้าเป็น Ubuntu หรือ Linux Distro อื่นๆ จะ mount มาให้อัตโนมัติที่นี้เป็นเรื่องง่าย แค่ดับเบิ้ลคลิกก็ใช้ได้เลย แต่ใน System Rescue Live CD  นี้จะไม่ mount มาให้เหมือนกับ Linux ยุคก่อนคือต้อง Mount ด้วยตัวเอง
  • ขั้นตอนแรกคือต้องทราบว่า Drive เราคือ Harddisk ก็เป็นอุปกรณ์ตัวหนึ่ง Linux จะมองเป็น device เรียกย่อๆว่า dev อุปกรณ์ที่ Linux พบหรือสนับสนุนจะอยู่ที่ Directory ของระบบ อยู่ที่ไดเรคทอรี /dev ถ้าใช้คำสั่ง $ ls -l /dev จะเห็นอุปกรณ์มากมายที่ Linux สนับสนุน เช่นถ้าเป็น Harddisk รุ่นที่เป็น PATA (ต่อด้วยสายแพร์สมัยก่อน) จะเห็น /dev/hda1, /dev/hda2 แต่ถ้าเป็น Harddisk SATA จะเห็น /dev/sda1, /dev/sda2 หรือ /dev/sdb1, /dev/sdb2 ของ Linux Harddisk จะไม่เรียงกันแบบ Drive A, Drive B,…. Drive Z แบบวินโดส์ การตั้งชื่อแบบ Linux หรือ Unix ผมว่าคิดได้สุดยอด Harddisk ลูกแรกอาจจะเป็น sda ถ้ามีการแบ่ง Partition ไป 8 Partition ก็จะมีชื่อ dev เป็น sda1, sda2, sda3, …. จนถึง sda8 แต่ถ้าเป็นวินโดส์ละลองคิดดู Drive ต่อจาก Drive Z  จะเป็นอะไร
  • ถ้าใช้คำสั่ง  $ df ก็จะเห็นแต่ drive ที่ mount แล้ว ผมเองสะดวกที่จะใช้ GParted ตัวนี้ใช้ในการจัดการ Partition ทั้งแบ่ง เพิ่มขนาด ลบ รวม Partition ทำได้ ถึงแม้จะเรียบง่ายแต่ที่ผมใช้มาหลายปีก็ไม่เคยงอแงเลย ที่จริงจุดประสงค์เราต้องการ list ดู partition ของ harddisk ที่เครื่องคอมพิวเตอร์เราต่ออยู่เท่านั้น คลิกที่เมนู Start > System > GParted หรือพิมพ์คำสั่งที่เทอร์มินอลดังนี้

root@sysrescd /root % gparted

gparted on system rescue live cd

  • ถ้าดูรูปด้านบนเป็นภาพของโปรแกรม GParted (GNome Parted) ให้สังเกตุมุมขวาบน linux จะแสดงอุปกรณ์ /dev/sda (298.09 GB) นี่คือ harddisk ของผมบนเครื่องโน๊ตบุ๊ค แบ่ง partition ไว้ 8 partition
  1. /dev/sda1 ฟอร์แมตเป็น ntfs เป็น partition ของวินโดส์เอ็กซพี
  2. /dev/sda2 ฟอร์แมตเป็น ext3 เป็น partition ของ Ubuntu 9.04
  3. /dev/sda3 ฟอร์แมตเป็น ext3 เป็น partition ของ PCLinux 2009 (distro ที่ผมรักอีกตัวหนึ่ง) ส่วน home partition ไม่ได้สร้างขึ้นมาเป็นพิเศษใช้รวมอยู่ใน partition นี้ด้วยกัน
  4. /dev/sda4 เป็น extended partition  ซึ่งข้างใน  partition นี้จะบรรจุ logical partition ดังต่อไปนี้
  5. /dev/sda5 ฟอร์แมตเป็น ext3 เป็น partition home ของ Ubuntu 9.04 ถ้าเปิด Ubuntu จะเมาท์เป็น /home/prajuab ตามชื่อของผม
  6. /dev/sda6 ฟอร์แมตเป็น ntfs เป็น partition ที่ไว้เก็บข้อมูลสำหรับวินโดส์ แต่ถ้าใช้ linux อย่าง Ubuntu ก็ใช้งานได้ทั้งอ่านและเขียน แต่วินโดส์จะมองไม่เห็น drive ของ linux เท่านั้น
  7. /dev/sda7 ฟอร์แมตเป็น ntfs เป็น partition ที่ไว้เก็บข้อมูลสำหรับวินโดส์เช่น /dev/sda6
  8. /dev/sda8 ขนาดประมาณ 2 GB ตั้งให้เป็น linux-swap สำหรับ linux ใช้เป็นพื้นที่สว๊อป
  • ผมบู๊ต System Rescue Live CD นี้ด้วย USB Flash drive ขนาดประมาณ 2 GB แล้วอยู่ไหนละ วิธีการคือคลิกที่รูป harddisk ตรงมุมบนขวาเลือก /dev/sdb1 ลองดูภาพข้างล่าง

Gparted แสดง USB Flash drive ที่ใช้บู๊ต System Rescue Live CD

  • มี partition เดียวคือ /dev/sdb1 มีฟอร์แมตเป็น Fat32
  • ที่ผมกล่าวอ้างมาก่อนคือถ้าเขียน image ลง external harddisk แล้ว drive อยู่ตรงไหน ลองตรวจดูคลิกที่เดิมมุมขวาบนที่เดิม

GParted แสดง External Harddisk ที่ต่อผ่านพอร์ท USB สำหรับเขียน Image

  • มี 2 partition คือ
    1. /dev/sdc1 ฟอร์แมตเป็น NTFS มีชื่อวอลุ่มคือ PJ146GBData
    2. /dev/sdc2 ฟอร์แมตเป็น NTFS มีชื่อวอลุ่มคือ PJ86GBOSImages พาร์ทิชั่นนี้แหละที่ผมจะใช้เขียนอ่าน image ของ harddisk
  • จะเห็นว่าใช้โปรแกรม GParted เพื่อตรวจดูว่า harddisk ตัวไหน และพาร์ทิชั่นไหน ที่จะใช้อ่าน image และจะไปเก็บที่พาร์ทิชั่นไหน ตอนนี้โจทย์ก็คือต้องการเขียน image ของวินโดส์เอ็กซพี (/dev/sda1) ไปเก็บไว้ที่ external harddisk (/dev/sdc2)

การเมาท์พาร์ทิชั่นของฮาร์ดดิสค์

  • ถ้าเข้าใจเรื่อง device ฮาร์ดดิสค์ ที่กล่าวมาแล้วเรื่องเมาท์ด้วยคำสั่ง mount หรือ ntfs-3g ก็เป็นเรื่องไม่ยากแล้ว ในไฟล์ระบบของ linux จะมี directory ที่ใช้สำหรับเมาท์โดยเฉพาะคือ /mnt ความเข้าใจง่ายๆสำหรับการเมาท์ คือเอา device ที่เป็นฮาร์ดดิสค์ ไปเชื่อมไปต่อกับ directory ที่เตรียมไว้ให้ linux ได้เห็นและใช้อุปกรณ์ตัวนั้น
  • สร้าง sub directory ไว้ภายใต้ directory mount ใช้คำสั่ง

root@sysrescd /root % cd /mnt

root@sysrescd /mnt % mkdir pjdiskimages

root@sysrescd /mnt % ls -l

  • จะเห็น directory pjimages ปรากฎอยู่ใต้ directory /mnt พร้อมที่จะเอา /dev/sdc2 มาเมาท์ที่นี่ มีข้อแม้อยู่นิดเดียวว่าถ้าโครงสร้างของพาร์ทิชั่นเป็น NTFS ต้องเมาท์ด้วยคำสั่ง ntfs-3g ดังนี้ ก่อนจะเมาท์ directory /mnt/pjdiskimages จะว่างเปล่า

root@sysrescd /mnt % ntfs-3g /dev/sdc2 /mnt/pjdiskimages

Mount external harddisk.

  • ตรวจสอบว่าพาร์ทิชั่น sdc2 เมาท์เข้ามาแล้วมีไฟล์และไดเรคทอรี ตรงที่เรารู้หรือปล่าว ด้วยโปรแกรม Midnight Commander หรือปล่าวคลิกที่เมนู Start > Misc > Midnight Commander ซึ่งคล้ายๆกับ Norton commander ในสมัยก่อน ไปที่ /mnt/pjdiskimages จะเห็นไฟล์และไดเรคทอรี ที่ผมไว้เก็บ image ของฮาร์ดดิสค์

Midnight commander

  • เมื่อเมาท์พาร์ทิชั่นฮาร์ดดิสค์เป็นที่เรียบร้อยแล้ว เราก็พร้อมจะเขียน image ลงไปยัง external harddisk ที่เราต้องการ ต่อไปโปรแกรมที่จะมาอ่าน image ของพาร์ทิชั่นฮาร์ดดิสค์ และเขียนไปยัง external harddisk คือ PartImage คลิกที่เมนู Start > System > PartImage หรือใช้คำสั่ง command line ดังนี้

root@sysrescd /mnt % partimage

  • จะเห็นโปรแกรม partimage ดังรูปข้างล่าง จะเห็นพาร์ทิชั่นของ Windows XP ที่ต้องการอ่าน (Partition to Save/Restore) คือ /dev/sda1 และพาร์ทิชั่นที่จะเขียน (Image file to create/use) คือ /mnt/pjdiskimages/win_images/Acer4920G/win_im.gz

การเลือกพาร์ทิชั่นที่จะอ่านและปลายทางที่จะเขียน image

  • จากรูปด้านบน ตรง Action to be done: ให้เลื่อนไปหาโดยการกด Tab ที่คีย์บอร์ด แล้วเลือก (*) Save partition into a new image file โดยการเคาะ space bar หนึ่งครั้งเพื่อเลือก เมื่อป้อนทุกอย่างเสร็จดังรูปแล้ว กด F5 เพื่อไปตั้งค่าที่หน้าต่อไป

การเลือกรูปแบบการบีบอัด

  • เลือก (*) Gzip จะบีบอัดได้ประมาณครึ่งหนึ่งของขนาดจริง แต่ถ้าเลือก Bzip2 จะบีบได้มากแต่ช้ามากๆ ส่วนพารามิเตอร์อื่นๆ เลือกไว้ตาม default กด F5 เพื่อไปหน้าต่อไป

เขียน comment เพื่อเตือนความทรงจำ

  • จากรูปด้านบนเขียนอะไรก็ได้เพื่อเตือนความทรงจำ ผมขอแหกกฎหน่อยจะเขียน password ของ administrator ของวินโดส์ไว้ เพราะเคยมาแล้วเขียนไว้นานแล้วผมก็เปลี่ยน password วินโดส์จนจำของเก่าไม่ได้เมื่อนำ image มา restore ลงฮาร์ดดิสค์ ปรากฎว่าเข้าวินโดส์ไม่ได้ เมื่อเขียนเตือนความทรงจำแล้ว ที่ปุ่ม OK กด Enter เพื่อไปหน้าต่อไป

ยืนยันเพื่อเขียนไฟล์ image ทับไฟล์เก่า

  • จากรูปด้านบนผมตั้งชื่อไฟล์ที่จะเขียนเหมือนไฟล์เดิมที่อยู่ใน external harddisk โปรแกรมถามเพื่อยืนยันให้เปลี่ยนชื่อหรือทับไฟล์เดิม เลือก Overwrite เพื่อเขียนทับ

โปรแกรม PartImage สรุปก่อนจะเริ่มเขียน image

  • จากรูปด้านบนกด Enter เพื่อไปหน้าต่อไป

NTFS Informations

  • จากรูปด้านบนโปรแกรม PartImage จะสรุปข้อมูลของพาร์ทิชั่นที่เราต้องการอ่านและเขียน กด Enter เพื่อไปหน้าต่อไป

PartImage เเริ่มขียน image ของพาร์ทิชั่นฮาร์ดดิสค์

  • รูปด้านบนโปรแกรม PartImage เริ่มเขียน image ไปยัง external harddisk (dev/sdc2)

โปรแกรม PartImage เขียน Image เสร็จ

  • และนาทีที่รอคอยก็มาถึง รูปด้านบนโปรแกรม PartImage แสดงข้อความว่าเขียน image เสร็จแล้วสรุปว่าใช้เวลาไปเท่าไหร่ ความเร็วเฉลี่ยที่ใช้การอ่านและเขียนรวมทั้งขนาดของ image
  • ก็เป็นอันว่าเสร็จสิ้นแล้วสำหรับการเขียน image ของพาร์ทิชั่นฮาร์ดดิสค์ ตอนต่อไป ตอนที่ 2 ผมจะเสนอการ Restore Image จาก External harddisk ที่เราเขียนไว้แล้ว มา Restore ลงบนพาร์ทิชั่นวินโดส์
  • ออกจาก System Rescue Live CD ด้วยการใช้คำสั่งเพื่อบู๊ตระบบใหม่

root@sysrescd /mnt % shutdown -r down