Page 1 of 1

[SOLVED] create an image and remap using a palette, the result image doesn't respect my palette

Posted: 2018-02-27T07:09:52-07:00
by Infrid
Hello,

thanks for ImageMagick, it's a marvellous tool, I am using it a lot!

I am opening this topic because I am translating a videogame and I need to create many BMP using a specific palette, those BMPs will be converted in the TIM format for the play station.

The BMP I am going to create is 4bbp with a specific palette from the game.

I manage to create an image from scratch and remap using my palette, but the result BMP doesn't have the palette in the right order.

Here the identify output from the file with the correct palette

Code: Select all

identify -verbose label-example.bmp 
Image: label-example.bmp
  Format: BMP3 (Microsoft Windows bitmap image (V3))
  Class: PseudoClass
  Geometry: 256x18+0+0
  Units: PixelsPerCentimeter
  Type: Grayscale
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 4/8-bit
  Channel depth:
    gray: 8-bit
  Channel statistics:
    Pixels: 4608
    Gray:
      min: 0 (0)
      max: 15 (0.972549)
      mean: 1.33017 (0.0886778)
      standard deviation: 3.34407 (0.222938)
      kurtosis: 5.58224
      skewness: 2.58414
      entropy: 0.344628
  Colors: 16
  Histogram:
      3768: (  0,  0,  0) #000000 gray(0)
       139: ( 24, 24, 24) #181818 gray(24)
        66: ( 48, 48, 48) #303030 gray(48)
        44: ( 64, 64, 64) #404040 gray(64)
        43: ( 80, 80, 80) #505050 gray(80)
        61: ( 96, 96, 96) #606060 gray(96)
        64: (112,112,112) #707070 gray(112)
        41: (128,128,128) #808080 gray(128)
        42: (136,136,136) #888888 gray(136)
        56: (152,152,152) #989898 gray(152)
        51: (168,168,168) #A8A8A8 gray(168)
        42: (184,184,184) #B8B8B8 gray(184)
        59: (200,200,200) #C8C8C8 gray(200)
        39: (216,216,216) #D8D8D8 gray(216)
        40: (232,232,232) #E8E8E8 gray(232)
        53: (248,248,248) #F8F8F8 gray(248)
  Colormap entries: 16
  Colormap:
         0: (  0,  0,  0) #000000 gray(0)
         1: ( 24, 24, 24) #181818 gray(24)
         2: ( 48, 48, 48) #303030 gray(48)
         3: ( 64, 64, 64) #404040 gray(64)
         4: ( 80, 80, 80) #505050 gray(80)
         5: ( 96, 96, 96) #606060 gray(96)
         6: (112,112,112) #707070 gray(112)
         7: (128,128,128) #808080 gray(128)
         8: (136,136,136) #888888 gray(136)
         9: (152,152,152) #989898 gray(152)
        10: (168,168,168) #A8A8A8 gray(168)
        11: (184,184,184) #B8B8B8 gray(184)
        12: (200,200,200) #C8C8C8 gray(200)
        13: (216,216,216) #D8D8D8 gray(216)
        14: (232,232,232) #E8E8E8 gray(232)
        15: (248,248,248) #F8F8F8 gray(248)
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: gray(255)
  Border color: gray(223)
  Matte color: gray(189)
  Transparent color: gray(0)
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 256x18+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: None
  Orientation: Undefined
  Properties:
    date:create: 2018-02-27T13:51:20+00:00
    date:modify: 2018-02-23T17:08:55+00:00
    signature: 4666e06822d1178735e9fff6174a8aa6d8418dbb8cd98440c8be66388ff85d3b
  Artifacts:
    filename: label-example.bmp
    verbose: true
  Tainted: False
  Filesize: 2.42KB
  Number pixels: 4.61K
  User time: 0.000u
  Elapsed time: 0:01.000
  Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
here the original tim file, just for completeness

Code: Select all

identify -verbose label-example.tim
Image: targhetta.tim
  Format: TIM (PSX TIM)
  Class: PseudoClass
  Geometry: 256x18+0+0
  Units: Undefined
  Type: Grayscale
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 8-bit
  Channel depth:
    gray: 8-bit
  Channel statistics:
    Pixels: 4608
    Gray:
      min: 0 (0)
      max: 255 (1)
      mean: 23.2368 (0.0911246)
      standard deviation: 58.4811 (0.229338)
      kurtosis: 5.58932
      skewness: 2.58592
      entropy: 0.344628
  Colors: 16
  Histogram:
      3768: (  0,  0,  0) #000000 gray(0)
       139: ( 24, 24, 24) #181818 gray(24)
        66: ( 49, 49, 49) #313131 gray(49)
        44: ( 66, 66, 66) #424242 gray(66)
        43: ( 82, 82, 82) #525252 gray(82)
        61: ( 99, 99, 99) #636363 gray(99)
        64: (115,115,115) #737373 gray(115)
        41: (132,132,132) #848484 gray(132)
        42: (140,140,140) #8C8C8C gray(140)
        56: (156,156,156) #9C9C9C gray(156)
        51: (173,173,173) #ADADAD gray(173)
        42: (189,189,189) #BDBDBD gray(189)
        59: (206,206,206) #CECECE gray(206)
        39: (222,222,222) #DEDEDE gray(222)
        40: (239,239,239) #EFEFEF gray(239)
        53: (255,255,255) #FFFFFF gray(255)
  Colormap entries: 16
  Colormap:
         0: (  0,  0,  0) #000000 gray(0)
         1: ( 24, 24, 24) #181818 gray(24)
         2: ( 49, 49, 49) #313131 gray(49)
         3: ( 66, 66, 66) #424242 gray(66)
         4: ( 82, 82, 82) #525252 gray(82)
         5: ( 99, 99, 99) #636363 gray(99)
         6: (115,115,115) #737373 gray(115)
         7: (132,132,132) #848484 gray(132)
         8: (140,140,140) #8C8C8C gray(140)
         9: (156,156,156) #9C9C9C gray(156)
        10: (173,173,173) #ADADAD gray(173)
        11: (189,189,189) #BDBDBD gray(189)
        12: (206,206,206) #CECECE gray(206)
        13: (222,222,222) #DEDEDE gray(222)
        14: (239,239,239) #EFEFEF gray(239)
        15: (255,255,255) #FFFFFF gray(255)
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: gray(255)
  Border color: gray(223)
  Matte color: gray(189)
  Transparent color: gray(0)
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 256x18+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: Undefined
  Orientation: Undefined
  Properties:
    date:create: 2018-02-23T17:10:46+00:00
    date:modify: 2018-02-23T17:08:37+00:00
    signature: 481aaa43e2c5e57ca4aaed7107f47fb99cce30e936a7af6daf05fda6d71d76f8
  Artifacts:
    filename: targhetta.tim
    verbose: true
  Tainted: False
  Filesize: 2.37KB
  Number pixels: 4.61K
  User time: 0.000u
  Elapsed time: 0:01.000
  Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
Here the command I use

Code: Select all

convert -size 256x18 xc:black -font "SteelfishRg-Regular" -fill "#f8f8f8" -pointsize 16 -draw "text 0,15 'The quick brown fox jumps over the lazy dog.'" -dither None -remap palette.bmp -depth 4 ppm:-| ppmtobmp -windows -bpp=4 > test-label.bmp 
and the result

Code: Select all

identify -verbose test-label.bmp 
Image: test-label.bmp
  Format: BMP3 (Microsoft Windows bitmap image (V3))
  Class: PseudoClass
  Geometry: 256x18+0+0
  Units: PixelsPerCentimeter
  Type: Grayscale
  Endianess: Undefined
  Colorspace: sRGB
  Depth: 4-bit
  Channel depth:
    gray: 4-bit
  Channel statistics:
    Pixels: 4608
    Gray:
      min: 0 (0)
      max: 15 (1)
      mean: 2.43468 (0.162312)
      standard deviation: 4.31004 (0.287336)
      kurtosis: 0.949765
      skewness: 1.55416
      entropy: 0.510921
  Colors: 16
  Histogram:
      3205: (  0,  0,  0) #000000 gray(0)
        92: ( 17, 17, 17) #111111 gray(17)
        77: ( 34, 34, 34) #222222 gray(34)
        93: ( 51, 51, 51) #333333 gray(51)
        56: ( 68, 68, 68) #444444 gray(68)
        75: ( 85, 85, 85) #555555 gray(85)
       155: (102,102,102) #666666 gray(102)
       133: (119,119,119) #777777 gray(119)
        73: (136,136,136) #888888 gray(136)
        68: (153,153,153) #999999 gray(153)
       119: (170,170,170) #AAAAAA gray(170)
       103: (187,187,187) #BBBBBB gray(187)
       129: (204,204,204) #CCCCCC gray(204)
        74: (221,221,221) #DDDDDD gray(221)
       135: (238,238,238) #EEEEEE gray(238)
        21: (255,255,255) #FFFFFF gray(255)
  Colormap entries: 16
  Colormap:
         0: (  0,  0,  0) #000000 gray(0)
         1: (255,255,255) #FFFFFF gray(255)
         2: (221,221,221) #DDDDDD gray(221)
         3: (187,187,187) #BBBBBB gray(187)
         4: (153,153,153) #999999 gray(153)
         5: (119,119,119) #777777 gray(119)
         6: ( 85, 85, 85) #555555 gray(85)
         7: ( 51, 51, 51) #333333 gray(51)
         8: ( 17, 17, 17) #111111 gray(17)
         9: (238,238,238) #EEEEEE gray(238)
        10: (204,204,204) #CCCCCC gray(204)
        11: (170,170,170) #AAAAAA gray(170)
        12: (136,136,136) #888888 gray(136)
        13: (102,102,102) #666666 gray(102)
        14: ( 68, 68, 68) #444444 gray(68)
        15: ( 34, 34, 34) #222222 gray(34)
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: gray(255)
  Border color: gray(223)
  Matte color: gray(189)
  Transparent color: gray(0)
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 256x18+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: None
  Orientation: Undefined
  Properties:
    date:create: 2018-02-27T14:02:51+00:00
    date:modify: 2018-02-27T14:02:51+00:00
    signature: cdffcc90077aca9126ae264711f877dacac90f87ccb47d84e8c924538685a2c8
  Artifacts:
    filename: test-label.bmp
    verbose: true
  Tainted: False
  Filesize: 2.42KB
  Number pixels: 4.61K
  User time: 0.000u
  Elapsed time: 0:01.000
  Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
  
I put the images here, so you can download and analyse, I know I am close to the solution but I cannot find a way to get the right palette!

Thanks

Infrid

Re: create an image and remap using a palette, the result image doesn't respect my palette

Posted: 2018-02-27T12:07:15-07:00
by snibgo
Infrid wrote:... but the result BMP doesn't have the palette in the right order.
IM can't do that. Gimp can.

Re: create an image and remap using a palette, the result image doesn't respect my palette

Posted: 2018-02-28T03:08:16-07:00
by Infrid
thanks for your reply, I suspected GIMP could do something different, in fact my previous workflow involved the creation using gimp but for 100 labels the process is tedious.

Now I resolved, that's how.

Step 1
Create the image using image magick, it could be done using gimp too, I need more time to learn how to script it

Code: Select all

convert -size 256x18 xc:black -font "SteelfishRg-Regular" -fill "#f8f8f8" -pointsize 16 -draw "text 0,15 'The quick brown fox jumps over the lazy dog.'" label-simple.bmp
Step 2
Open the image palette.bmp and go to image > mode > indexed and create a palette for 16 colors, no dithering, rename the palette to a more easy to write name

Step 3
Open the batch plugin and create this pipeline
  • Convert to grayscale
  • Other gimp procedure: gimp-image-convert-indexed. Select no dither (or some, depends fro your taste), custom type palette and use the name of your palette created in step 2.
  • Use the bmp output format
  • Apply!
Step 4

Now I need a bmp without any color information, gimp doesn't seems to have this option using the api (you can using the export gui), so I found this script for strip the information and changed a bit

Code: Select all

import struct
import sys

V4_HEADER_SIZE = 108
COLOR_INFO_SIZE = 68
HEADER_OFF = 14
DATA_OFF_FIELD = 10
SIZE_OFF  =  2

def strip_color_info(old_bmp_name, new_bmp_name=None):
    if new_bmp_name is None:
        new_bmp_name = 'mod_'+old_bmp_name
    data = bytearray(open(old_bmp_name, "rb").read())
    header_size = struct.unpack("I", data[HEADER_OFF: HEADER_OFF + 4])[0]
    if header_size == 108:
        # Remove 68  - the size for the extra data-chunk from both headers
        data[HEADER_OFF: HEADER_OFF + 4] = struct.pack("I", V4_HEADER_SIZE - COLOR_INFO_SIZE)
        data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4] = struct.pack("I",
            struct.unpack("I",data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4])[0] - COLOR_INFO_SIZE)
        # Offset image data:
        data[HEADER_OFF + header_size - COLOR_INFO_SIZE:] =  data[HEADER_OFF + header_size:]
        data[SIZE_OFF: SIZE_OFF + 4] = struct.pack("I", len(data))
    with open(new_bmp_name, "wb") as output_file:
        output_file.write(data)
    print('done')

strip_color_info(sys.argv[1])
Now I can strip the information using

python strip.py someimage,bmp

I can use bash for process all the images!

This is very hackysh, I can create a more polished pipeline, but it works and for translate a game is fine!