คำตอบนี้สรุปได้จากการโหลดบิตแมปขนาดใหญ่อย่างมีประสิทธิภาพ
ซึ่งอธิบายถึงวิธีการใช้ inSampleSize เพื่อโหลดเวอร์ชันบิตแมปที่ลดขนาดลง
โดยเฉพาะอย่างยิ่งPre-scaling bitmapsจะอธิบายรายละเอียดของวิธีการต่างๆวิธีการรวมเข้าด้วยกันและวิธีใดเป็นหน่วยความจำที่มีประสิทธิภาพมากที่สุด
มีสามวิธีที่โดดเด่นในการปรับขนาดบิตแมปบน Android ซึ่งมีคุณสมบัติหน่วยความจำที่แตกต่างกัน:
createScaledBitmap API
API นี้จะใช้บิตแมปที่มีอยู่และสร้างบิตแมปใหม่พร้อมมิติข้อมูลที่คุณเลือกไว้
ในด้านบวกคุณจะได้ขนาดภาพที่ต้องการ (ไม่ว่าจะมีลักษณะอย่างไร) แต่ข้อเสียคือ API นี้ต้องการบิตแมปที่มีอยู่เพื่อให้ทำงานได้ หมายความว่ารูปภาพจะต้องโหลดถอดรหัสและสร้างบิตแมปก่อนจึงจะสามารถสร้างเวอร์ชันใหม่ที่เล็กกว่าได้ สิ่งนี้เหมาะอย่างยิ่งในแง่ของการได้ขนาดที่แน่นอนของคุณ แต่น่ากลัวในแง่ของค่าใช้จ่ายหน่วยความจำเพิ่มเติม ด้วยเหตุนี้นี่จึงเป็นตัวทำลายข้อตกลงสำหรับนักพัฒนาแอปส่วนใหญ่ที่มักจะคำนึงถึงความจำ
ธง inSampleSize
BitmapFactory.Options
มีคุณสมบัติที่ระบุinSampleSize
ว่าจะปรับขนาดภาพของคุณในขณะที่ถอดรหัสเพื่อหลีกเลี่ยงความจำเป็นในการถอดรหัสเป็นบิตแมปชั่วคราว ค่าจำนวนเต็มที่ใช้ที่นี่จะโหลดรูปภาพที่มีขนาดลดลง 1 / x ตัวอย่างเช่นการตั้งค่าinSampleSize
เป็น 2 จะส่งคืนรูปภาพที่มีขนาดครึ่งหนึ่งและการตั้งค่าเป็น 4 จะส่งคืนรูปภาพที่มีขนาด 1/4 โดยทั่วไปขนาดภาพจะมีขนาดเล็กกว่าขนาดต้นฉบับของคุณเสมอ
จากมุมมองของหน่วยความจำการใช้inSampleSize
เป็นการดำเนินการที่รวดเร็วมาก อย่างมีประสิทธิภาพมันจะถอดรหัสทุกพิกเซล Xth ของภาพของคุณเป็นบิตแมปที่ได้ มีสองประเด็นหลักinSampleSize
ดังนี้:
มันไม่ได้ให้คุณความละเอียดที่แน่นอน มันจะลดขนาดของบิตแมปของคุณด้วยกำลัง 2 เท่านั้น
มันไม่ได้ผลิตปรับขนาดคุณภาพที่ดีที่สุด ฟิลเตอร์ปรับขนาดส่วนใหญ่จะสร้างภาพที่ดูดีโดยการอ่านบล็อคพิกเซลจากนั้นจึงถ่วงน้ำหนักเพื่อสร้างพิกเซลที่ปรับขนาดดังกล่าว inSampleSize
หลีกเลี่ยงทั้งหมดนี้ด้วยการอ่านทุกๆสองสามพิกเซล ผลลัพธ์ที่ได้ค่อนข้างมีประสิทธิภาพและหน่วยความจำต่ำ แต่คุณภาพแย่ลง
หากคุณกำลังเพียงการจัดการกับการหดตัวภาพของคุณด้วยขนาด pow2 บางส่วนและการกรองจะไม่เป็นปัญหาแล้วคุณไม่สามารถหาหน่วยความจำมีประสิทธิภาพมากขึ้น (หรือมีประสิทธิภาพ) inSampleSize
วิธีการมากกว่า
แฟล็ก inScaled, inDensity, inTargetDensity
หากคุณจำเป็นต้องขนาดภาพไปยังมิติที่ไม่ได้เท่ากับอำนาจของทั้งสองแล้วคุณจะต้องinScaled
, inDensity
และธงinTargetDensity
BitmapOptions
เมื่อinScaled
ตั้งค่าสถานะแล้วระบบจะรับค่ามาตราส่วนเพื่อนำไปใช้กับบิตแมปของคุณโดยการหารinTargetDensity
ด้วยinDensity
ค่า
mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeResources(getResources(),
mImageIDs, mBitmapOptions);
การใช้วิธีนี้จะปรับขนาดรูปภาพของคุณใหม่และยังใช้ 'ตัวกรองการปรับขนาด' ด้วยนั่นคือผลลัพธ์สุดท้ายจะดูดีขึ้นเนื่องจากมีการพิจารณาคณิตศาสตร์เพิ่มเติมบางอย่างในระหว่างขั้นตอนการปรับขนาด แต่ขอเตือน: ขั้นตอนการกรองพิเศษนั้นใช้เวลาในการประมวลผลมากขึ้นและสามารถเพิ่มรูปภาพขนาดใหญ่ได้อย่างรวดเร็วส่งผลให้การปรับขนาดช้าลงและการจัดสรรหน่วยความจำเพิ่มเติมสำหรับตัวกรองเอง
โดยทั่วไปไม่ควรใช้เทคนิคนี้กับรูปภาพที่มีขนาดใหญ่กว่าขนาดที่คุณต้องการอย่างมีนัยสำคัญเนื่องจากค่าใช้จ่ายในการกรองเพิ่มเติม
การผสมผสานเวทมนตร์
จากมุมมองของหน่วยความจำและประสิทธิภาพคุณสามารถรวมตัวเลือกเหล่านี้เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด (การตั้งค่าinSampleSize
, inScaled
, inDensity
และinTargetDensity
ธง)
inSampleSize
ก่อนอื่นจะถูกนำไปใช้กับรูปภาพโดยทำให้มันมีกำลังสองต่อไปที่ใหญ่กว่าขนาดเป้าหมายของคุณ จากนั้นinDensity
& inTargetDensity
จะใช้เพื่อปรับขนาดผลลัพธ์ให้เป็นขนาดที่คุณต้องการโดยใช้การกรองเพื่อล้างภาพ
การรวมสองสิ่งนี้เป็นการดำเนินการที่เร็วกว่ามากเนื่องจากinSampleSize
ขั้นตอนดังกล่าวจะลดจำนวนพิกเซลที่ขั้นตอนที่ใช้ความหนาแน่นที่เป็นผลลัพธ์จะต้องใช้ตัวกรองการปรับขนาด
mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity = dstWidth * mBitmapOptions.inSampleSize;
// will load & resize the image to be 1/inSampleSize dimensions
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);
หากคุณต้องการปรับขนาดภาพให้พอดีกับขนาดที่เฉพาะเจาะจงและการกรองที่ดีกว่าเทคนิคนี้เป็นสะพานที่ดีที่สุดในการรับขนาดที่เหมาะสม แต่ทำในการดำเนินการที่รวดเร็วและมีหน่วยความจำต่ำ
รับขนาดภาพ
การรับขนาดภาพโดยไม่ต้องถอดรหัสภาพทั้งหมดในการปรับขนาดบิตแมปของคุณคุณจะต้องทราบขนาดที่เข้ามา คุณสามารถใช้inJustDecodeBounds
แฟล็กเพื่อช่วยให้ได้ขนาดของรูปภาพโดยไม่จำเป็นต้องถอดรหัสข้อมูลพิกเซลจริงๆ
// Decode just the boundaries
mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, mBitmapOptions);
srcWidth = mBitmapOptions.outWidth;
srcHeight = mBitmapOptions.outHeight;
//now go resize the image to the size you want
คุณสามารถใช้แฟล็กนี้เพื่อถอดรหัสขนาดก่อนจากนั้นคำนวณค่าที่เหมาะสมสำหรับการปรับขนาดตามความละเอียดเป้าหมายของคุณ