สำหรับผู้ที่หลงเข้ามาอ่านที่ไม่เคยทำงานเกี่ยวกับกราฟฟิคมาก่อนก็คงจะไม่ค่อยรู้จักกันมากนักว่าภาพเวคเตอร์มันคืออะไร พิเศษยังไง
ภาพที่ใช้งานกันบนคอมนั้นจะแบ่งออกเป็นสองประเภทใหญ่ๆด้วยกันดังนี้
Bitmap
ภาพประเภท Bitmap (เรียกอีกอย่างว่า Raster) เป็นภาพที่เกิดจากจุดหลายๆจุดที่มีสีต่างกันมาเรียงกันที่เรียกกันว่าจุดพิกเซลนี่แหละ จนเป็นภาพหนึ่งภาพ ภาพประเภทนี้จะพบเห็นได้ทั่วไปอยู่แล้วบนคอม ไม่ว่าจะรูปถ่าย รูปจากอินเตอร์เนต ล้วนก็เป็น Bitmap ทั้งนั้น จุดสังเกตที่สำคัญของภาพ Bitmap เลยก็คือ เมื่อขยายภาพจนถึงระยะนึงจะเห็นว่าภาพแตก ภาพที่มีขนาดเล็กขยายนิดขยายหน่อยก็แตกแล้ว ส่วนภาพที่มีขนาดใหญ่จะขยายได้มากกว่าภาพเล็ก แต่เมื่อขยายไปเยอะๆภาพก็แตกอยู่ดีนั่นแหละ
Vector
ภาพเวคเตอร์จะเป็นภาพที่เกิดจากการคำนวณพิกัด XY บนระนาบ 2 มิติ เส้นทุกเส้น สีทุกสีเกิดจากการคำนวณทางคอมพิวเตอร์แล้วแสดงออกมาเป็นภาพ ไม่ได้เกิดจากการนำพิกเซลหลายๆจุดมาเรียงต่อๆกันแบบ Bitmap สำหรับภาพแบบ Vector จะพบได้ในงานกราฟฟิคบนคอมพิวเตอร์เท่านั้น มีคุณสมบัติพิเศษตรงที่ขยายเท่าไรภาพก็ไม่แตก เพราะเกิดจากการคำนวณจากคอมพิวเตอร์แล้ววาดใหม่ทุกครั้ง ดังนั้นไม่ว่าจะขยายมากเท่าไร มากเท่าไร ภาพก็จะคำนวณแล้ววาดขึ้นใหม่ ดังนั้นจึงเป็นที่นิยมกับงานออกแบบกราฟฟิค เพราะนำไปใช้งานได้สะดวก แต่ลูกเล่นในการตกแต่งเอฟเฟคจะยากกว่า ซึ่งต้องใช้ฝีมือพอสมควร
สำหรับภาพ Vector จะพบกันได้ในไฟล์ที่มีนามสกุลเป็น .ai เป็นต้น จริงๆแล้วก็ยังมีอีกหลายๆไฟล์เช่นกัน แต่งานส่วนมากจะนิยมเป็นไฟล์ .ai ซึ่งงาน Vector จะนำไปใช้งานก็จะแปลงให้เป็นภาพแบบ Bitmap แทน เมื่อแปลงเป็นภาพแบบ Bitmap แล้วก็จะพบกับปัญหาขยายแล้วภาพแตก
ดังนั้นจึงนิยมแปลงเป็นภาพ Bitmap ให้มีขนาดพอเหมาะสมกับงาน เวลาใช้งานกับแอปพลิเคชันแอนดรอยด์ก็ทำออกมาตามหน้าจอแต่ละขนาด ก็จะหมายความว่าถึงจะทำภาพ Vector แล้ว แต่สุดท้ายก็ใช้เป็น Bitmap แถมต้องทำหลายขนาดอีกต่างหาก ทำให้ภาพหนึ่งภาพมีหลายไฟล์
โดยที่ระบบบนแอนดรอยด์นั้นจะรองรับไฟล์ภาพดังนี้
Vector
ภาพเวคเตอร์จะเป็นภาพที่เกิดจากการคำนวณพิกัด XY บนระนาบ 2 มิติ เส้นทุกเส้น สีทุกสีเกิดจากการคำนวณทางคอมพิวเตอร์แล้วแสดงออกมาเป็นภาพ ไม่ได้เกิดจากการนำพิกเซลหลายๆจุดมาเรียงต่อๆกันแบบ Bitmap สำหรับภาพแบบ Vector จะพบได้ในงานกราฟฟิคบนคอมพิวเตอร์เท่านั้น มีคุณสมบัติพิเศษตรงที่ขยายเท่าไรภาพก็ไม่แตก เพราะเกิดจากการคำนวณจากคอมพิวเตอร์แล้ววาดใหม่ทุกครั้ง ดังนั้นไม่ว่าจะขยายมากเท่าไร มากเท่าไร ภาพก็จะคำนวณแล้ววาดขึ้นใหม่ ดังนั้นจึงเป็นที่นิยมกับงานออกแบบกราฟฟิค เพราะนำไปใช้งานได้สะดวก แต่ลูกเล่นในการตกแต่งเอฟเฟคจะยากกว่า ซึ่งต้องใช้ฝีมือพอสมควร
สำหรับภาพ Vector จะพบกันได้ในไฟล์ที่มีนามสกุลเป็น .ai เป็นต้น จริงๆแล้วก็ยังมีอีกหลายๆไฟล์เช่นกัน แต่งานส่วนมากจะนิยมเป็นไฟล์ .ai ซึ่งงาน Vector จะนำไปใช้งานก็จะแปลงให้เป็นภาพแบบ Bitmap แทน เมื่อแปลงเป็นภาพแบบ Bitmap แล้วก็จะพบกับปัญหาขยายแล้วภาพแตก
ดังนั้นจึงนิยมแปลงเป็นภาพ Bitmap ให้มีขนาดพอเหมาะสมกับงาน เวลาใช้งานกับแอปพลิเคชันแอนดรอยด์ก็ทำออกมาตามหน้าจอแต่ละขนาด ก็จะหมายความว่าถึงจะทำภาพ Vector แล้ว แต่สุดท้ายก็ใช้เป็น Bitmap แถมต้องทำหลายขนาดอีกต่างหาก ทำให้ภาพหนึ่งภาพมีหลายไฟล์
โดยที่ระบบบนแอนดรอยด์นั้นจะรองรับไฟล์ภาพดังนี้
JPEG, GIF, PNG, BMP และ WEBP (เฉพาะ 4.0 ขึ้นไป)
จะเห็นว่าไฟล์เหล่านี้เป็นไฟล์ภาพแบบ Bitmap ทั้งนั้นเลย
เป็นไปได้มั้ยที่จะเอาไฟล์ภาพแบบ Vector มาใช้งานเลย?
** ข้อสำคัญสำหรับการทำภาพ Vector **
ถึงแม้ว่าจะนำภาพ Bitmap มาใส่ในงาน Vector ได้ แต่ภาพ Bitmap ก็ไม่ได้แปลงเป็น Vector ให้เลยนะ อย่าเข้าใจผิดแล้วเอาภาพ Bitmap มาลากใส่งาน Vector เพื่อหวังว่า Bitmap มันจะเป็น Vector เวลาขยายภาพจะไม่แตก (ถ้าทำแบบนั้นได้จริงๆป่านนี้ภาพถ่ายก็ไม่ต้องมีความละเอียดสูงกันแล้ว)
ทีนี้มาดูที่โค๊ดกันเลยนะ ก่อนอื่นไปจัดหน้า Layout กันก่อน เจ้าของบล็อกจัดหน้า Layout ให้มีแค่ Image View กลางจอ
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="500dp"
android:layout_height="500dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher" />
</RelativeLayout>
กำหนดให้แสดงภาพ ic_launcher หรือภาพไอคอนไปก่อน เพราะว่าไฟล์ภาพ SVG ยังไม่สามารถแสดงได้ทันทีใน Layout ส่วน Image View ขอตั้งชื่อไอดีง่ายๆว่า imageView1
ทีนี้มาดูการใช้งานโค๊ดของไลบรารี svg-android กันต่อ สำหรับการใช้งานไลบรารีตัวนี้จะง่ายมากมาย
SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.sample_image);
ImageView iv = (ImageView)findViewById(R.id.imageView1);
iv.setImageDrawable(svg.createPictureDrawable());
นอกจากเก็บภาพไว้ใน res/raw แล้ว เก็บในโฟลเดอร์ assets ก็ได้นะ
SVG svg = SVGParser.getSVGFromAsset(getAssets(), "sample_image.svg");
ในกรณีที่ดึงภาพผ่านคลาส InputStream
InputStream input = กำหนดค่า;
SVG svg = SVGParser.getSVGFromInputStream(input);
สรุปโค๊ดใน Main.java ก็จะมีดังนี้
Main.java
package app.akexorcist.svgsample;
import com.larvalabs.svgandroid.SVG;
import com.larvalabs.svgandroid.SVGParser;
import android.os.Bundle;
import android.app.Activity;
import android.widget.ImageView;
public class Main extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SVG svg = SVGParser.getSVGFromResource(getResources()
, R.raw.sample_image);
ImageView iv = (ImageView)findViewById(R.id.imageView1);
iv.setImageDrawable(svg.createPictureDrawable());
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.akexorcist.svgsample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="app.akexorcist.svgsample.Main"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
พอลองทดสอบดูก็จะพบกับภาพ Vector แสดงบนหน้าจอแล้ว ไม่ว่าจะแสดงบนหน้าจอความละเอียดแค่ไหนภาพก็จะไม่แตก (เว้นแต่ว่าพวกเครื่องจอใหญ่ความละเอียดต่ำนะ อันนั้นเป็นที่เครื่อง)
แต่ถ้าเกิดว่า ภาพดันไม่แสดงซะงั้นล่ะ?
โค๊ดนี้จะใช้งานได้สำหรับแอนดรอยด์เวอร์ชันต่ำกว่า 2.3.7 ลงไป ซึ่งเวอร์ชันตั้งแต่ 3.0 ขึ้นไปจะไม่แสดงภาพให้เห็น เนื่องจากว่าแอนดรอยด์เวอร์ชัน 3.0 ขึ้นไปจะมีความสามารถ ในการนำ GPU มาช่วยประมวลผลในการแสดงภาพบน View เรียกกันว่า Hardware Acceleration ซึ่งไลบรารีตัวนี้ไม่ได้ทำให้รองรับ ดังนั้นเครื่องเวอร์ชันดังกล่าวจะไม่สามารถแสดงภาพได้ (แต่โค๊ดก็ไม่ได้เออเรอร์นะ แค่ภาพไม่ขึ้นเฉยๆ)
วิธีแก้ก็จะมีอยู่ด้วยกันสองสามวิธี ถ้าง่ายสุดก็คือ ยกเลิกการใช้งาน Hardware Acceleration ซะ กำหนดใน Activity นี้ว่าไม่ใช้งาน Hardware Acceleration โดยกำหนดที่ AndroidManifest.xml ดังนี้
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.akexorcist.svgsample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="false" >
<activity
android:name="app.akexorcist.svgsample.Main"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
ในกรณีที่อยากให้ Activity นั้นต้องการใช้งานละก็ ให้ไปกำหนดแค่ในโค๊ดแทนว่าให้เฉพาะ Image View ไม่ใช้งาน
SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.sample_image);
ImageView iv = (ImageView)findViewById(R.id.imageView1);
iv.setImageDrawable(svg.createPictureDrawable());
iv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
แต่ปัญหาต่อมาคือ ไอคำสั่งนี้มันใช้กับ API ที่ต่ำกว่า 11 ไม่ได้ เพราะมันถูกเพิ่มเข้ามาใน Android 3.0 นั่นเอง ถ้าจะให้รองรับทั้งเวอร์ชันใหม่และเก่าด้วย ก็ให้เช็คเวอร์ชันของเครื่องก่อนว่าเวอร์ชันอะไร ถ้าต่ำกว่า API 10 ลงมาก็จะไม่ใช้คำสั่งนี้ แต่ถ้าสูงกว่านั้นก็จะให้ใช้คำสั่งนี้ ดังนี้
SVG svg = SVGParser.getSVGFromResource(getResources(), R.raw.sample_image);
ImageView iv = (ImageView)findViewById(R.id.imageView1);
iv.setImageDrawable(svg.createPictureDrawable());
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.HONEYCOMB) {
iv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
แต่ตอนที่พิมโค๊ดจะพบกับปัญหานี้ต่อ
โปรแกรม Eclipse จะบอกว่าคำสั่งนี้อาจจะเกิดปัญหาได้ เพราะว่าโปรเจคได้ตั้งไว้ให้รันบนแอนดรอยด์ขั้นต่ำสุดคือ API 8 โดยทำงานที่ API 11 ขึ้นไป ดังนั้นบนเครื่องที่เป็น API 8-10 ก็จะทำให้คำสั่งนี้เกิดการเออเรอร์ขึ้นได้นั่นเอง
แต่จากคำสั่งเจ้าของบล็อกใช้ IF เช็คแล้ว ดังนั้นคำสั่งนี้จึงไม่มีทางทำงานบน API 8 - 10 แน่นอน ก็ให้เลือก Disable Check เพื่อยกเลิกการเช็คเออเรอร์ตัวนี้ไป
เท่านี้ก็เป็นอันเสร็จแล้วกับการนำภาพแบบ Vector มาใช้งานบนแอปพลิเคชันของผู้ที่หลงเข้ามาอ่าน ทำให้จัดการปัญหาเรื่องภาพแตกเมื่อขยายได้ดีนัก