Loading

palette-v9

  1. import math
  2. import time
  3. import datetime
  4. import os
  5. from os import remove
  6. from PIL import Image
  7. from multiprocessing import Pool
  8. import multiprocessing
  9.  
  10. #starting message
  11. print("-"*79)
  12. print("Starting...")
  13.  
  14. #path definition
  15. diskPath = 'D:/OpenTTD_repositories/BRIX/scripts/' #"C:/Users/Pavel/Downloads/scripts/"#"E:/_BRIX/_BRIX-repository/scripts/"
  16. inputFolder = diskPath + "input/"
  17. outputFolder = diskPath + "output/"
  18.  
  19. #printing path just to check
  20. print("inputFolder is " + inputFolder)
  21. print("outputFolder is " + outputFolder)
  22.  
  23. #started time
  24. tt = time.time()
  25. startedTime = datetime.datetime.fromtimestamp(tt).strftime('%H:%M:%S')
  26.  
  27.  
  28.  
  29. #open palette image
  30. palette = Image.open(inputFolder + "openttd-palette-dos.png")
  31. print("Opening and loading palette: " + "openttd-palette-dos.png")  
  32.  
  33. p=[]
  34.  
  35. for b in range(0,palette.height):
  36.   for a in range(0, palette.width):
  37.     p.append(palette.getpixel((a,b)))
  38.    
  39. print('Palette loaded.')
  40.  
  41. # ----------------------------------------------------------------------------------------------------------------
  42. # ----------------------------------------------------------------------------------------------------------------
  43. # ----------------------------------------------------------------------------------------------------------------
  44.  
  45.  
  46. def rgb2palette(input_image, x_start, x_end):
  47.   #open input image
  48.   i = Image.open(inputFolder + input_image + ".png")
  49.   print("Opening: " + input_image + ".png")  
  50.  
  51.   #create new empty image for output
  52.   imageOutput = Image.new("RGBA", (i.width,i.height), color=(0,0,0,0))
  53.  
  54.   for y in range (0, i.height):
  55.     #timeStamp
  56.     ts = time.time()
  57.     timeStamp = datetime.datetime.fromtimestamp(ts).strftime('%H:%M:%S')
  58.     #print(timeStamp + " - " + input_image + " row {}".format(y))
  59.     for x in range (x_start, x_end):
  60.       print(timeStamp + " - " + input_image + " row {}".format(x))
  61.       #defining winner variables
  62.       winnerDistance = 100000000
  63.       winnerID = 0
  64.      
  65.       #loading pixel from image and separating RGBA
  66.       pixelNumber = x + (y * i.width)
  67.       pix = i.getpixel((x,y))
  68.       pixRed = pix[0]
  69.       pixGreen = pix[1]
  70.       pixBlue = pix[2]
  71.       pixAlpha = pix[3]
  72.            
  73.       #check Alpha in pixel, and output alpha/color offset
  74.       if pixAlpha < 128:
  75.         finalAlpha = 0
  76.         colorOffset = 0
  77.       if pixAlpha >= 128 and pixAlpha < 178:
  78.         finalAlpha = 255
  79.         colorOffset = 1
  80.       if pixAlpha >= 178 and pixAlpha < 230:
  81.         finalAlpha = 255
  82.         colorOffset = 2
  83.       if pixAlpha >= 230:
  84.         finalAlpha = 255
  85.         colorOffset = 0
  86.      
  87.       #if alpha above 50%, do colour comparing to palette
  88.       if pixAlpha >= 128:
  89.         for z, (r1, g1, b1, ca) in enumerate(p):
  90.           #dr = pixRed - cr
  91.           #dg = pixGreen - cg
  92.           #db = pixBlue - cb
  93.           #distance = dr*dr + dg*dg + db*db
  94.           l1 = (r1*299 + g1*587 + b1*114) / 255000
  95.           l2 = (pixRed*299 + pixGreen*587 + pixBlue*114) / 255000
  96.           dL = l1-l2
  97.           dR = (r1-pixRed)/255
  98.           dG = (g1-pixGreen)/255
  99.           dB = (b1-pixBlue)/255
  100.           distance = (dR*dR*0.299 + dG*dG*0.587 + dB*dB*0.114)*0.75 + dL*dL
  101.          
  102.           if distance < winnerDistance:
  103.             winnerDistance = distance
  104.             winnerID = z
  105.    
  106.       #compare input RGB channels and output highest value
  107.       if pixRed >= pixGreen and pixRed >= pixBlue:
  108.         highestValue = pixRed
  109.       if pixGreen >= pixRed and pixGreen >= pixBlue:
  110.         highestValue = pixGreen
  111.       if pixBlue >= pixRed and pixBlue >= pixGreen:
  112.         highestValue = pixBlue    
  113.       # set color offset +/- based on colour value
  114.       if highestValue < 128:
  115.         negation = -1
  116.         colorOffset = colorOffset * negation
  117.       #print("colorOffset is ... " + str(colorOffset) )
  118.      
  119.       #final color changed by colorOffset
  120.       finalColor = p[winnerID - colorOffset]
  121.      
  122.       finalR = finalColor[0]
  123.       finalG = finalColor[1]
  124.       finalB = finalColor[2]
  125.       #finalAlpha taken from the if output above palette colour comparing
  126.      
  127.       #put the final pixel into the output picture
  128.       imageOutput.putpixel((x,y),(finalR,finalG,finalB,finalAlpha))
  129.       #print("Pixel " + str(pixelNumber) + ": R= " + str(finalR) + ", G= " + str(finalG) + ", B= " + str(finalB) + ", A= "  + str(finalAlpha)   )
  130.          
  131.      
  132.  
  133.      
  134.      
  135. def run():
  136.   # ----------------------------------------------------------------------------------------------------------------
  137.   #VARIABLES
  138.   # ----------------------------------------------------------------------------------------------------------------
  139.   job_list = [
  140.       'test0'
  141.       #'BRIDGES_0000',
  142.       #'LAND_OUTPUT_0000'
  143.       ]
  144.   # ----------------------------------------------------------------------------------------------------------------
  145.   thread_count = 16
  146.   # ----------------------------------------------------------------------------------------------------------------
  147.   # ----------------------------------------------------------------------------------------------------------------
  148.   # ----------------------------------------------------------------------------------------------------------------
  149.  
  150.   for job in job_list:
  151.     all_jobs = []
  152.     job_chunks = []
  153.     queue = []
  154.  
  155.     extra = 0
  156.     chunk_image = Image.open(inputFolder + job + ".png")
  157.     chunk_average_size = math.floor(chunk_image.width/thread_count)
  158.     chunk_modulo_size = chunk_image.width % thread_count
  159.     for thread in range(0, thread_count):
  160.       start = chunk_average_size * thread
  161.       end = (chunk_average_size * (thread+1)) -1
  162.  
  163.       start += extra
  164.       if thread < chunk_modulo_size:  
  165.         extra += 1
  166.       end += extra
  167.  
  168.       start_and_end = [job, start, end]
  169.      
  170.       job_chunks.append(start_and_end)
  171.  
  172.       queue.append( [job, start, end] )
  173.       #print(str(queue))
  174.  
  175.     all_jobs.append(job_chunks)
  176.  
  177.     for a_job in all_jobs:
  178.       #print('-'*32)
  179.       thread_id = 0
  180.       for b_thread in a_job:
  181.         if thread_id == 0:
  182.           thread_id += 1
  183.           print('Job: ' + str(b_thread[0]))#
  184.           print(' '*10 + 'Start, ' + 'End')#
  185.           print('Thread ' + str(thread_id) + ': ' + str(b_thread[1]) + ', ' + str(b_thread[2]))#
  186.        
  187.        
  188.    
  189.     #print(all_jobs)
  190.    
  191.     # ----------------------------------------------------------------------------------------------------------------
  192.     # PROCESS
  193.     # ----------------------------------------------------------------------------------------------------------------
  194.    
  195.     pool = multiprocessing.Pool(processes = thread_count)
  196.     for q in queue:
  197.       pool.apply_async(rgb2palette, args=(q[0], q[1], q[2], ) )
  198.     pool.close()
  199.     pool.join()
  200.  
  201.  
  202.     os.makedirs(outputFolder, exist_ok = True)
  203.     imageOutput.save(outputFolder + input_image[-5:] + "_8bpp.png") #assumes _#### frame number format (removes last 5 characters)
  204.    
  205.     #finished time
  206.     tx = time.time()
  207.     finishedTime = datetime.datetime.fromtimestamp(tx).strftime('%H:%M:%S')
  208.    
  209.     print("Started:  " + startedTime)
  210.     print("Finished: " + finishedTime)
  211.    
  212.  
  213. run()
  214.  
  215. if __name__ == '__main__':
  216.   #freeze_support()
  217.   run()

Comments