curious technology logo

9-patch definition:  Draw 9-patch is a utility to create 9-patch files for Android.

There are several types of 9-patch files that you may come across:
  Image.9.png with a 'npTc' chunk = a correctly compiled 9-patch file.
  Image.9.png without a 'npTc' chunk, 2x2 pixels larger than it should be, with black ticks around the border = a decompiled 9-patch file.
  Image.9.png without a 'npTc' chunk, correct size, no added border = a normal png file incorrectly renamed as .9.png
  Image.png = a normal png.  (may have border/ticks or chunk = incorrectly renamed with .9 removed).

Often times, when decompiling a framework, errors may occur on 9-patch files due to incorrect use. These are decompiled files that were dropped in a compiled apk or the .9 was added to a normal image and dropped in.
Warning: Test the output files before deleting any originals until understanding how this works.
How it all works:
  Gdi.LoadImage( filename.png ) will load an image ignoring any 9-patch data.
  Gdi.LoadImage( filename.9.png ) will load an image and read the 9-patch.  If the image doesn't have 9-patch it will be created as full on all sides (no-stretch).
                                                  If the image was previously decompiled, it will have visual patch data that PngMagic will analyze and use if valid.
                                                  Gdi.IsCompiled will be false if the patch had to be created
 
Gdi.LoadImage( filename.png, 'Decompile' ) will load the image normally, ignoring the decompile option.
  Gdi.LoadImage( filename.9.png, 'Decompile' ) will load the image, add a 1px border and draw the patch. If it doesn't have data, it will be created and
                                                                    analyzed as a possible decompiled image.
                                                                    Gdi.ImageWidth and Gdi.ImageHeight will include the extra border in the size.
  Gdi.Save( filename.9.png, x, y, w, h, 'Compile' ) will compile the image by reading the border lines, remove 1px on each border and save unless errors are reported.
  Gdi.Save( filename.png, x, y, w, h, 'Compile' ) Same as above, but will change the extension to .9.png.
  Gdi.Save( filename.png, x, y, w, h, 'Clone' ) Will save as w/h, adds .9 if not there as above, but copies the exact 9-patch from the last loaded image (if available).
Example 1: Load a compiled image and draw it with patches visible
Gdi.Clear(0xFFFFFFFF) // Fill with white (can be any color.  9-patch only looks at alpha)
Gdi.Clear(0)                      // Sett work area to 0% opacity
Gdi.LoadImage( '9files\\ic_notification_overlay.9.png' , 'Decompile')
Gdi.DrawImage()  // Draw image at 0,0
//<change color or something>
// Save as decompiled
Gdi.Save('9decompiled\\ic_notification_overlay.9.png', 0, 0, Gdi.ImageWidth, Gdi.ImageHeight)
// Compile and save
Gdi.Save('9compiled\\ic_notification_overlay.9.png', 0, 0, Gdi.ImageWidth, Gdi.ImageHeight, 'Compile')
// Save another as normal (without 9-patch)
Gdi.Save('normal\\ic_notification_overlay.png', 1, 1, Gdi.ImageWidth-2, Gdi.ImageHeight-2)
Example 2: Load a normal png (or compiled) and make a 9-patch
Gdi.Clear(0xFFFFFFFF) // Fill with white (can be any color.  9-patch only looks at alpha)
Gdi.Clear(0)                      // Set work area to 0% opacity
Gdi.LoadImage( 'normal\\ic_notification_overlay.png' )
Gdi.DrawImage(1, 1)  // Draw image at 1,1 for 9-patch space
Gdi.Smoothing = 'None' // Disable smoothing for absolute pixel/alpha color
Gdi.Pen(0xFF000000) // solid black lines
Gdi.Line(0,11, 0, 12)
// left
Gdi.Line(12,0, 13, 0) // top
Gdi.Line(25,1, 25, 22) // right
Gdi.Line(2,25, 22, 25)
// bottom
// Compile and save (Compile can insert .9 in the name if it succeeds, Clone will if it has data to write)
Gdi.Save( '9new\\ic_notification_overlay.png' , 0, 0, Gdi.ImageWidth+2, Gdi.ImageHeight+2, 'Compile')
Example 3: Load a normal png (or compiled) and make a 9-patch, but using SetPatch this time
Gdi.Clear(0xFFFFFFFF) // Fill with white (can be any color.  9-patch only looks at alpha)
Gdi.Clear(0)                      // Set work area to 0% opacity
Gdi.LoadImage( 'normal\\ic_notification_overlay.png' )
Gdi.DrawImage( )  // Draw image at 1,1 for 9-patch space
Gdi.SetPatch( 11,12, 12,13, 1,0, 2,0)
// Save by using 9-patch data
Gdi.Save( '9new\\ic_notification_overlay.png' , 0, 0, Gdi.ImageWidth, Gdi.ImageHeight, 'Clone' )
Example 4: Load a 9-patch without decompiling and save it with 9-patch intact
Gdi.Clear(0xFFFFFFFF) // Fill with white (9-patch won't be used)
Gdi.Clear(0)                      // Set work area to 0% opacity
Gdi.LoadImage( '9files\\ic_notification_overlay.9.png' )
Gdi.DrawImage(0, 0)  // Draw image at 0,0
// <do some image manipulation here>
// Save with 9-patch because last loaded image has 9-patch (use the same size, and probably the same image)
Gdi.Save( '9new\\ic_notification_overlay.9.png', 0, 0, Gdi.ImageWidth, Gdi.ImageHeight, 'Clone')
 

CuriousTech™ Copyright © 2003-2024 Curious Technology