วันพฤหัสบดีที่ 14 มีนาคม พ.ศ. 2556

ซิลิโคนติดซีพียู (Thermal Compound)

ซิลิโคน Thermal Compound คืออะไร..??

...ซิลิโคนคือ สารประกอบพวกThermal Compound หรือตัวนำความร้อนนี่เอง ทำหน้าที่เชื่อมประสาน
นำความร้อนจากซีพียูไปยังฮีทซิงค์เพื่อให้พื้นที่ผิว สัมผัสกันได้ดียิ่งขึ้น เพิ่มประสิทธิภาพการระบายความร้อนได้ดีขึ้น
เพราะหากไม่มีซิลิโคนคั่นระหว่างซีพียูและฮีทซิงค์ หากติดตั้งฮีทซิงค์มาไม่ดี หรือขาล็อกฮีทซิงค์ไม่แข็งแรงแล้ว
ความร้อนจะไม่ถ่ายเทไปยังฮีทซิงค์ได้เท่าที่ควรและทำให้ซีพียูร้อนมากขึ้น เกินไปจนซีพียูไหม้ได้


ทำไมต้องใช้ซิลิโคน...??

...หากเกิดช่องว่างระหว่าซีพียูและฮีทซิงค์ซีพียูร้อนจี๋ แต่ฮีทซิงค์กลับเย็นปกติ...อาจรู้สึกขัดๆกันนิดหน่อยเหมือนกันเพราะ
ตามหลักคือถ้าฮีทซิงค์ร้อนก็หมายถึงว่าฮีทซิงค์นั้นระบายความร้อนไม่ทันและ ไม่เหมาะกับความเร็วซีพียู หรือระบายความ
ร้อนได้ดีครับ ให้เข้าใจว่าถ้ามีความร้อนเกิดขึ้นที่ฮีทซิงค์ ก็คือ ฮีทซิงค์เริ่มทำงานได้ครับ แต่เราจะมาดูคือ ถ้าใช้งานแรกๆ
ฮีทซิงค์จะร้อนปกติ เกิดวันดีคืนดีฮีทซิงค์กลับเย็นลง แต่ซีพียูร้อนมากทราบจากเข้าดูอุณหภูมิที่ไบออส นั่นคือเกิดช่องว่างขึ้น
หมายถึงฮีทซิงค์ติดตั้งไม่แน่น ไม่แนบสนิท การทาซิลิโคนจะช่วยอุดช่องว่างหมดไป เพิ่มพื้นที่หน้าสัมผัสซีพียูกับฮีทซิงค์ให้
สัมผัสกันได้ดีขึ้นทำให้ช่วยนำ ความร้อนไปยังฮีทซิงค์ได้ดีขึ้น ยิ่งซีพียูรุ่นใหม่ๆมีความเร็วสูง พื้นที่ตัวแกนซีพียูหรือcore มี
ขนาดเล็กลง ความร้อนต่อหน่วยพื้นที่มีมากขึ้น การระบายความร้อนต้องดีตามด้วย ซีลิโคนหรือสารนำความร้อนต่างๆจึงสำคัญมาก
และซิลิโคนสารนำความร้อนที่ใช้ก็ผลิตมาสำหรับนำความร้อนได้ดีในพื้นที่จำกัด ด้วย


Thermal Compoundทำจาก...??

...ซิลิโคนที่ใช้กันในอุปกรณ์ อิเล็กทรอนิกส์ทั่วไป มี2ประเภทคือ สารที่เป็นโลหะ และสารโลหะผสมออกไซด์
ซึ่งเป็นสารประกอบซิงค์ออกไซด์ อลูมินัมออกไซด์ คอปเปอร์ออกไซด์ และซิลเวอร์ออกไซด์ก็ได้ คุณสมบัติ
ส่วนใหญ่คือ ไม่นำไฟฟ้า ไม่แห้ง เหนียว ลักษณะเป็นครีมสีขาว สีแดง สีเทา อาจมีสีอื่นได้ขึ้นอยู่กับว่าใส่สาร
ประกอบนำความร้อนชนิดใดถ้า เป็นสารแบบโลหะจะนำความร้อนและนำไฟฟ้าด้วย ต้องพิจารณาด้วยว่าควรเอา
มาใช้ระบายความร้อนสื่อนำไฟฟ้าอะไรบ้าง และระมัดระวังการทาโดนส่วนอื่นที่อาจเกิดการซ็อตกันขึ้น บางชนิดเหนียว
เช็ดทำความสะอาดออกง่าย บางชนิดเหมือนกาวเชื่อม เหมาะสำหรับวัสดุที่ติดแล้วติดเลย เช่นชิพเช็ต การ์ดวีจีเอเป็นต้น


วิธีการใช้Thermal Compound

...การทาซิลิโคนควรทาในบริเวณที่เกิดความร้อนสูง คือแกนcore หรือชิพซีพียู แล้วค่อยทำการติดตั้งฮีทซิงค์ลงไป
ไม่จำเป็นที่จะต้องทาหนามากเกินไป เพราะจะเป็นการดันความร้อนแทนที่จะนำความร้อน ควรทาบางพอประมาณว่า
สามารถเชื่อมรอยต่อได้ หรือจะทาหนาๆไว้ก่อนก็ได้ครับ พอติดตั้งฮีทซิงค์แล้ว แรงกดจะกระจายสาร Thermal Compound
หรือ ซิลิโคนออกไปทำให้อากาศช่องว่างออกไปหมด คือแนบสนิทครับ นอกจากใช้งานกับซีพียูแล้ว หน่วยความจำ
ชิพเช็ต อุปกรณ์อิเล็กทรอนิกส์ต่างๆที่มีความร้อนก็สามารถใช้ด้วยกันได้ และชิพวิจีเอก็ใช้ชิลิโคนทาเพื่อนำความร้อน
ได้ด้วยเช่นกัน ก่อนทาควรทำความสะอาดผิวสัมผัสให้สะอาดเสียก่อน ที่จะติดตั้งฮีทซิงค์ดูด้วยว่าแนบสนิทกันดีหรือไม่
อาจจะต้องทำให้ผิวเรียบสนิทขึ้นก่อนใช้งาน โดยการขัดผิวฮีทซิงค์ด้วยกระดาษทรายละเอียดเพื่อลอกเอาสิ่งสกปรกออก
และทำความสะอาดอีกครั้งและพอเห็นว่าเรียบสนิทดีแล้วก็ทาThermal Compoundลงไป และกรณีที่จะใช้Thermal 
Compoundแบบออกไซด์ผสมจะไม่มีปัญหาเรื่องซ็อตกันเท่าไหร่ เพราะไม่นำไฟฟ้า ถ้าสารThermal Compound
เป็นแบบโลหะก็ควรระมัดระวังการทาโดนวงจรอื่นของซีพียูหรือทาโดนบริเวณอื่นเข้า เพื่อป้องกันการซ็อตขึ้นครับ

วันพุธที่ 13 มีนาคม พ.ศ. 2556

CMS คืออะไร


ระบบการจัดการเนื้อหาของเว็บไซต์ (Content Management System: CMS) คือ ระบบที่พัฒนา คิดค้นขึ้นมาเพื่อช่วยลดทรัพยากรในการพัฒนา (Development)และบริหาร (Management)เว็บไซต์ ไม่ว่าจะเป็นเรื่องของกำลังคน ระยะเวลา และเงินทอง ที่ใช้ในการสร้างและควบคุมดูแลไซต์ โดยส่วนใหญ่แล้ว มักจะนำเอาภาษาสคริปต์ (Script languages) ต่างๆมาใช้ เพื่อให้วิธีการทำงานเป็นแบบอัตโนมัติ ไม่ว่าจะเป็น PHP, Perl, ASP, Python หรือภาษาอื่นๆ(แล้วแต่ความถนัดของผู้พัฒนา) ซึ่งมักต้องใช้ควบคู่กันกับโปรแกรมเว็บเซิร์ฟเวอร์ (เช่น Apache) และดาต้าเบสเซิร์ฟเวอร์(เช่น MySQL)


ลักษณะเด่นของ CMS

ก็คือ มีส่วนของ Administration panel(เมนูผู้ควบคุมระบบ) ที่ใช้ในการบริหารจัดการส่วนการทำงานต่างๆในเว็บไซต์ ทำให้สามารถบริหารจัดการเนื้อหาได้อย่างรวดเร็ว และเน้นที่การ จัดการระบบผ่านเว็บ(Web interface) ในลักษณะรูปแบบของ ระบบเว็บท่า(Portal Systems) โดยตัวอย่างของฟังก์ชันการทำงาน ได้แก่ การนำเสนอบทความ(Articles), เว็บไดเรคทอรี(Web directory), เผยแพร่ข่าวสารต่างๆ(News), หัวข้อข่าว(Headline), รายงานสภาพดินฟ้าอากาศ(Weather), ข้อมูลข่าวสารที่น่าสนใจ(Informations), ถาม/ตอบปัญหา(FAQs), ห้องสนทนา(Chat), กระดานข่าว(Forums), การจัดการไฟล์ในส่วนดาวน์โหลด(Downloads), แบบสอบถาม(Polls), ข้อมูลสถิติต่างๆ(Statistics) และส่วนอื่นๆอีกมากมาย ที่สามารถเพิ่มเติม ดัดแปลง แก้ไขแล้วประยุกต์นำมาใช้งานให้เหมาะสมตามแต่รูปแบบและประเภทของเว็บไซต์นั้นๆ ปัจจุบันซอฟต์แวร์ที่ใช้สร้าง CMS มีหลายตัวด้วยกันอาทิเช่น PostNuke, PHP-Nuke, MyPHPNuke, Mambo, eNvolution, MD-Pro, XeOOPs, OpenCMS, Plone, JBoss, Drupal เป็นต้น


ลักษณะการทำงานของ Content Management System (CMS)

เป็นระบบที่แบ่งแยกการจัดการในการทำงานระหว่างเนื้อหา(Content) ออกจากการออกแบบ (Design) โดยการออกแบบเว็บเพจจะถูกจัดเก็บไว้ใน Templates หรือ Themes ในขณะที่เนื้อหาจะถูกจัดเก็บไว้ในฐานข้อมูลหรือไฟล์ เมื่อใดที่มีการใช้งานก็จะมีการทำงานร่วมกันระหว่าง 2 ส่วน เพื่อสร้างเว็บเพจขึ้นมา โดยเนื้อหาอาจจะประกอบไปด้วยหลายๆส่วนประกอบ เช่น Sidebar หรือ Blocks, Navigation bar หรือ Main menu, Title bar หรือ Top menu bar เป็นต้น


การประยุกต์ใช้ CMS ในวงการต่างๆ

ระบบ CMS สามารถนำมาประยุกต์ในงานต่างๆ หลากหลาย ตัวอย่างการนำซอฟต์แวร์ CMS มาประยุกต์ใช้งาน อาทิเช่น

- การนำ CMS มาใช้ในการสร้างเว็บไซต์สถาบันการศึกษา ธุรกิจบันเทิง หนังสือพิมพ์ การเงิน การธนาคาร หุ้นและการลงทุน อสังหาริมทรัพย์ งานบุคคล งานประมูล สถานที่ท่องเที่ยว งานให้บริการลูกค้า
- การนำ CMS มาใช้ในหน่วยงานของรัฐ อาทิเช่น งานข่าว งานประชาสัมพันธ์ การนำเสนองานต่างๆ ขององค์กร
- การใช้ CMS สร้างไซต์ ส่วนตัว ชมรม สมาคม สมาพันธ์ โดยวิธีการแบ่งงานกันทำ เป็นส่วนๆ ทำให้เกิดความสามัครคี ทำให้มีการทำงานเป็นทีมเวิร์คมากยิ่งขึ้น
- การนำ CMS มาใช้ในการสร้างเว็บไซต์สำหรับธุรกิจ SME โดยเฉพาะสินค้าหนึ่งตำบลหนึ่งผลิตภัณฑ์ หรือ OTOP กำลังได้รับความนิยมสูง
- การนำ CMS มาใช้แทนโปรแกรมลิขสิทธิ์ อื่นๆ เพื่อประหยัดค่าใช้จ่าย และง่ายต่อการพัฒนา
- การใช้ CMS ทำเป็น Intranet Web Site สร้างเว็บไซต์ใช้ภายในองค์กร


ส่วนประกอบของ CMS

· Templates หรือ Theme เป็นส่วนที่เปรียบเสมือนหน้าตา หรือเสื้อผ้า ที่ถือเป็นสีสรรของเว็บไซต์ (Look&feel) ที่มีรูปแบบที่กลมกลืนกันตลอดทั้งไซต์

· ภาษาสคริปต์ หรือ ภาษา HTML ที่ใช้ในการควบคุมการทำงานทั้งหมดของระบบ ฐานข้อมูล เพื่อไว้เก็บข้อมูลทุกอย่างที่เกี่ยวข้องทั้งหมดของเว็บไซต์


แล้ว CMS กับ Web log มันต่างกันตรงไหน

Web log นิยมเรียกสั้นๆ ว่า Blog หมายถึง เว็บไซต์ที่มีรูปแบบง่ายๆ โดยมากจะเป็นในลักษณะเว็บไซต์ส่วนตัวคนสร้างบล็อกต้องการบรรยายเหตุการณ์ส่วนตัว อาทิ ความในใจ ชีวิติครอบครัว เหตุการณ์ประทับใจในชีวิต อะไรทำนองนี้ โดยที่เนื้อหาของบล็อกแต่ละบล็อกนั้นจะเป็นเนื้อหาใหม่ล่าสุด ไล่ย้อนหลังลงกลับไปเรื่อยๆ กล่าวคือข้อความหลังสุดจะอยู่ด้านบนสุด เราเรียกคนที่ทำ Blog ว่า Blogger หรือ Weblogger โดยในเนื้อหาใน Blog นั้นจะส่วนประกอบสามส่วนคือ
- หัวข้อ (Title) เป็นหัวข้อสั้นสั้นๆ
- เนื้อหา (Post หรือ Content) เป็นเนื้อหาหลักที่คนสร้าง Blog ต้องการที่จะบอกให้คุณทราบ
- วันที่เขียน (Date) เป็นวัน เดือน ปี ที่เขียนทูลที่ใช้ทำ Blog เช่น pMachine , b2evolution, bBlog, MyPHPblog, Nucleus, Wordpress, Simplog เป็นต้น

ปัจจุบันเว็บบล็อกบางตัวฝังโมดูลกระดานข่าวและอื่นๆ มาด้วย
หากจะพูดแบบภาษาชาวบ้าน CMS ก็คือปู่ของ Blog นั่นแหละครับ เพราะ CMS เองก็สามารถนำมาทำเป็น Blog ได้ แต่ CMS มันมีความสามารถอื่นๆ อีกมากที่บล็อกทำไม่ได้


ข้อดีของ CMS

1.ผู้ใช้งานไม่จำเป็นต้องมีความรู้เรื่องการทำเว็บไซต์ เพียงแค่เคยพิมพ์ หรือเคยโพสข้อความในอินเทอร์เนต ก็สามารถมีเว็บไซต์เป็นของตัวเองได้
2.ไม่เสียเวลาในการพัฒนาเว็บไซต์ ไม่เสียเงินจำนวนมาก
3.ง่ายต่อการดูแล เพราะมีระบบจัดการทุกอย่างให้เราหมด
4.มีระบบจัดการที่เราสามารถหามาใส่เพิ่มได้มากมาย อย่างเช่น ระบบแกลลอรี่
5.สามารถเปลี่ยนหน้าตาเว็บไซต์ได้ง่ายๆ เพียงแค่โหลดทีม (Theme) ของ CMS นั้นๆ

ข้อเสียของ CMS

1.ในกรณีที่ผู้ใช้ต้องการออกแบบทีม (หน้าตาของเว็บ) เอง จะต้องใช้ความรู้มากกว่าปรกติ เนื้องจาก CMS มีหลายๆระบบมารวมกันทำให้เกิดความยุ่งยาก สำหรับผู้ที่ไม่มีความรู้
2.ผู้ใช้จะต้องศึกษาระบบ CMS ที่ผู้พัฒนาสร้างขึ้นมา เช่นจะต้องใส่ข้อความลงตรงไหน จะต้องแทรกภาพอย่างไร ซึ่งจะลำบากเพียงแค่ช่วงแรกเท่านั้น
3.ในการใช้งานจริงนั้นจะมีความยุ่งยากในการ set up ครั้งแรกกับ web server แต่ปัจจุบันก็มีผู้บริการ web server มากมายที่เสนอลงและ set up ระบบ CMS ให้ฟรีๆโดยไม่เสียค่าใช้จ่าย

เมื่อรวมๆข้อดีและข้อเสียดูแล้ว ก็ยังเห็นได้ว่า CMS นั้นก็เป็นระบบที่น่าใช้งานอยู่ดี

แนะนำ CMS
- Mambo
- Joomla
- Blogger
- WordPress

วันอังคารที่ 5 มีนาคม พ.ศ. 2556

แชร์เน็ตให้กับเพื่อนๆ ด้วย Connectify


สำหรับ Connectify PRO โดยเป็นโปรแกรมที่จะทำให้เราและเพื่อนๆ ทุกคนสามารถเข้าใช้งานอินเทอร์เน็ตได้โดยผ่านโน้ตบุ๊ คของเรา โดยที่ไม่ต้องเสียบสาย LAN เพราะมันคือการแชร์อินเทอร์เน็ตผ่าน Wi-Fi จากโน้ตบุ๊คของเราเอง…เสมือนว่าเรามี Hotspot ใหม่เกิดขึ้นในบริเวณนั้นๆ ถ้าใครรับสัญญาณ Wi-Fi ของเราได้ก็เข้ามาใช้เน็ตได้นั่นเอง โดยโปรแกรมนี้จะช่วยให้เราสามารถแชร์อินเตอร์เน็ตให้ กับคอมพิวเตอร์เครื่อง อื่นที่ใช้ WiFi ได้ ถึงแม้ว่าจะไม่มีแอคเคาท์ที่จะเชื่อมต่ออินเตอร์เน็ต เพียงแค่ใช้โปรแกรมนี้แล้วให้เครื่องอื่นเชื่อมต่อเข้ามาที่เครื่องของเรา เครื่องอื่นก็จะสามารถใช้งานอินเตอร์เน็ตได้ทันทีครั บ ทั้งนี้โปรแกรม Connectify จะทำหน้าที่ในการสร้างเครือข่ายที่เรียกว่า Ad Hoc ขึ้นมา ซึ่งมีข้อกำหนดอย่างหนึ่งว่าการ์ด Wi-Fi หรือชิป Wi-Fi ที่ฝังอยู่ในโน้ตบุ๊คของเราจะต้องรองรับการรับ-ส่งหรือมีความสามารถในการ แชร์สัญญาณได้ด้วย (AP Mode) ซึ่งในปัจจุบันมีโน้ตบุ๊คเพียงไม่กี่รุ่นที่มีความสา มารถนี้ แต่สำหรับการ์ด Wi-Fi แบบเสียบภายนนอกที่เป็น USB จะมีความสามารถนี้อยู่แล้ว ฉะนั้นก่อนใช้งานท่านควรตรวจสอบก่อนว่าการ์ด Wi-Fi ของท่านนั้นรองรับการแชร์อินเทอร์เน็ต (AP Mode) ด้วยระบบนี้หรือไม่นะครับ
>>> Connectify 3.7.1.25486 Pro







วันอาทิตย์ที่ 3 มีนาคม พ.ศ. 2556

วิธีแก้ไข Wireless ขึ้นเครื่องหมายตกใจ (!)



ปัญหาของการที่ขึ้นเครื่องหมายตกใจ เกิดได้จากการเปิดให้เครื่องรับ IP แบบ Automatic แล้วไม่ได้รับ IP เข้ามา Windows จึงทำการกำหนด IP Private ให้กับเครื่องเอง และโดยมากจะใช้ไม่ได้เพราะคนละวงกับที่เราใช้กันอยู่

วิธีแก้ คือถ้าคุณใช้ ip เป็นแบบ AUTO ให้ใช้วิธี FIX IP แทนครับ เช่น ip ที่ router เป็น 192.168.0.1 ให้ ใส่เลขตัวสุดท้ายในเครื่องคอมคุณให้อยู่ ในระหว่าเลข 2 - 255 ครับ เลือกเอาเลขใอะไรก็ ได้ ...แต่ต้องย้อนถามก่อนว่าคุณใช้ windows 7 รึเปล่าครับ ถ้าใช่ก็ แนะนำให้ไปเปลี่ยนนะครับ สำหรับ notebook

แต่ถ้าคุณ fix แล้ว นำไปเล่นในที่อื่นที่ไม่ใช่ router ตัวที่มีปัญหา คุณต้องปรับค่าให้เป็น auto เหมือนเดิมนะครับ แล้วพอกลับมาตัวที่มีปัญหาก็ให้ fix ใหม่

วีธี fix

ip adsress 192.168.0.12

subnet mask 255.255.255.0

gateway 192.168.0.1




สังเกต gateway คือ ip ของ router ครับ ip address คือ ip ของเครื่องคอมของคุณนะครับ




ไม่ก็ลองอีกวิธี คือ




1. ไปที่ control panel

2. เลือก adminstrative tools

3. แล้วก็ service

4. หาแถบที่เขียนว่า ## id string xxxxx ## จะอยู่บนสุด

แล้วคลิกขวา property เปลียน่จาก auto เป้น disble แล้วกด stop รีสตราสเครื่อง ใช้ได้เลย


หมายเหตุ

##Id_String1.6844f930_1628_4223_b5cc_5bb94b879762## Apple Computer, INC

ตัวนี้จะถูกติดตั้งมาพร้อมกับการติดตั้งผลิตภัณฑ์ของ Adobe ครับ หากที่เครื่องของคุณไม่มีการติดตั้งผลิตภัณฑ์ดังกล่าวก็จะไม่มี Service นี้ครับ ให้ลองวิธีปิด ipv6 ดูก่อนนะครับ





วันพฤหัสบดีที่ 28 กุมภาพันธ์ พ.ศ. 2556

Web วาดรูปด้วย canvas จาก HTML5



ใน HTML5 นั้นจะมี Element ที่ชื่อว่า canvas ที่เราสามารถใช้ jQuery หรือ JavaScript ควบคุมการทำงานของมันได้ ไม่ว่าจะวาดภาพ วาดวงกลม ใส่รูป เราก็สามารถใส่เข้าไปใน canvas ได้

ถ้าเพื่อนๆที่เคยใช้พวก Java applet คงจะพอนึกภาพออกนะครับว่า Canvas นั้นมันก็เป็นพื้นที่สี่เหลี่ยมที่เอาไว้ใช้แสดงผลกราฟฟิก ที่เราสามารถจะควบคุมได้ สามารถควบคุมในระดับ pixel ได้เลยทีเดียว

Canvas นั้นก็เหมือนๆกับ Element อื่นๆครับ สามารถกำหนด Style ให้ได้ไม่ว่าจะเป็นสี ขนาดความกว้าง ความสูง กำหนดทำแหน่งได้ด้วย

ผมก็เลยเอาตัวอย่างเว็บที่ผมเขียนขึ้นมาให้ดูว่ามันเป็นอย่างไร 
ผมไม่ได้เขียนขึ้นเองมาทั้งหมด นำมาจากหลายที่ แก้ไขและเพิ่มเติม 
ก็เลยจะนำมาแบ่งให้เพื่อนๆศึกษากันดู ^^



------------------------------------------------------------------------------------------------------------

canvas.html


<html>
<head>
<script type="text/javascript" src="canvas2image.js"> </script>
</head>
<body>
<center>
<button id="pencil" onclick="Default()"> Default </button>
<input type="color" name="favcolor" id="favcolor" onchange="selectColor()"/>
<button id="sizeP" onclick="sizeP()"> + </button>
<button id="sizeD" onclick="sizeD()"> - </button>
<input type="file" NAME="Files" onchange="preview(this)" />
<button id="Submit" onclick="Submit()"> Submit </button>

</br>
<button id="clears" onclick="Pencil()"> Pencil </button>
<button id="Circle" onclick="Circle()"> Circle </button>
<button id="Rectangle" onclick="Rectangle()"> Rectangle </button>
<button id="Ellipse" onclick="Ellipse()"> Ellipse </button>
<button id="export" onclick="exportImage()"> Export </button>
<button id="eraser" onclick="eraser()"> Eraser </button>
<button id="clears" onclick="Clear_image()"> Clear </button></br>
<canvas id="canvas" width="800" height="500" style="border: 1px solid black;"></canvas>
<div id="coord"></div></center>



<script> 
var mouse = {x: 0, y: 0};
var start_mouse = {x: 0, y: 0};
var radius = 5;
var canvas = document.getElementById('canvas'),
    coord = document.getElementById('coord'),
    context = canvas.getContext('2d'), // get 2D context
    rect = {},
    drag = false;
imgCat = new Image();

/*********** draw image *************/
imgCat.src = 'Untitled.jpg';
imgCat.onload = function() { // wait for image load
    context.drawImage(imgCat, 0, 0); // draw imgCat on (0, 0)
context.lineWidth = radius;
context.strokeStyle = '#000000';
context.lineWidth = 5;
};

function getPath(){
      var str = document.getElementById('blaat').value;
      // lastIndexOf('\\') you need to use two \\'s because you use \ to escape
      str = str.substring(0, str.lastIndexOf('\\'));
      //if you want a closing \ just add a \ to the str (str += '\')
      document.getElementById('verborgenBlaat').value = str;
      // alert to proof it sets the directory 
      alert(document.getElementById('verborgenBlaat').value)
}

function preview(test){
    var source=test.value;
    alert(source);
}


function fileSelected(){
alert( document.forms[0].files.value);

}
function Submit(){
alert(document.forms[0].getElementById('files').value);

}


/*********** handle mouse events on canvas **************/
function Pencil(){
context.strokeStyle = document.getElementById("favcolor").value;
var mousedown = false;
canvas.onmousedown = function(e) {
    var pos = fixPosition(e, canvas);
    mousedown = true;
    context.beginPath();
    context.moveTo(pos.x, pos.y);
    return false;
};

canvas.onmousemove = function(e) {
    var pos = fixPosition(e, canvas);
    coord.innerHTML = '(' + pos.x + ',' + pos.y + ')';
    if (mousedown) {
        context.lineTo(pos.x, pos.y);
        context.stroke();
    }
};

canvas.onmouseup = function(e) {
    mousedown = false;
};

}
/********** utils ******************/
// Thanks to http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element/4430498#4430498
function fixPosition(e, gCanvasElement) {
    var x;
    var y;
    if (e.pageX || e.pageY) { 
      x = e.pageX;
      y = e.pageY;
    }
    else { 
      x = e.clientX + document.body.scrollLeft +
          document.documentElement.scrollLeft;
      y = e.clientY + document.body.scrollTop +
          document.documentElement.scrollTop;
    } 
    x -= gCanvasElement.offsetLeft;
    y -= gCanvasElement.offsetTop;
    return {x: x, y:y};
}


function exportImage() {
window.open(canvas.toDataURL(),'_blank','width=800,height=600');
//window.open("http://www.w3schools.com")
}
function Default(){
   context.strokeStyle = document.getElementById("favcolor").value;
   context.lineWidth = 5;
}

function Clear_image() {
context.clearRect(0, 0, canvas.width, canvas.height);

function sizeP() {
radius++;
                context.lineWidth = radius;

function sizeD() {
if(radius==1){}
else{
radius--;
                context.lineWidth = radius;
}

function eraser(){
Pencil();
   context.strokeStyle = "#FFFFFF";
  
}
function showR(){
   document.write(radius);
}

//////////////////////////////////////////////////////

function Rectangle(){
context.strokeStyle = document.getElementById("favcolor").value;
      var mousedown = false;
canvas.onmousedown = function(e) {
var pos = fixPosition(e, canvas);
mousedown = true;
context.drawImage(canvas, 0, 0);
context.beginPath();
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
return false;
};

canvas.onmousemove = function(e) {
    var pos = fixPosition(e, canvas);
    coord.innerHTML = '(' + pos.x + ',' + pos.y + ')';
    
/* if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    context.clearRect(0,0,canvas.width,canvas.height);
    context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
  }
*/
};



canvas.onmouseup = function(e) {
if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    
    context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
  }
    mousedown = false;
};
}


function Circle(){
context.strokeStyle = document.getElementById("favcolor").value;
var mousedown = false;
canvas.onmousedown = function(e) {
var pos = fixPosition(e, canvas);
mousedown = true;
context.drawImage(canvas, 0, 0);
context.beginPath();
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
return false;
};

canvas.onmousemove = function(e) {
    var pos = fixPosition(e, canvas);
    coord.innerHTML = '(' + pos.x + ',' + pos.y + ')';
    
/* if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    context.clearRect(0,0,canvas.width,canvas.height);
    context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
  }
*/
};



canvas.onmouseup = function(e) {
if (mousedown) {
    rect.w = (e.pageX - this.offsetLeft) - rect.startX;
    rect.h = (e.pageY - this.offsetTop) - rect.startY ;
    
var radius = Math.max(
Math.abs(rect.w),
Math.abs(rect.h)
) / 2;
    context.arc(rect.startX, rect.startY, radius, 0, Math.PI*2, false);
context.stroke();
context.closePath();
  }
    mousedown = false;
};

}





</script>

</body>
</html>

------------------------------------------------------------------------------------------------------------

canvas2image.js


var Canvas2Image = (function() {

// check if we have canvas support
var bHasCanvas = false;
var oCanvas = document.createElement("canvas");
if (oCanvas.getContext("2d")) {
bHasCanvas = true;
}

// no canvas, bail out.
if (!bHasCanvas) {
return {
saveAsBMP : function(){},
saveAsPNG : function(){},
saveAsJPEG : function(){}
}
}

var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
var bHasDataURL = !!(oCanvas.toDataURL);
var bHasBase64 = !!(window.btoa);

var strDownloadMime = "image/octet-stream";

// ok, we're good
var readCanvasData = function(oCanvas) {
var iWidth = parseInt(oCanvas.width);
var iHeight = parseInt(oCanvas.height);
return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
}

// base64 encodes either a string or an array of charcodes
var encodeData = function(data) {
var strData = "";
if (typeof data == "string") {
strData = data;
} else {
var aData = data;
for (var i=0;i<aData.length;i++) {
strData += String.fromCharCode(aData[i]);
}
}
return btoa(strData);
}

// creates a base64 encoded string containing BMP data
// takes an imagedata object as argument
var createBMP = function(oData) {
var aHeader = [];
var iWidth = oData.width;
var iHeight = oData.height;

aHeader.push(0x42); // magic 1
aHeader.push(0x4D); 
var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256);

aHeader.push(0); // reserved
aHeader.push(0);
aHeader.push(0); // reserved
aHeader.push(0);

aHeader.push(54); // dataoffset
aHeader.push(0);
aHeader.push(0);
aHeader.push(0);

var aInfoHeader = [];
aInfoHeader.push(40); // info header size
aInfoHeader.push(0);
aInfoHeader.push(0);
aInfoHeader.push(0);

var iImageWidth = iWidth;
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256);
var iImageHeight = iHeight;
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256);
aInfoHeader.push(1); // num of planes
aInfoHeader.push(0);
aInfoHeader.push(24); // num of bits per pixel
aInfoHeader.push(0);
aInfoHeader.push(0); // compression = none
aInfoHeader.push(0);
aInfoHeader.push(0);
aInfoHeader.push(0);
var iDataSize = iWidth*iHeight*3; 
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); 
for (var i=0;i<16;i++) {
aInfoHeader.push(0); // these bytes not used
}
var iPadding = (4 - ((iWidth * 3) % 4)) % 4;

var aImgData = oData.data;

var strPixelData = "";
var y = iHeight;
do {
var iOffsetY = iWidth*(y-1)*4;
var strPixelRow = "";
for (var x=0;x<iWidth;x++) {
var iOffsetX = 4*x;

strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
}
for (var c=0;c<iPadding;c++) {
strPixelRow += String.fromCharCode(0);
}
strPixelData += strPixelRow;
} while (--y);

var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);

return strEncoded;
}


// sends the generated file to the client
var saveFile = function(strData) {
document.location.href = strData;
}

var makeDataURI = function(strData, strMime) {
return "data:" + strMime + ";base64," + strData;
}

// generates a <img> object containing the imagedata
var makeImageObject = function(strSource) {
var oImgElement = document.createElement("img");
oImgElement.src = strSource;
return oImgElement;
}

var scaleCanvas = function(oCanvas, iWidth, iHeight) {
if (iWidth && iHeight) {
var oSaveCanvas = document.createElement("canvas");
oSaveCanvas.width = iWidth;
oSaveCanvas.height = iHeight;
oSaveCanvas.style.width = iWidth+"px";
oSaveCanvas.style.height = iHeight+"px";

var oSaveCtx = oSaveCanvas.getContext("2d");

oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
return oSaveCanvas;
}
return oCanvas;
}

return {

saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
if (!bHasDataURL) {
return false;
}
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
var strData = oScaledCanvas.toDataURL("image/png");
if (bReturnImg) {
return makeImageObject(strData);
} else {
saveFile(strData.replace("image/png", strDownloadMime));
}
return true;
},

saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
if (!bHasDataURL) {
return false;
}

var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
var strMime = "image/jpeg";
var strData = oScaledCanvas.toDataURL(strMime);
// check if browser actually supports jpeg by looking for the mime type in the data uri.
// if not, return false
if (strData.indexOf(strMime) != 5) {
return false;
}

if (bReturnImg) {
return makeImageObject(strData);
} else {
saveFile(strData.replace(strMime, strDownloadMime));
}
return true;
},

saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
if (!(bHasImageData && bHasBase64)) {
return false;
}

var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);

var oData = readCanvasData(oScaledCanvas);
var strImgData = createBMP(oData);
if (bReturnImg) {
return makeImageObject(makeDataURI(strImgData, "image/bmp"));
} else {
saveFile(makeDataURI(strImgData, strDownloadMime));
}
return true;
}
};

})();

------------------------------------------------------------------------------------------------------------

วันพุธที่ 27 กุมภาพันธ์ พ.ศ. 2556

โปรแกรม Scan Barcode and QR Code (Android)

ในส่วนของโปรแกรมนี้ ผมได้อยากทำจริงๆ  แต่บังเอิญ  มีเพื่อนผมคนหนึ่งวานให้เขียนให้หน่อย
ผมก็เลย Solo จัดการให้ด้วยความเป็นคนดี 555+    ทั้งที่ไม่มีความรู้ด้าน Android เท่าไหร่  
ในบทความนี้ผมจะเอาตัวอย่างโค้ดมาให้ดูว่ามันเป็นแบบไหน  เผื่อเพื่อนคนไหนสนใจ  จะนำไปศึกษาได้ เพราะผมก็นำจากคนอื่นมาต่อยอดอีกที   เดี่ยวถ้ามีโอกาสผมจะมาอธิบายแต่ละส่วนให้ฟังนะครับ ^^
โดยตัวโปรแกรมนี้  ผมได้นำ  Library ของ zbar.jar มาใช้ด้วย เพราะถ้าจะให้เขียนมาทั้งหมด  มันก็จะเยอะไป      ก็ค่อยๆศึกษากันไปนะครับ ^^
----------------------------------------------------------------------------------------------------------

CameraPreview.java

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private PreviewCallback previewCallback;
    private AutoFocusCallback autoFocusCallback;

    public CameraPreview(Context context, Camera camera,
                         PreviewCallback previewCb,
                         AutoFocusCallback autoFocusCb) {
        super(context);
        mCamera = camera;
        previewCallback = previewCb;
        autoFocusCallback = autoFocusCb;

        /* 
         * Set camera to continuous focus if supported, otherwise use
         * software auto-focus. Only works for API level >=9.
         */
        /*
        Camera.Parameters parameters = camera.getParameters();
        for (String f : parameters.getSupportedFocusModes()) {
            if (f == Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
                mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                autoFocusCallback = null;
                break;
            }
        }
        */

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);

        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            Log.d("DBG", "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Camera preview released in activity
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        /*
         * If your preview can change or rotate, take care of those events here.
         * Make sure to stop the preview before resizing or reformatting it.
         */
        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        try {
            // Hard code camera surface rotation 90 degs to match Activity view in portrait
            mCamera.setDisplayOrientation(90);

            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            mCamera.autoFocus(autoFocusCallback);
        } catch (Exception e){
            Log.d("DBG", "Error starting camera preview: " + e.getMessage());
        }
    }
}

------------------------------------------------------------------------------------------------------------

CameraTestActivity.java

public class CameraTestActivity extends Activity
{
    private Camera mCamera;
    private CameraPreview mPreview;
    private Handler autoFocusHandler;
    private EditText et;
    public static SQLiteDatabase db;
    TextView output;
    
    EditText res ;
    TextView scanText;
    Button scanButton;
    Button view;
    Button del;
    Button back;
    Button exit;

    ImageScanner scanner;

    private boolean barcodeScanned = false;
    private boolean previewing = true;

    static {
        System.loadLibrary("iconv");
    } 

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();
        res = (EditText)findViewById(R.id.editText1);
        
        /* Instance barcode scanner */
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        
        
        et = (EditText)findViewById(R.id.editText1);
        Button save = (Button)findViewById(R.id.button2);
        view = (Button)findViewById(R.id.button1);
        exit = (Button)findViewById(R.id.exit);
       
        save.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String name = et.getText().toString();   // รับค่าจาก txt_name

    if(name.equals("")){
    return;
    }
   
    String sql ="insert into person values(null,'"+name+"')";
    try{
    db.execSQL(sql);
    Toast.makeText(getBaseContext(), "Inset to Database is success.",Toast.LENGTH_SHORT).show();
    }catch(Exception e){
    Toast.makeText(getBaseContext(), "Error,"+e.getMessage(),Toast.LENGTH_SHORT).show();
    }finally{
    et.setText("");
    }
}
});
        
        
        view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(CameraTestActivity.this,ShowData.class);
startActivity(intent);
}
});
        
        
        
        exit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
           System.exit(0);
}
});
        
        
        
        
        preview.addView(mPreview);

        scanText = (TextView)findViewById(R.id.scanText);

        scanButton = (Button)findViewById(R.id.ScanButton);

        scanButton.setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    if (barcodeScanned) {
                        barcodeScanned = false;
                        scanText.setText("Scanning...");
                        mCamera.setPreviewCallback(previewCb);
                        mCamera.startPreview();
                        previewing = true;
                        mCamera.autoFocus(autoFocusCB);
                    }
                }
            });
        
    db = openOrCreateDatabase( "test1.db", SQLiteDatabase.CREATE_IF_NECESSARY, null); // สร้าง Database ชื่อ test1.db
db.setVersion(1);
db.setLocale(Locale.getDefault());
db.setLockingEnabled(true);

try {
            final String CREATE_TABLE_CONTAIN = "CREATE TABLE IF NOT EXISTS person ("  // ถ้าไม่มี table person ให้ทำการสร้าง
                    + "_id INTEGER primary key AUTOINCREMENT,"   // ฟิลด์ _id ให้เป็น PK
                    + "name TEXT);";                  // ฟิลด์ name ชนิด Text

            db.execSQL(CREATE_TABLE_CONTAIN);
          //  Toast.makeText(getBaseContext(), "Table person is created.",Toast.LENGTH_SHORT).show();
        }
        catch (Exception e) {
        Toast.makeText(getBaseContext(), "Error,"+e.getMessage(),Toast.LENGTH_SHORT).show();
        }
    }

   
   
    
    @Override
    protected void onDestroy(){
       super.onDestroy();
       db.close();  // Close Database Connection
    }
    

public void onPause() {
        super.onPause();
        releaseCamera();
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e){
        }
        return c;
    }

    private void releaseCamera() {
        if (mCamera != null) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    private Runnable doAutoFocus = new Runnable() {
            public void run() {
                if (previewing)
                    mCamera.autoFocus(autoFocusCB);
            }
        };

    PreviewCallback previewCb = new PreviewCallback() {
            public void onPreviewFrame(byte[] data, Camera camera) {
                Camera.Parameters parameters = camera.getParameters();
                Size size = parameters.getPreviewSize();

                Image barcode = new Image(size.width, size.height, "Y800");
                barcode.setData(data);

                int result = scanner.scanImage(barcode);
                
                if (result != 0) {
                    previewing = false;
                    mCamera.setPreviewCallback(null);
                    mCamera.stopPreview();
                    
                    SymbolSet syms = scanner.getResults();
                    for (Symbol sym : syms) {
                        scanText.setText("barcode result " + sym.getData());
                        res.setText(sym.getData().toString());
                        barcodeScanned = true;
                    }
                }
            }
        };

    // Mimic continuous auto-focusing
    AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
            public void onAutoFocus(boolean success, Camera camera) {
                autoFocusHandler.postDelayed(doAutoFocus, 1000);
            }
        };
}

-----------------------------------------------------------------------------------------------------------

ShowData.java


public class ShowData extends Activity{

private TextView output;
private Button del;
private Button back;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.showdata);
output = (TextView)findViewById(R.id.textView1);
del = (Button)findViewById(R.id.delete);
back = (Button)findViewById(R.id.back);
CameraTestActivity.db = openOrCreateDatabase( "test1.db", SQLiteDatabase.CREATE_IF_NECESSARY, null); // สร้าง Database ชื่อ test1.db
CameraTestActivity.db.setVersion(1);
CameraTestActivity.db.setLocale(Locale.getDefault());
CameraTestActivity.db.setLockingEnabled(true);

try {
            final String CREATE_TABLE_CONTAIN = "CREATE TABLE IF NOT EXISTS person ("  // ถ้าไม่มี table person ให้ทำการสร้าง
                    + "_id INTEGER primary key AUTOINCREMENT,"   // ฟิลด์ _id ให้เป็น PK
                    + "name TEXT);";                  // ฟิลด์ name ชนิด Text

            CameraTestActivity.db.execSQL(CREATE_TABLE_CONTAIN);
          //  Toast.makeText(getBaseContext(), "Table person is created.",Toast.LENGTH_SHORT).show();
        }
        catch (Exception e) {
        Toast.makeText(getBaseContext(), "Error,"+e.getMessage(),Toast.LENGTH_SHORT).show();
        }
showdata();
del.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
delete_clicked();
}
});
back.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(ShowData.this,CameraTestActivity.class);
startActivity(intent);
}
});
}
public void delete_clicked(){
    String sql = "delete from person ";
    CameraTestActivity.db.execSQL(sql);
      showdata();
    }

private void showdata() {
    output.setText("");
    SQLiteCursor cur = (SQLiteCursor)CameraTestActivity.db.rawQuery("select * from person",null);
    cur.moveToFirst();
         while (cur.isAfterLast() == false) {
          output.append(" Data : "+cur.getString(1)+"\n");
        cur.moveToNext();
         }
         cur.close();
}
}

------------------------------------------------------------------------------------------------------------

ที่มาที่ไป

เรื่องมันก็มีอยู่ว่า อยากจะเก็บเนื้อหา  ความรู้  และสิ่งที่ได้ทำไว้ที่ไหนสักแห่ง
ก็ได้พบเจอกับ blogger โดยบังเอิญ  ก็เลยปิ้งไอเดีย  เอาทุกอย่างที่สะสมมา มาเก็บไว้ในนี้  และเผยแพร่ให้เพื่อนๆที่สนใจมาดู  นี้ก็คือที่มานั้นเอง  อิอิ