ทำไมรูปใน WordPress ถึงเบลอหลังอัพโหลด (พร้อมวิธีแก้)
เก้าในสิบครั้ง รูปของคุณไม่ได้เบลอจริง ๆ หรอก — WordPress ย่อขนาดมันตอนอัพโหลดแล้วเสิร์ฟไฟล์ที่ถูกจำกัดขนาดออกมาแทน ตั้งแต่ WordPress 5.3 เป็นต้นมา รูปใด
เผยแพร่แล้ว
เก้าในสิบครั้ง รูปของคุณไม่ได้เบลอจริง ๆ หรอก — WordPress ย่อขนาดมันลงตอนอัพโหลดและตอนนี้กำลังเสิร์ฟไฟล์ก็อปปี้ที่ถูกจำกัดขนาดออกมาแทน ตั้งแต่ WordPress 5.3 เป็นต้นมา รูปที่มีด้านกว้างหรือด้านสูงเกิน 2560px จะถูกแทนที่แบบเงียบ ๆ ด้วยเวอร์ชัน -scaled ที่จำกัดด้านที่ยาวที่สุดไว้ที่ 2560px และไฟล์ที่เล็กลงนี้เองที่ธีมของคุณเอาไปยืดให้เต็ม hero, บล็อกแบบเต็มความกว้าง หรือจอ retina วิธีแก้คือพิสูจน์ให้ได้ก่อนว่าเกิดเรื่องนี้ขึ้นจริง แล้วค่อยเลือกว่าจะเพิ่มค่า threshold หรือเลิกอัพโหลดรูปที่ต้องใหญ่กว่ากล่องที่มันจะไปวางอยู่
ทำไมถึงเกิดขึ้น
เวลาคุณอัพโหลดรูป WordPress จะรัน wp_create_image_subsizes() (อยู่ใน wp-admin/includes/image.php) ถ้าด้านที่ยาวที่สุดเกินค่า big_image_size_threshold — ค่าเริ่มต้นคือ 2560px — มันจะเรียก _wp_image_meta_replace_original(), สร้างไฟล์ your-photo-scaled.jpg ขึ้นมา แล้วเขียนทับ metadata ของ attachment เพื่อให้ขนาด full ชี้ไปยังก็อปปี้ที่ถูกย่อแทน ไฟล์ต้นฉบับจริงของคุณยังถูกเก็บไว้บนดิสก์ในชื่อ your-photo.jpg และอ้างอิงผ่าน wp_get_original_image_path() แต่ไม่มีอะไรบนหน้าเว็บที่เสิร์ฟมันออกมาเลย ทุกขนาดกลาง (intermediate) และทุก candidate ใน srcset ล้วนถูกสร้างขึ้น จากไฟล์ scaled ขนาด 2560px ไม่ใช่จากไฟล์ที่คุณอัพโหลดเข้าไป
นี่แหละที่มาของความเบลอ คุณอัพโหลดรูปคมชัดขนาด 4000px เพื่อทำ header แบบเต็มขอบ WordPress จำกัดมันไว้ที่ 2560px บนจอทั่วไปในกล่องกว้าง 1600px ก็ไม่มีปัญหาอะไร แต่บนจอ retina 2x เบราว์เซอร์ต้องการพิกเซลจริงราว ๆ 3200 พิกเซลเพื่อเติมกล่องนั้นให้คมชัด แต่มีอยู่แค่ 2560 แล้วก็อัพสเกลส่วนที่ขาดขึ้นมาเอง ผลคือขอบนุ่มเบลอ ตัวหนังสือในรูปเลอะ ๆ ตรงกับอาการ “เบลอหลังอัพโหลด” เป๊ะ ๆ
อีกครึ่งหนึ่งของปัญหาเดียวกันนี้คือ srcset เลือกขนาดที่เล็กเกินไป ถ้าธีมของคุณรายงานค่า content width ที่ไม่ตรงกับกล่องที่ถูกเรนเดอร์จริง WordPress จะยื่นไฟล์กลางอย่าง -1024x683 หรือ -1536x1024 ให้เบราว์เซอร์ แล้วมันก็ถูกยืดขึ้นมา สาเหตุเดียวกัน — กล่องแสดงผลใหญ่กว่าพิกเซลที่มี — แต่จุดที่ทำให้เกิดต่างกัน
ตรวจดูว่า WordPress เสิร์ฟอะไรออกมาจริง ๆ
อย่าเดา ให้คลิกขวาที่รูปที่เบลอ เปิดในแท็บใหม่ แล้วดูชื่อไฟล์ใน URL ถ้ามันลงท้ายด้วย -scaled.jpg หรือมี suffix บอกขนาดอย่าง -1024x683.jpg ก็ยืนยันได้เลยว่า เบราว์เซอร์กำลังเรนเดอร์ไฟล์ที่ถูกย่อขนาดลงมา ไม่ใช่ไฟล์ที่คุณอัพโหลด คุณยัง inspect element แล้วอ่านค่า currentSrc เพื่อดูได้ด้วยว่าเบราว์เซอร์เลือก candidate ตัวไหนกันแน่
ถ้าอยากเห็นภาพรวมทั้งหมดก่อนจะอัพโหลดรูปใหม่ ให้ลากรูปเข้าไปใน เครื่องมือดูขนาดรูป WordPress — มันจะแสดงทุกไฟล์ที่ WordPress จะสร้างจากไฟล์นั้น ๆ รวมถึงว่าจะมีการสร้างก็อปปี้ -scaled ขึ้นมาไหมและที่ขนาดเท่าไหร่ คุณจะได้รู้ล่วงหน้าว่าไฟล์ต้นฉบับของคุณใหญ่พอกับที่ที่จะเอาไปวางหรือเปล่า
บนเซิร์ฟเวอร์ คุณสามารถ list ทุกไฟล์ที่ถูกจำกัดขนาดได้ด้วยคำสั่งนี้
find wp-content/uploads -name '*-scaled.*'
วิธีแก้ ทำตามลำดับ
1. ถ้ารูปของคุณจำเป็นต้องใหญ่กว่า 2560px จริง ๆ (hero ขนาดใหญ่, retina, แกลเลอรีคุณภาพระดับพิมพ์) ให้เพิ่มค่า threshold
// functions.php or a small mu-plugin
add_filter( 'big_image_size_threshold', function () {
return 3840; // longest edge, in pixels
} );
หรือปิดการจำกัดขนาดไปเลยทั้งหมด
add_filter( 'big_image_size_threshold', '__return_false' );
2. อัพโหลดรูปที่มีปัญหาใหม่อีกครั้ง นี่คือขั้นตอนที่คนมักจะข้าม การเปลี่ยนค่า threshold มีผลกับการอัพโหลด ใหม่ เท่านั้น รูปที่อยู่ในไลบรารีอยู่แล้วยังคงเก็บ metadata เดิมไว้ และการ regenerate thumbnails ก็แค่สร้างขนาดกลางขึ้นใหม่จากไฟล์ -scaled ที่ถูกจำกัดขนาดไปแล้ว — มันไม่ได้เพิ่มความละเอียดที่ถูกทิ้งไปกลับคืนมา ทางที่ได้ผลจริงคือ เปลี่ยน filter, ลบ attachment, แล้วอัพโหลดใหม่
3. ถ้าไฟล์ต้นฉบับของคุณเล็กกว่าหรือเท่ากับ 2560px อยู่แล้วแต่ยังเบลอ ปัญหาไม่ได้อยู่ที่ threshold — แต่กล่องแสดงผลใหญ่กว่ารูป ให้อัพโหลดไฟล์ต้นฉบับที่ใหญ่ขึ้น หรือย่อกล่องให้เล็กลง สำหรับความคมชัดระดับ retina ไฟล์ต้นฉบับของคุณต้องมีความกว้างราว ๆ สองเท่าของความกว้างในหน่วย CSS pixel ของกล่องที่มันไปเติม
4. ค่อย regenerate thumbnails หลังทำข้างบนเสร็จแล้วเท่านั้น เพื่อให้ขนาดกลางสอดคล้องกัน — แต่ต้องเข้าใจว่านี่คือการเก็บกวาด ไม่ใช่ยารักษา
สิ่งที่ไม่ควรทำ
อย่าดัน JPEG quality ขึ้นไปที่ 100 WordPress บีบอัดที่ค่า quality เริ่มต้น 82 ผ่าน wp_editor_set_quality และคำแนะนำครึ่งหนึ่งบนเน็ตก็บอกให้คุณ override มัน
add_filter( 'wp_editor_set_quality', function () { return 90; } );
แบบนั้นก็โอเคสำหรับลด artifact จากการบีบอัด แต่รูปที่ถูกยืดและอัพสเกลเป็นปัญหาเรื่อง ความละเอียด ไม่ใช่เรื่องการบีบอัด การเปลี่ยนจาก 82 ไป 100 ทำให้ไฟล์บวมขึ้นและแทบไม่ช่วยอะไรกับความเบลอที่คุณเห็นเลย
อย่าปิด -scaled แบบสะท้อนกลับอัตโนมัติ การปิดการจำกัดขนาด (มีเครื่องมือสำหรับเรื่องนี้) เป็นทางเลือกที่ถูกต้อง ถ้า คุณเสิร์ฟรูปที่ใหญ่กว่า 2560px — แต่ถ้าปัญหาจริงของคุณคือไฟล์กลางที่เล็กเกินไปถูกยืด การปิดมันก็ไม่เปลี่ยนอะไรเลยและคุณยังเสียการประหยัด bandwidth ไปเปล่า ๆ วินิจฉัยให้ชัดก่อน
อย่าโทษ cache หรือ regenerate thumbnails เป็นอย่างแรก การ regenerate อ่านจากไฟล์ต้นทางที่ถูกจำกัดขนาดตัวเดียวกัน มันจึงคืนรายละเอียดกลับมาไม่ได้ การล้าง CDN หรือ page cache ก็ไม่ช่วยอะไรกับไฟล์ที่มันเล็กบนดิสก์มาตั้งแต่แรก
อย่าไปพึ่ง CSS ของธีมหรือ object-fit ไม่มีการจัดสไตล์แบบไหนที่เพิ่มพิกเซลได้ ถ้าไฟล์ที่เสิร์ฟออกมาลงท้ายด้วย -scaled หรือมี suffix บอกขนาด ปัญหาอยู่ที่ไฟล์ ไม่ใช่ layout
ยังแก้ไม่ได้อีก?
ถ้าคุณยืนยันแล้วว่าไฟล์ที่เสิร์ฟออกมาคือไฟล์ที่คุณอัพโหลดแบบเต็มความละเอียด — ไม่มี -scaled, ไม่มี suffix บอกขนาด — แต่มันก็ยังนุ่มเบลออยู่ ให้ลองเช็คว่ามีปลั๊กอิน wordpress (พวก optimizer, CDN image-resizer หรือไลบรารี lazy-load) กำลังเขียนทับค่า src ของคุณให้ชี้ไปยัง proxy ที่ถูกบีบอัดหรือเปล่า ลองรันรูปผ่าน เครื่องมือดูขนาดรูป เพื่อยืนยันว่า WordPress ควรจะ สร้างอะไรออกมา แล้วเทียบกับสิ่งที่เบราว์เซอร์โหลดมาจริง เมื่อสองอย่างนี้ไม่ตรงกัน แสดงว่ามีบางอย่างระหว่าง WordPress กับเบราว์เซอร์ที่เป็นตัวการ
FAQ
คำถาม
ทำไมรูปใน WordPress ถึงเบลอหลังอัพโหลด?
มีความเป็นไปได้สูงสุดว่า WordPress ย่อขนาดไฟล์ลงตอนอัพโหลด ตั้งแต่ WordPress 5.3 เป็นต้นมา รูปที่มีด้านกว้างหรือด้านสูงเกิน 2560px จะถูกแทนที่แบบเงียบ ๆ ด้วยก็อปปี้ -scaled ที่จำกัดด้านที่ยาวที่สุดไว้ที่ 2560px และไฟล์ที่เล็กลงนั้นเองที่ธีมของคุณเอาไปยืดให้เต็ม hero, บล็อกเต็มความกว้าง หรือจอ retina
-scaled ในชื่อไฟล์รูปของ WordPress หมายความว่าอะไร?
หมายความว่า WordPress จำกัดไฟล์ที่อัพโหลดไว้ที่ 2560px บนด้านที่ยาวที่สุด และกำลังเสิร์ฟก็อปปี้ที่เล็กลงแทนไฟล์ต้นฉบับของคุณ ไฟล์ต้นฉบับจริงยังอยู่บนดิสก์แต่ไม่มีอะไรบนหน้าเว็บที่เสิร์ฟมันออกมา และทุกขนาดกลางกับทุก candidate ใน srcset ล้วนถูกสร้างจากไฟล์ scaled ขนาด 2560px
จะหยุดไม่ให้ WordPress ย่อรูปที่ใหญ่กว่า 2560px ได้อย่างไร?
เพิ่ม filter บน big_image_size_threshold ใน functions.php หรือใน mu-plugin เล็ก ๆ แล้วคืนค่าที่ใหญ่กว่า เช่น 3840 หรือคืน __return_false เพื่อปิดการจำกัดขนาดไปเลย วิธีนี้มีผลกับไฟล์ที่อัพโหลดใหม่เท่านั้น ดังนั้นให้ลบแล้วอัพโหลดรูปที่อยู่ในคลังอยู่แล้วเข้าไปใหม่
การ regenerate thumbnail แก้รูปเบลอใน WordPress ได้ไหม?
ไม่ได้ การสร้างใหม่จะสร้างขนาดกลางขึ้นมาจากไฟล์ -scaled ตัวเดิมที่ถูกจำกัดขนาดไปแล้ว มันจึงเพิ่มความละเอียดที่ถูกทิ้งไปแล้วกลับมาไม่ได้ ทางที่ได้ผลจริงคือเปลี่ยนค่า filter ของ threshold ลบ attachment นั้นแล้วอัพโหลดใหม่ ส่วนการ regenerate thumbnail ให้ถือเป็นการเก็บกวาด ไม่ใช่การรักษา
การเพิ่มคุณภาพ JPEG ทำให้รูปใน WordPress คมขึ้นไหม?
ไม่ อย่างน้อยก็ไม่ใช่ตอนที่รูปกำลังถูกยืด WordPress บีบอัดที่คุณภาพเริ่มต้น 82 ผ่าน wp_editor_set_quality และการเพิ่มค่านั้นช่วยลดได้แค่ artifact จากการบีบอัด รูปที่ถูกอัพสเกลคือปัญหาเรื่องความละเอียด การขยับจาก 82 ไป 100 จึงทำให้ไฟล์บวมขึ้นและแทบไม่ช่วยเรื่องความเบลอเลย