Movie Mood & Tone with Palette ลองใช้จานสีสร้างดูเล่นๆ

Android Apr 19, 2019

บล็อกก่อนมีคนถามว่าเรื่อง Palette โอเค งั้นเรามา re-write ของเดิมให้จบดีกว่า

Titanic (1997) dir. James Cameron , ref: https://twitter.com/CINEMAPALETTES/status/623518953973919744 ; ตอนแรกจะเลือกหนังที่ชอบ เลื่อนดูแล้ว เลือกหนังที่เคยดูจะง่ายกว่ากันเยอะ

เท่าที่เราดูภาพเล่นๆ น่าจะไม่เหมือนที่ Palette generate สีหรือเปล่านะ 555 แอปตัวอย่างในบล็อกนี้ คือ มีรูปจากหนัง แล้วให้มัน generate สีจาก Palette มาให้ ดูสิว่าจะตรง mood & tone หรือไม่

มาทำความรู้จักเจ้า Palette กันก๊อนนนน

palette เป็นหนึ่งใน library ของทางฝั่ง Android เอง โดยการเพิ่มเจ้านี่ลงไปใน dependency

implementation 'com.android.support:palette-v7:28.0.0'

Palette | Android Developers
Synchronous Palette p = Palette.from(bitmap).generate(); // Asynchronous Palette.from(bitmap).generate(new…developer.android.com

ซึ่งไม่น่ามีใครเอ๊ะใจอะไร เนื่องจากตัวอย่างเราใช้เจ้า Android Support 28.0.0 ดังนั้นเทียบเท่ากับ AndroidX 1.0.0 นั่นเอง

implementation 'androidx.palette:palette:1.0.0'

ส่วน Document ที่เกี่ยวกับเจ้า Palette นั้น ก็น่าจะตัวนี้แหละ เพราะใน AndroidX ไม่ได้เขียนไว้

Selecting Colors with the Palette API | Android Developers
The palette library is a support library that extracts prominent colors from images to help you create visually engaging apps.

หลักการทำงานคร่าวๆ คือ เอารูปมารูปนึง ที่เป็น bitmap มาทำการ generate โดยเราสามารถดึง color profile ที่ Palette generate มาได้ ดังนี้

  • Vibrant : getVibrantColor()
  • Vibrant Dark : getDarkVibrantColor()
  • Vibrant Light : getLightVibrantColor()
  • Muted : getVibrantColor()
  • Muted Dark : getDarkVibrantColor()
  • Muted Light : getLightVibrantColor()

แต่จริงๆแล้วเจ้า Palette นาง Swatches สีทั้งหมดมาให้ 16 สี โดยเราสามารถนำไปใช้โดยการ getSwatches() ซึ่งหนุ่มๆไม่ต้องกังวลเวลาสาวขอแขนมา Swatches สีลิปสติก เอ้ยผิดๆๆๆๆๆ ><

Android – Pick Colors from Image Color Palette
Extracting Colors to a Palette with Android Lollipop - Digital product development agency | Big Nerd Ranch
Editor’s Note:n This post has been updated since its initial release. The generate(Bitmap) andgenerate(Bitmap, PaletteAsyncListener) methods have been deprecated in favorof a builder static method on the Palette class. The code listings in thispost now use the new Palette functionality.

การใช้งาน Palette

ก่อนอื่นมาสร้าง instance ของ Palette กันก่อน ซึ่งรองรับการทำงานทั้ง synchronous และ asynchronous

// Generate palette synchronously and return it
fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate()

// Generate palette asynchronously and use it on a different
// thread using onGenerated()
fun createPaletteAsync(bitmap: Bitmap) {
    Palette.from(bitmap).generate { palette ->
        // Use generated instance
    }
}

คำถามจากทางบ้านเมื่อคราวนั้น รวมไปถึงพี่เอกก็ทักตอนตรวจดราฟ ว่าทำไมไม่ใช้ palette generate สีให้เลยหล่ะ ตอนนี้เริ่มได้คำตอบนึงแล้วว่า มันรับ input เป็น bitmap มา generate สีให้เรา แล้วคำถามต่อไปว่า จะทำยังไงให้เป็น bitmap หล่ะ ในกรณีของ

  • ถ้าใส่เป็นสีหล่ะ ทำงานได้ไหม?

ก่อนอื่นต้องแปลงเป็น bitmap เสียก่อน แล้วจะแปลงยังไง google it แล้วพบอันนี้

How do i convert to Color to Bitmap?
I have a color in form of integer, and i want that color to be in a Bitmap form.Is there any way to do so? I tried Drawable d = new ColorDrawable(Color.parseColor(”#ffffff”));Bitmap b = ((

แล้วใส่ไปแบบนี้

val bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(ContextCompat.getColor(this, R.color.colorBg))

จากนั้นเอาเข้าไปใน Palette ซึ่งเอาตัวอย่างจากใน Document มา

Palette.from(bitmap).generate { palette ->
    textview.setTextColor(palette?.vibrantSwatch!!.titleTextColor)
}

ผลที่ได้คือ อื้มมม แบบนี้นี่เองง แต่ไม่ตรงทุกอันแหะ อันนี้ต้องไป work ต่อเอาเองว่าอันไหนจะได้สีตัวหนังสือที่เราต้องการจริงๆ แต่จริงๆสีตัวหนังสือมันไม่ออกขาวดำเลย มันเป็นสีๆไง

อธิบายเพิ่มเติม แต่ละ swatch นั้น สามารถดึง rgb, hsl, population รวมไปถึง title และ body text color ได้ด้วย มิน่าาา ทำไมถึงทักกันว่าทำไมไม่ใช่ Palette คือตอนแรกก็นึกว่าทำได้เฉพาะรูปอย่างเดียวซะอีก ฮ่าาาๆๆๆ

  • แล้ว drawable ที่เป็นรูปต้องแปลงเป็น bitmap ก่อน?

คราวนี้เราจะลองให้แสดงรูปต้นแบบด้านบน และสีที่ได้ด้านล่างเนอะ พร้อมชื่อของมันไปเลยจ้า การทำ layout ในตอนนี้ขอถึกนิดนึง คือสร้าง TextView มา 7 ตัว พร้อมใส่แต่ละ swatch จ้า

  • เจ้า drawable นั้น สามารถ get แบบปกติโดยใช้ ContextCompat และแปลงเป็น BitmapDrawable โดย get bitmap มาอีกที
(ContextCompat.getDrawable(this, R.drawable.sample) as BitmapDrawable).bitmap
  • แต่ละ swatch ที่ได้นั้น เช่น palette?.darkMutedSwatch output ที่ได้คือ Palette.Swatch ดังนั้นเราจะไปใช้ตรงๆในการ set color ต่างๆไม่ได้นะจ๊ะ
  • การนำสีแต่ละ swatch ไปใช้นั้น จะต้องห้อยด้วย .rgb เสมอ เช่น palette.darkMutedSwatch!!.rgb
  • แน่นอนว่าพวก text color จะมี 2 ตัวให้ใช้ คือ titleTextColor ( palette?.darkMutedSwatch!!.titleTextColor ) กับ bodyTextColor ( palette?.darkMutedSwatch!!.bodyTextColor ) ห้อยท้ายนั่นเอง

ดังนั้นผลที่ได้จะเป็นแบบนี้

  • แล้วถ้ารูปมาจาก url เราต้องให้ method ของ library นั้นๆทำให้เป็น bitmap

เราใช้ Library Fresco ในการดึงภาพจาก url ซึ่งจริงๆแล้วใช้ตั้งแต่ตัวอย่างที่แล้วแล้วแหละ 55555

ความเดิมตอนที่แล้ว

ทดลองใช้ Fresco, Library Image สุดจี้ดจาก Facebook Open Source
เบื่อ Gilde ที่ใช้ยากขึ้นทุกวัน งั้นขอลองใช้ของใหม่ดูสิว่าจะยังไงดี

แต่ความยากเพิ่มขึ้นคือ ต้องทำให้เป็น Bitmap กับรูปตัวอย่างของเรา ซึ่งมันแอบไม่สอดคล้องกับความตั้งใจของเจ้า Fresco เท่าไหร่นัก 555

เท่าที่ดูมี 2 ways คือ ใช้ pipeline ใน Fresco กับ ดึงจาก connection ยัดเข้า InputStream แล้วได้ Bitmap มา ซึ่งซับซ้อนน้อยกว่าวิธีแรก งั้นลอง way ที่สองเนอะ

ข้อควรระวัง ใส่ async ด้วยไม่งั้นมันจะ crash นะเออ ซึ่งใส่ async ได้สองแบบ

แบบแรกแบบ สร้าง class AsyncTask

การเรียกใช้จะเป็นแบบนี้

AsyncGettingBitmapFromUrl().execute(url).get()

แบบที่สอง ใช้ Coroutines

ก่อนอื่นเข้าไปเพิ่มใน dependency

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

จากนั้นสร้าง function get bitmap จาก image url มา ซึ่งเหมือนข้างบน

private fun getBitmapFromUrl(src: String): Bitmap {
    val url = URL(src)
    val connection = url.openConnection() as HttpURLConnection
    connection.doInput = true
    connection.connect()

    val input = connection.inputStream
    return BitmapFactory.decodeStream(input)
}

วิธีการใช้งาน

GlobalScope.async {
    createPaletteAsync(getBitmapFromUrl(url))
}

ซึ่งจะเขียนเรื่อง coroutine ทีหลังเนอะ :D

แต่เราก็หนี crash ไม่พ้น พอลอง debug เหมือนบางสีมันไม่มีให้ง่ะ ดังนั้นอย่าลืมดักด้วย

เพราะรูปตัวอย่างมันได้สีมาแค่นี้ใช่ไหม แต่ 16 สีมันดันมาครบไง

Mood & Tone ซีนในตำนานของ Girls don’t cry และเป็นซีนที่เป็น ref ในการเกรดสีหนัง ว่าให้เห็นหยดนํ้าตาน้องๆชัดๆ สุดท้ายเลยสีนี้มาที่เราเห็นนั่นแหละ //โดนซีนในตำนานของโอชิเล่นเฉยย

งั้นลองเอา Mood & Tone ที่เราเห็นๆตามเว็บมาลองดูสักหน่อย

สุดท้ายกับการโชว์ swatch ทั้ง 16 สี ก็ดูจะค่อนข้างตรงบ้างเนอะ ในบางสี 555

ส่วนอันนี้สีเยอะเฉ้ยยย เท่าที่ดูเนี่ย สีแต่ละ swatch ก็อยู่ใน swatch ที่เป็น list อีกที

การประยุกต์ใช้ สามารถเอาสีใน Palette ไปใส่ตอน loading รูป เห็นหลายๆแอปชอบทำกัน เช่น Pinterest

ที่ทำไปก็ไม่แน่ใจว่า เขาหาสี Mood & Tone ของหนังแต่ละเรื่องยังไง เพราะของเขามีกัน 10 สี ของเราเนี่ยมีสีอะไรบ้าง 7 + 16 สีอ่ะ งั้นลองอ่านอันนี้ดู มีหลายองค์ประกอบเลยนะเนี่ย

Filmmaking: Using Colour in Your Movie

ส่วนอันนี้ละเอียดจนล้องห้ายยย มันยาวมาก

How to Use Color in Film: 50+ Examples of Movie Color Palettes
In this post, we are analyzing the overall psychological effects of color in film and how you can tell better stories. Free e-book on color included!

Reference รูปเผื่ออยากเอาไปเล่นกัน :

Color Palettes From Famous Movies Show How Colors Set The Mood Of A Film
In The Mood For Love (2000, Wong Kar Wai) / Cinematography by Christopher Doyle, Pung-Leung Kwan, Ping Bin Lee | Movie color palette, Cinema colours, Color in film
In The Mood For Love (2000, Wong Kar Wai) / Cinematography by Christopher Doyle, Pung-Leung Kwan, Ping Bin Lee

วันดีคืนดีอาจจะมีคนแชร์โพสประมาณนี้ใน Facebook :)


โค้ดทั้งหมดอยู่ในนี้ มาส่องกันได้จ้า

mikkipastel/MoviePalette
Generate Mood & Tone of Movie by Palette. Contribute to mikkipastel/MoviePalette development by creating an account on GitHub.

ถ้ามีเวลาว่างๆจะตัดซีนหนังจากลิ้งด้านบนมาให้ swatch สีนะ น่าสนุกดี :D


สุดท้ายฝากร้านกันสักนิด ฝากเพจด้วยนะจ๊ะ

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, December 10, 2017

Tags

Minseo Chayabanjonglerd

I am a full-time Android Developer and part-time contributor with developer community and web3 world, who believe people have hard skills and soft skills to up-skill to da moon.