5.7. การรวมภาพ

primitives การวาดในหน้าก่อนหน้าจะวาดเครื่องหมาย เรขาคณิต ลงบนภาพ เช่น เส้น สี่เหลี่ยม หรือข้อความ สิ่งเหล่านี้ครอบคลุมการระบุตำแหน่งส่วนใหญ่ที่อัลกอริทึมต้องการแสดง แต่ไม่ทั้งหมด บางครั้งการระบุตำแหน่งนั้นเป็นภาพในตัวเองได้แก่ เฟรมอ้างอิงที่ถ่ายไว้เพื่อแสดงควบคู่กับเฟรมปัจจุบัน, ภาพขนาดย่อของการถ่ายภาพก่อนหน้าที่แสดงอยู่มุมหนึ่งของหน้าต่างแสดงผล, หรือเทมเพลตที่บันทึกไว้ซึ่งแสดงทับเฟรมสดเพื่อการสอบเทียบ กลไกสำหรับการวาดภาพหนึ่งทับบนอีกภาพหนึ่งคือ method เดียว -- draw_image() -- ซึ่งมีพารามิเตอร์เพียงพอสำหรับจัดการตำแหน่ง, การปรับขนาด, color palette และความโปร่งใสที่การรวมภาพจริงต้องการ

5.7.1. การเรียกใช้งานขั้นพื้นฐาน

ในรูปแบบที่ง่ายที่สุด draw_image รับ Image อีกอันและตำแหน่งที่ต้องการวาด:

reference = image.Image("/sdcard/reference.bmp")
img.draw_image(reference, x=10, y=10)

ปลายทางคือ img; แหล่งที่มาคือ reference; พิกเซลมุมซ้ายบนของแหล่งที่มาจะอยู่ที่ (10, 10) ของ img และพิกเซลที่เหลือของแหล่งที่มาจะต่อเนื่องไปทางขวาและลงจากตำแหน่งนั้น พิกเซลของปลายทางที่แหล่งที่มาครอบคลุมจะถูกเขียนทับด้วยพิกเซลที่สอดคล้องกันจากแหล่งที่มา ส่วนพิกเซลที่อยู่นอกพื้นที่ของแหล่งที่มาจะไม่ถูกแตะต้อง

หากแหล่งที่มาขยายเกินขอบของปลายทาง ส่วนที่เกินออกไปจะถูกตัดออกโดยอัตโนมัติ ซึ่งเป็นพฤติกรรมที่ยืดหยุ่นเช่นเดียวกับที่ set_pixel แสดงสำหรับตำแหน่งที่อยู่นอกขอบเขต โค้ดของแอปพลิเคชันไม่จำเป็นต้องจำกัดตำแหน่งให้อยู่ภายในขนาดภาพล่วงหน้า เพียงแค่ส่งตำแหน่งที่ต้องการแล้วปล่อยให้ method จัดการการตัดออก

5.7.2. การโหลดไฟล์แบบ inline

draw_image ยอมรับ path ของไฟล์แทน argument ของ Image และโหลดไฟล์นั้นก่อนทำการรวมภาพ:

img.draw_image("/sdcard/reference.bmp", x=10, y=10)

ดูเหมือนเป็นความสะดวก -- หนึ่งบรรทัดแทนที่จะเป็นสองบรรทัด -- และก็เป็นเช่นนั้นจริง แต่ความแตกต่างนั้นมากกว่าแค่ syntax การสร้าง Image จากไฟล์จะจัดสรรบัฟเฟอร์เพื่อเก็บพิกเซลที่ถอดรหัสแล้ว และบัฟเฟอร์นั้นจะอยู่จนกว่า garbage collection จะปล่อยมัน การส่ง path โดยตรงไปยัง draw_image จะทำให้โมดูลถอดรหัสไฟล์ลงใน scratch buffer, รวมภาพจากมัน และปล่อยบัฟเฟอร์นั้นเมื่อการเรียกใช้คืนค่า โดยไม่ต้องให้โค้ดของแอปพลิเคชันเก็บ reference ไปยัง Image แยกต่างหากระหว่างเฟรม

5.7.3. การปรับขนาด

เมื่อแหล่งที่มาและปลายทางมีขนาดต่างกัน -- การถ่ายภาพความละเอียดต่ำที่รวมเข้ากับ canvas ความละเอียดสูง หรือภาพขนาดย่อที่ต้องปรับให้เป็นสัดส่วนหนึ่งของเฟรม -- พารามิเตอร์ scale สองตัวจะดูแลการปรับขนาดแหล่งที่มาขณะวาด:

img.draw_image(reference, x=10, y=10, x_scale=2.0, y_scale=2.0)

x_scale และ y_scale เป็น float อิสระ การส่งค่าเดียวกันทั้งคู่จะปรับขนาดสม่ำเสมอ และการส่งค่าต่างกันจะยืดหรือหดแหล่งที่มาตามแกนใดแกนหนึ่ง การปรับขนาดเกิดขึ้นในเวลาวาด และ reference แหล่งที่มาจะไม่ถูกเปลี่ยนแปลง

bitmask ของ flag hint จะกำหนดวิธีการที่การปรับขนาดจะ interpolate ระหว่างพิกเซลจริง image.BILINEAR ให้ผลลัพธ์ที่นุ่มนวลกว่าแต่ต้องใช้การคำนวณมากขึ้น image.BICUBIC ให้ผลลัพธ์ที่นุ่มนวลกว่าอีกและต้องใช้ทรัพยากรมากขึ้นอีก ค่าเริ่มต้นใช้ nearest-neighbour ซึ่งถูกที่สุดและเป็นตัวเลือกที่ถูกต้องเมื่อแหล่งที่มามีความละเอียดพิกเซลเดียวกับปลายทางแล้ว flag สำหรับจัดการ aspect -- SCALE_ASPECT_KEEP, SCALE_ASPECT_EXPAND, SCALE_ASPECT_IGNORE -- กำหนดสิ่งที่ต้องทำเมื่อ aspect ratio ของแหล่งที่มาไม่ตรงกับสี่เหลี่ยมที่กำลังวาดเข้าไป

5.7.4. การผสม alpha

ตามค่าเริ่มต้น draw_image จะ แทนที่ พิกเซลปลายทางด้วยพิกเซลแหล่งที่มา เมื่อเป้าหมายคือการซ้อนทับแบบ โปร่งแสง เพื่อให้ปลายทางแสดงผ่านแหล่งที่มา พารามิเตอร์ alpha จะควบคุมวิธีการผสมทั้งสอง alpha=0 จะแสดงเฉพาะปลายทาง (ไม่มีแหล่งที่มา); alpha=255 เป็นค่าเริ่มต้นและแสดงเฉพาะแหล่งที่มา (การแทนที่เต็มรูปแบบ); ค่ากลางจะผสมทั้งสองตามสัดส่วน:

img.draw_image(overlay, x=0, y=0, alpha=128)

argument alpha_palette แยกต่างหากเป็นกลไก alpha ต่อพิกเซลเดียวของโมดูล มันรับภาพ GRAYSCALE ซึ่งค่าของมันถูกใช้เป็น alpha ที่ตำแหน่งที่ตรงกันในแหล่งที่มา เช่น heatmap ที่ค่า alpha แปรผันตามความเข้มของมัน ค่า alpha จะต้องถูกส่งเป็น argument ระดับสีเทาแยกต่างหากนั้น ภาพแหล่งที่มาที่มี alpha channel ของตัวเอง (เช่น PNG ที่มีความโปร่งใส) จะไม่ส่งผ่านโดยอัตโนมัติ

5.7.5. Source ROI และ palette

พารามิเตอร์เพิ่มเติมสองตัวทำให้กลไกการรวมภาพสมบูรณ์:

  • roi=(x, y, w, h) จำกัดแหล่งที่มาให้อยู่ในสี่เหลี่ยมย่อยของตัวเอง ดังนั้นเฉพาะสี่เหลี่ยมนั้นเท่านั้นที่จะรวมเข้ากับปลายทาง มีประโยชน์สำหรับการครอบตัดภายใน call เดียวกันโดยไม่ต้องเตรียมภาพที่ครอบตัดแล้วแยกต่างหาก

  • color_palette แทนที่ค่าของพิกเซลแหล่งที่มาแต่ละพิกเซลผ่าน lookup table ก่อนวาด ซึ่งเป็นกลไกเดียวกับที่ to_rainbow() และ to_ironbow() ใช้ โดยเปิดเผยไว้ที่นี่เพื่อให้ overlay สามารถ palettise ในระหว่างที่วาดลงบนปลายทางโดยไม่ต้องผ่านการแปลงแยกต่างหาก

ทั้งสองรวมกับทุกอย่างใน call อื่นๆ ได้แก่ การปรับขนาด, alpha, argument mask ของปลายทาง และพารามิเตอร์ roi ของปลายทางที่กำหนดขอบเขตการ เขียน ให้อยู่ในสี่เหลี่ยมของปลายทาง