Ver código fonte

Fix transparency missing with indexed color

Mike L 1 mês atrás
pai
commit
06ef5ed435
4 arquivos alterados com 55 adições e 25 exclusões
  1. 9 1
      ani2cape.py
  2. 13 2
      ani2gif.py
  3. 13 2
      ani2spritesheet.py
  4. 20 20
      config.py

+ 9 - 1
ani2cape.py

@@ -14,7 +14,15 @@ def scaleImage(img, scale):
 
 
 def readCUR(f, width=-1.0, height=-1.0):
-    frameImage = Image.open(f, formats=['cur', 'ico']).convert('RGBA')
+    frameImage = Image.open(f, formats=['cur', 'ico'])
+    if (frameImage.mode == 'P'):
+        palette = list(frameImage.palette.getdata()[1])
+        for i in range(4, len(palette), 4):
+            if sum(palette[i:i + 3]) == 0:
+                break
+            palette[i + 3] = 255
+        frameImage.putpalette(palette, 'BGRA')
+        frameImage = frameImage.convert('RGBA')
     if (width, height) == (-1.0, -1.0):
         return frameImage, (float(frameImage.width), float(frameImage.height))
     if -1 in (width, height):

+ 13 - 2
ani2gif.py

@@ -46,6 +46,16 @@ def analyzeANIFile(filePath):
             nowSize += subChunkSize
         return {"code":0,"msg":frameList,"frameRate":frameRate}
 
+def CURPaletteFix(image):
+    # type: (Image.ImageFile.ImageFile) -> None
+    if (image.mode == 'P'):
+        palette = list(image.palette.getdata()[1])
+        for i in range(4, len(palette), 4):
+            if sum(palette[i:i + 3]) == 0:
+                break
+            palette[i + 3] = 255
+        image.putpalette(palette, 'BGRA')
+
 if __name__ == '__main__':
     if len(sys.argv) < 2:
         logging.fatal("Usage:python ani2gif.py <inputFile> <outputFile,Option>")
@@ -55,8 +65,9 @@ if __name__ == '__main__':
         if res["code"] == 0:
             logging.info('ANI文件分析完成,帧提取完成!')
             for frame in res["msg"]:
-                frameImage = Image.open(io.BytesIO(frame),formats=['CUR']).convert('RGBA')
-                GIFframes.append(frameImage)
+                frameImage = Image.open(io.BytesIO(frame),formats=['CUR'])
+                CURPaletteFix(frameImage)
+                GIFframes.append(frameImage.convert('RGBA'))
             if(len(sys.argv) >= 3):
                 GIFframes[0].save(sys.argv[2],format="GIF",save_all=True, append_images=GIFframes[1:], optimize=False, duration=res["frameRate"], loop=0, transparency=0, disposal=2)
             else:

+ 13 - 2
ani2spritesheet.py

@@ -46,6 +46,16 @@ def analyzeANIFile(filePath):
             nowSize += subChunkSize
         return {"code":0,"msg":frameList,"frameRate":frameRate}
 
+def CURPaletteFix(image):
+    # type: (Image.ImageFile.ImageFile) -> None
+    if (image.mode == 'P'):
+        palette = list(image.palette.getdata()[1])
+        for i in range(4, len(palette), 4):
+            if sum(palette[i:i + 3]) == 0:
+                break
+            palette[i + 3] = 255
+        image.putpalette(palette, 'BGRA')
+
 if __name__ == '__main__':
     OUTPUT_SIZE = (48,48)
     if len(sys.argv) < 2:
@@ -57,8 +67,9 @@ if __name__ == '__main__':
             logging.info('ANI文件分析完成,帧提取完成!')
             output = Image.new("RGBA", (OUTPUT_SIZE[0], OUTPUT_SIZE[1] * len(res["msg"])))
             for frameIndex in range(len(res["msg"])):
-                frameImage = Image.open(io.BytesIO(res["msg"][frameIndex]),formats=['cur']).convert('RGBA')
-                extracted_frame = frameImage.resize(OUTPUT_SIZE)
+                frameImage = Image.open(io.BytesIO(res["msg"][frameIndex]),formats=['cur'])
+                CURPaletteFix(frameImage)
+                extracted_frame = frameImage.convert('RGBA').resize(OUTPUT_SIZE)
                 position = (0, OUTPUT_SIZE[0] * frameIndex)
                 output.paste(extracted_frame, position)
             if(len(sys.argv) >= 3):

+ 20 - 20
config.py

@@ -1,8 +1,8 @@
 capeConfig = {
-    'Author': '作者名',
-    'CapeName': '鼠标指针',
+    'Author': '',
+    'CapeName': '-菫時-',
     'CapeVersion': 1.0,
-    'Identifier': 'com.mihuashi.authornickname.cursors',
+    'Identifier': 'com.bilibili.gjsg.cursors',
     'Cursors': {
         'com.apple.coregraphics.Arrow': {
             'FrameDuration': 0.1,
@@ -18,19 +18,19 @@ capeConfig = {
         },
         'com.apple.cursor.4': {
             'FrameDuration': 0.1,
-            'HotSpot': (11.0, 11.0),
+            'HotSpot': (12.0, 12.0),
             'Size': (32.0, 32.0),
-            'Path': "./Busy.ani"
+            'Path': "./Working.ani"
         },
         'com.apple.cursor.34': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (16.0, 16.0),
             'Size': (32.0, 32.0),
             'Path': "./Diagonal1.ani"
         },
         'com.apple.cursor.30': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (16.0, 16.0),
             'Size': (32.0, 32.0),
             'Path': "./Diagonal2.ani"
         },
@@ -42,13 +42,13 @@ capeConfig = {
         },
         'com.apple.cursor.19': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (16.0, 4.0),
             'Size': (32.0, 32.0),
             'Path': "./Horizontal.ani"
         },
         'com.apple.cursor.28': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (16.0, 4.0),
             'Size': (32.0, 32.0),
             'Path': "./Horizontal.ani"
         },
@@ -66,49 +66,49 @@ capeConfig = {
         },
         'com.apple.cursor.39': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (16.0, 16.0),
             'Size': (32.0, 32.0),
             'Path': "./Move.ani"
         },
         'com.apple.cursor.5': {
             'FrameDuration': 0.1,
-            'HotSpot': (7.0, 7.0),
+            'HotSpot': (16.0, 16.0),
             'Size': (32.0, 32.0),
-            'Path': "./Precision.ani"
+            'Path': "./Precision.cur"
         },
         'com.apple.cursor.20': {
             'FrameDuration': 0.1,
-            'HotSpot': (7.0, 7.0),
+            'HotSpot': (16.0, 16.0),
             'Size': (32.0, 32.0),
-            'Path': "./Precision.ani"
+            'Path': "./Precision.cur"
         },
         'com.apple.coregraphics.IBeam': {
             'FrameDuration': 0.1,
-            'HotSpot': (5.0, 7.0),
+            'HotSpot': (3.0, 7.0),
             'Size': (32.0, 32.0),
             'Path': "./Text.ani"
         },
         'com.apple.cursor.23': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (4.0, 16.0),
             'Size': (32.0, 32.0),
             'Path': "./Vertical.ani"
         },
         'com.apple.cursor.32': {
             'FrameDuration': 0.1,
-            'HotSpot': (15.0, 15.0),
+            'HotSpot': (5.0, 16.0),
             'Size': (32.0, 32.0),
             'Path': "./Vertical.ani"
         },
         'com.apple.coregraphics.Wait': {
             'FrameDuration': 0.1,
-            'HotSpot': (6.0, 6.0),
+            'HotSpot': (12.0, 12.0),
             'Size': (32.0, 32.0),
-            'Path': "./Working.ani"
+            'Path': "./Busy.ani"
         },
         'com.apple.cursor.3': {
             'FrameDuration': 0.1,
-            'HotSpot': (8.0, 8.0),
+            'HotSpot': (16.0, 16.0),
             'Size': (32.0, 32.0),
             'Path': "./Unavailable.ani"
         },