Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Bitmap Remapping (Scripting Tool)

Bitmap Remapping
v1.2

Introduction


As I told Zeriab earlier today, I had the idea for this script long ago, when I was modding Command & Conquer - Operation Tiberian Sun. That game used specific shades of red as remapable colors to use with the respective player colors to make units and buildings look individual for each player. This script isn't an exact translation in any way really, but yeah.. that's where I got the idea from.
The purpose of this script is simple... imagine you have a range of colors of the same make (aka dark red, with shading variations) and you'd rather have dark blue, but as you know as a spriter, changing the hue doesn't always do the trick, and as you know as a scripter, doing things with scripts is way cooler anyway. Oh, and last but not least, as you know as a game designer: Having only one sprite for nearly unlimited variations without additional save space needed is great stuff.


Features


  • Pre-defined palettes for instant use with Photoshop-swatches sprited resources
  • Exchange whatever range of colors with any other within the default RGB(A) range
  • Adjust the script to your spriting needs by adding own palettes with ease
  • Modify Alpha values for individual pixels by array input



Script


[rgss]#==============================================================================
# Bitmap Remapping                                                         v1.2
#------------------------------------------------------------------------------
# Script by BlueScope
#==============================================================================
 
class Bitmap
  #--------------------------------------------------------------------------
  def remap(remap_color, new_color, remap_alpha=255, new_alpha=255)
    mapping = colorset(remap_color, remap_alpha)
    replace = colorset(new_color, new_alpha)
    if mapping.size <= replace.size
      for x in 0..self.width
        for y in 0..self.height
          for i in 0...mapping.size
            if self.get_pixel(x, y) == mapping
              self.set_pixel(x, y, replace)
            end
          end
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  def colorset(id, alpha)
    if alpha.is_a?(Integer) or alpha.size < 5
      alpha = [alpha, alpha, alpha, alpha, alpha]
    end
    case id
    when 0 # Skin Color
      color = [Color.new(254, 254, 254, alpha[0]),
               Color.new(255, 217, 173, alpha[1]),
               Color.new(235, 179, 133, alpha[2]),
               Color.new(212, 140, 82, alpha[3]),
               Color.new(117, 62, 45, alpha[4])]
    when 1
      color = [Color.new(242, 154, 121, alpha[0]),
               Color.new(235, 102, 69, alpha[1]),
               Color.new(227, 0, 26, alpha[2]),
               Color.new(157, 13, 21, alpha[3]),
               Color.new(121, 14, 17, alpha[4])]
    when 2
      color = [Color.new(247, 179, 131, alpha[0]),
               Color.new(241, 143, 78, alpha[1]),
               Color.new(233, 93, 15, alpha[2]),
               Color.new(162, 67, 17, alpha[3]),
               Color.new(124, 51, 14, alpha[4])]
    when 3
      color = [Color.new(252, 203, 140, alpha[0]),
               Color.new(248, 179, 86, alpha[1]),
               Color.new(243, 148, 0, alpha[2]),
               Color.new(168, 104, 4, alpha[3]),
               Color.new(128, 80, 7, alpha[4])]
    when 4
      color = [Color.new(255, 246, 155, alpha[0]),
               Color.new(255, 241, 95, alpha[1]),
               Color.new(255, 237, 0, alpha[2]),
               Color.new(180, 165, 0, alpha[3]),
               Color.new(136, 126, 0, alpha[4])]
    when 5
      color = [Color.new(208, 224, 153, alpha[0]),
               Color.new(185, 209, 101, alpha[1]),
               Color.new(151, 191, 13, alpha[2]),
               Color.new(103, 135, 19, alpha[3]),
               Color.new(77, 104, 17, alpha[4])]
    when 6
      color = [Color.new(177, 211, 152, alpha[0]),
               Color.new(136, 191, 103, alpha[1]),
               Color.new(65, 166, 42, alpha[2]),
               Color.new(39, 118, 33, alpha[3]),
               Color.new(24, 91, 26, alpha[4])]
    when 7
      color = [Color.new(144, 199, 151, alpha[0]),
               Color.new(71, 173, 104, alpha[1]),
               Color.new(0, 144, 54, alpha[2]),
               Color.new(0, 103, 41, alpha[3]),
               Color.new(0, 80, 31, alpha[4])]
    when 8
      color = [Color.new(138, 204, 199, alpha[0]),
               Color.new(48, 179, 173, alpha[1]),
               Color.new(0, 151, 144, alpha[2]),
               Color.new(0, 107, 102, alpha[3]),
               Color.new(0, 82, 79, alpha[4])]
    when 9
      color = [Color.new(132, 208, 241, alpha[0]),
               Color.new(0, 185, 233, alpha[1]),
               Color.new(0, 158, 225, alpha[2]),
               Color.new(0, 111, 159, alpha[3]),
               Color.new(0, 84, 122, alpha[4])]
    when 10
      color = [Color.new(139, 174, 216, alpha[0]),
               Color.new(72, 141, 199, alpha[1]),
               Color.new(0, 106, 179, alpha[2]),
               Color.new(0, 74, 127, alpha[3]),
               Color.new(0, 55, 98, alpha[4])]
    when 11
      color = [Color.new(142, 154, 201, alpha[0]),
               Color.new(87, 115, 178, alpha[1]),
               Color.new(0, 74, 153, alpha[2]),
               Color.new(0, 51, 110, alpha[3]),
               Color.new(0, 36, 84, alpha[4])]
    when 12
      color = [Color.new(144, 133, 186, alpha[0]),
               Color.new(97, 86, 157, alpha[1]),
               Color.new(23, 41, 131, alpha[2]),
               Color.new(15, 27, 95, alpha[3]),
               Color.new(13, 15, 73, alpha[4])]
    when 13
      color = [Color.new(171, 140, 188, alpha[0]),
               Color.new(138, 91, 157, alpha[1]),
               Color.new(98, 33, 129, alpha[2]),
               Color.new(70, 21, 93, alpha[3]),
               Color.new(54, 3, 71, alpha[4])]
    when 14
      color = [Color.new(197, 147, 190, alpha[0]),
               Color.new(174, 96, 158, alpha[1]),
               Color.new(147, 17, 126, alpha[2]),
               Color.new(105, 8, 90, alpha[3]),
               Color.new(81, 0, 69, alpha[4])]
    when 15
      color = [Color.new(241, 159, 193, alpha[0]),
               Color.new(234, 105, 160, alpha[1]),
               Color.new(227, 0, 122, alpha[2]),
               Color.new(160, 0, 87, alpha[3]),
               Color.new(124, 0, 66, alpha[4])]
    when 16
      color = [Color.new(242, 157, 160, alpha[0]),
               Color.new(235, 104, 120, alpha[1]),
               Color.new(227, 0, 79, alpha[2]),
               Color.new(159, 0, 56, alpha[3]),
               Color.new(122, 3, 42, alpha[4])]
    when 17
      color = [Color.new(206, 188, 165, alpha[0]),
               Color.new(163, 144, 124, alpha[1]),
               Color.new(125, 105, 90, alpha[2]),
               Color.new(89, 73, 63, alpha[3]),
               Color.new(56, 48, 43, alpha[4])]
    when 18
      color = [Color.new(204, 166, 116, alpha[0]),
               Color.new(175, 133, 84, alpha[1]),
               Color.new(149, 105, 57, alpha[2]),
               Color.new(125, 80, 36, alpha[3]),
               Color.new(103, 59, 21, alpha[4])]
    else
      color = [Color.new(254, 254, 254, alpha[0]),
               Color.new(192, 192, 192, alpha[1]),
               Color.new(128, 128, 128, alpha[2]),
               Color.new(64, 64, 64, alpha[3]),
               Color.new(1, 1, 1, alpha[4])]
    end
    return color
  end
  #--------------------------------------------------------------------------
end
[/rgss]


Instructions


First, you should know about the palettes... I included 20 pre-defined ones, referenced to by an index number. Here are your options:

  • 0 :: RMVX's default skin color
  • 1-18 :: The default Adobe Photoshop swatches palettes (image below)
  • > 18 :: hard grayscale


remapsheetxp1.png


Of course, you can - and should - add own palettes to the list. You alternatively can modify the sprites you're using to your needs. A combination of both will ultimately make this script powerful to you. If you want to advance the palettes I gave ya, you can do that... you can add as many colors to a palette as you want, as long as you keep their count equal between palettes. You can exchange a larger palette with a smaller one, but not vice versa - in the latter case, no color will be exchanged simply, but you don't get any error message shutting your game down.


It operates by switching out two palettes, so you don't need to do anything else than giving the method two values. Syntax is the following:

Code:
@sprite = Sprite.new

@sprite.bitmap = ...

@sprite.bitmap.remap(remap_color, new_color)

So if, for example, your sprite has hair colored with the colors from palette #1, but you want them to be blue like palette #10, you use @sprite.bitmap.remap(1, 10) - as soon as you have your resources and palettes, it's easy as hell.

What you can also do is give specific alpha values. With that, you can check for transparency values in colors, giving you a bit more of adjustability. All you need to do is change the last line given above like this:

Code:
@sprite.bitmap.remap(remap_color, new_color, remap_alpha, new_alpha)

Keep in mind that the last two values can be numbers from 0 to 255, as well as arrays with the size of 5. That means instead of a single number, you can use [60, 80, 100, 120, 140], giving the first color the alpha value 60, the second one 80, and so on.
Also, they have 255 as default value, so if you don't input anything, you just get the completely opaque pixels.


FAQ


Q: Will this script work for RMXP and RMVX alike?
A: I didn't test it, but it should run completely fine on either platform.

Q: This script is really slow on big graphics! What can I do?
A: You can try poccil's/BwdYeti's independent color remapping in the Script Snippets topic (somewhere on page 2) and merge it with my script. That shouldn't be hard to do, but personally, I prefer non-dll scripts, which is why there won't be a version of that in this topic.


Compatibility


Unless any other scripts have the same names as the ones in my script, it's perfectly compatible, as it's a simple add-on - no modified methods.


Thanks


...to Zeriab, for pointing out that I messed up the palette data at first


Terms and Conditions


You may use and/or modify this script in any way you want, and/or release your modifications, as long as you accept the following terms and conditions entirely.
You may not use this for commercial projects, profit-oriented projects, or projects that aren't meant to be sold, but otherwise aquire money (i.e. through donations). That is not limited to RPG Maker projects, but valid for all appliances. You may not remove or delete contents of the original header included in the script, but you may add your name if you made any changes.

The actual mentioning of my nickname in your release (i.e. in-media credits, printed pages or even a readme file) is not necessary, but much apprechiated.
 
This could be extrmely useful with a character creation system, if I remebmer how those work. You could easily make it where each individual portion of the character's body/clothing could have the color selected, without having to make a sprite for every one. In fact, this would be a very good addition to an online game too, because it makes it easier to give everyone a unique item. I haven't tried it, but, if it works like you say it does, good job!
 
Zeriab tried it, and he said it "works like a charm", if I might quote him here ^^ Also, that's exactly what I originally planned it to be for, before I figured I might as well make it a scripting tool for all bitmaps... and yeah, you can change as many colors as you want, for example for a charactersheet, so you can have a sprite with simultaneously remapable hair, skincolor, armor, sleeves, belt, legs, shoes, accessories, ... unlimited possibilities here. Oh, and there's tilesets, of course ;)
 
That would be very cool I must say for my GUI system Indeed, I was thinking in doing somthing like this, as I said to you :P. But well I have so many things in my hands that I decided to keep that for last, works great for what I tried =).

Nice work BlueScope!
 
This looks very nifty. I think I'm going to take this and run it through RPG::Cache when I build my character creation/visible equipment script.
 
@mew: Well, while that is the purpose of the script really, I surely don't need to tell ya that this method is highly resource-consuming, potentially rising by increasing dimensions of your bitmap. ^^"
 
Who would've thought it, but this script got updated. It's only a small change only a few people will need really, but it's still a cool thing: Alpha transparency access using the remap method - in other words, you can make sprites have different opacity levels. And all of that on the cost of only one more line and a few more words ^^

This was just my lunch break boredom ban, so I might release a v1.2 soon which is on my mind at the moment... I'm thinking about utilizing arrays as alpha values, so you can address each color by it's own. Ah well, lemme see about that. (EDIT: Screw that, I was just napping some minutes from my worktime to get this done... so yeah, v1.2 is up!)

Please tell me if you know anything else to add to this.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top