คุณย้ายมาจากผู้ให้บริการอีกรายหนึ่งใช่หรือไม่ Check out our migration guide
รูปแบบเอาต์พุต PNG เดลต้าช่วยลดเวลาตอบสนองและประหยัดแบนด์วิดท์ได้มาก รวมทั้งมีประโยชน์อย่างยิ่งในสถานการณ์ที่เวลาตอบสนองและแบนด์วิธมีความสำคัญ เช่น แอปมือถือ
ทั้งนี้จะกำหนดให้โหลดพิกเซลในภาพต้นฉบับบนไคลเอนต์ จากนั้นจึงใช้ PNG เดลต้ากับภาพต้นฉบับเพื่อสร้างภาพที่เป็นผลลัพท์
ตัวอย่าง:
778 × 639 พิกเซล
409,048 ไบต์
110,904 ไบต์
แม้แต่ในตัวอย่างนี้ที่เน้นเส้นผมเป็นหลัก (ซึ่งเป็นสถานการณ์ที่เลวร้ายที่สุดสำหรับรูปแบบ PNG เดลต้า) ก็ยังช่วยประหยัดอย่างเห็นได้ชัด: 73%
PNG เดลต้าเป็นเพียงไฟล์ PNG ปกติที่คลังซอฟต์แวร์ใด ๆ ที่อ่าน PNG ได้จะสามารถอ่านไฟล์นี้ได้เช่นกัน เมื่อเปรียบเทียบกับภาพผลลัพธ์ PNG ปกติแล้ว สิ่งเดียวที่แตกต่างกันคือค่าพิกเซลเอง พื้นหลังได้รับการเข้ารหัสเป็นสีดำโปร่งใส 0x00000000 ส่วนพื้นหน้าเป็นสีขาวโปร่งใส 0x00FFFFFF พิกเซลโปร่งใสบางส่วนจะมีค่าสีตามจริง
| ประเภทพิกเซล | ภาพต้นฉบับ | PNG ปกติ | PNG เดลต้า | แหล่งเอาต์พุต |
|---|---|---|---|---|
| พื้นหน้า |
0xFFrrggbb
|
0xFFrrggbb
|
0x00FFFFFF
|
ภาพต้นฉบับ |
| พื้นหลัง |
0xFFrrggbb
|
0x00000000
|
0x00000000
|
PNG เดลต้า |
| ขอบ |
0xFFrrggbb
|
0x80rrggbb
|
0x80rrggbb
|
PNG เดลต้า |
ทั้งนี้หมายความว่าเมื่อคุณถอดรหัสค่าพิกเซล PNG เดลต้า คุณจะต้องดึงค่าพิกเซลที่แท้จริงนั้นจากต้นฉบับเมื่อคุณพบสีขาวโปร่งใส 0x00FFFFFF พิกเซลอื่น ๆ มีค่าเดียวกันกับในรูปแบบ PNG ปกติ
นี่คือตัวอย่างรหัส TypeScript สำหรับการถอดรหัสรูปแบบ PNG เดลต้า:
export function decodeDeltaPngInPlace(originalPixels: Uint8Array, deltaPngPixels: Uint8Array): Uint8Array {
const N = originalPixels.length / 4; // Array of RGBA values, div 4 to get number of pixels
for (let i = 0; i < N; i++) {
const i4 = i * 4;
const alpha = deltaPngPixels[i4 + 3]; // JavaScript is RGBA, +3 to get alpha
if (alpha == 0) {
const r = deltaPngPixels[i4]; // JavaScript is RGBA, +0 to get red
if (r == 0xFF) {
// Transparent white => foreground => take values from original
deltaPngPixels[i4] = originalPixels[i4];
deltaPngPixels[i4 + 1] = originalPixels[i4 + 1];
deltaPngPixels[i4 + 2] = originalPixels[i4 + 2];
deltaPngPixels[i4 + 3] = originalPixels[i4 + 3];
} // else transparent black => background => keep values
} // else partially transparent => keep values
}
return deltaPngPixels;
}
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการดำเนินการกับข้อมูลรูปภาพและข้อมูลพิกเซลใน JavaScript โปรดดูการช่วยสอนการจัดการพิกเซลกับแคนวาส ที่ยอดเยี่ยมบนเครือข่ายผู้พัฒนา Mozilla
คลังการโหลดภาพของคุณจะต้องสามารถรักษาค่าพิกเซลไว้ได้แม้กระทั่งพิกเซลที่โปร่งใสทั้งหมด ซึ่งเป็นวิธีการทำงานตามปกติ
แต่หากคุณใช้คลัง อย่างเช่น Python และ OpenCV ที่รู้จักกันดี คุณจะต้องใช้สัญญาณเตือน cv2.IMREAD_UNCHANGED และโหลดภาพดังนี้: cv2.imread(path, cv2.IMREAD_UNCHANGED) มิฉะนั้น OpenCV จะลบล้างค่าพิกเซลที่แท้จริงของพิกเซลที่โปร่งใสทั้งหมด
ขออภัย OpenCV ไม่ได้ใช้ข้อมูลการหมุนใด ๆ ที่จัดเก็บไว้ในภาพเมื่อคุณใช้สัญญาณเตือนนั้น นี่คือเหตุผลที่เราส่งคืนส่วนหัวของ X-Input-Orientation เพื่อให้คุณสามารถใช้การวางทิศทางที่ถูกต้องกับภาพในสถานการณ์นี้
นี่คือตัวอย่างโค้ด Python+OpenCV เพื่อใช้ในการวางทิศทาง:
def apply_exif_rotation(im: np.ndarray, orientation: int) -> np.ndarray:
# https://note.nkmk.me/en/python-opencv-numpy-rotate-flip/
if 1 < orientation <= 8:
if 2 == orientation: # TOP-RIGHT, flip left-right, [1, 1] -> [-1, 1]
im = cv2.flip(im, 1)
elif 3 == orientation: # BOTTOM-RIGHT, rotate 180
im = cv2.rotate(im, cv2.ROTATE_180)
elif 4 == orientation: # BOTTOM-LEFT, flip up-down, [1, 1] -> [1, -1]
im = cv2.flip(im, 0)
elif 5 == orientation: # LEFT-TOP, Rotate 90 and flip left-right
im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
im = cv2.flip(im, 1)
elif 6 == orientation: # RIGHT-TOP, Rotate 90
im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
elif 7 == orientation: # RIGHT-BOTTOM,
im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
im = cv2.flip(im, 0)
else: # 8 == orientation: # LEFT-BOTTOM, Rotate 270
im = cv2.rotate(im, cv2.ROTATE_90_COUNTERCLOCKWISE)
return im