快速生成 Android 的 Splash 的 9 Patch 图片

import java.io.File;

import java.awt.Color;
import java.awt.Image;
import java.awt.Graphics2D;

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

/**
 * 实在受不了 Android Studio 里制作 9 Patch 难用的 Editor
 *
 * 快速生成  Android 的 Splash 的 9 Patch 图片
 *
 * 找最大一张图片,作为  xxxdpi,比如 1024 * 1024,生成如下尺寸的,注意图片里的上下左右空白边距必须大于 4 * 3 / 0.75 = 16 个像素
 *
 * xxxhdpi  1024  4.00x
 *
 *  xxhdpi   768  3.00x
 *
 *   xhdpi   512  2.00x
 *
 *   hdpi    384  1.50x
 *
 *   mdpi    256  1.00x
 *
 *   ldpi    192  0.75x
 *
 * @author NeedJava@126.com
 *
 * @since 2025.07.12
 */
public final class Create9Patch
{
    private static final Item[] ITEMS = new Item[]
    {
        new Item( "drawable-xxxhdpi", 4.00F ),  //1024 = * 4.00F / 4

        new Item( "drawable-xxhdpi",  3.00F ),  // 768 = * 3.00F / 4

        new Item( "drawable-xhdpi",   2.00F ),  // 512 = * 2.00F / 4

        new Item( "drawable-hdpi",    1.50F ),  // 384 = * 1.50F / 4

        new Item( "drawable-mdpi",    1.00F ),  // 256 = * 1.00F / 4

        new Item( "drawable-ldpi",    0.75F ),  // 192 = * 0.75F / 4
    };

    public static void main( final String[] args ) throws Exception
    {
        final java.io.BufferedReader reader = new java.io.BufferedReader( new java.io.InputStreamReader( System.in ) );

        while( true )
        {
            System.err.println( "\r\nPlease input image path and press Enter:" );

            final String source = reader.readLine().trim();

            final File sourceFile = new File( source.startsWith( "\"" ) && source.endsWith( "\"" ) ? source.substring( 1, source.length() - 1 ) : source );

            if( sourceFile.isFile() == false ){ System.err.println( "Image not exists! " + sourceFile ); continue; }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////

            System.err.println( "\r\nPlease input 9 patch file name and press Enter:" );

            final String outputName = reader.readLine().trim();

            ////////////////////////////////////////////////////////////////////////////////////////////////////////////

            create( sourceFile, outputName );

            System.err.println( "\r\nDONE" );
        }
    }

    public static void create( final File oldFile, final String outputName ) throws Exception
    {
        final File outputFolder = new File( oldFile.getParent(), "output"/*HARD_CODE*/ );

        final String oldName = isTrimEmpty( outputName ) ? "image_splash.9.png"/*HARD_CODE*/ : outputName + ".9.png"/*HARD_CODE*/;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        final BufferedImage oldImage = ImageIO.read( oldFile );

        final int oldWidth  = oldImage.getWidth();

        final int oldHeight = oldImage.getHeight();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        Item item = null; File folder = null; int newWidth = 0, newHeight = 0;

        for( int i = 0; i < ITEMS.length; i ++ )
        {
            if( ( item = ITEMS[i] ) == null || isTrimEmpty( item.mFolder ) ){ continue; }

            folder = new File( outputFolder, item.mFolder ); folder.mkdirs();

            newWidth  = (int) ( oldWidth  * item.mTimes / 4/*HARD_CODE*/ );

            newHeight = (int) ( oldHeight * item.mTimes / 4/*HARD_CODE*/ );

            ImageIO.write( scaleImageByWidth( oldImage, newWidth, newHeight ), "png"/*HARD_CODE*/, new File( folder, oldName ) );
        }
    }

    public static BufferedImage scaleImageByWidth( final BufferedImage oldImage, final int newWidth, final int newHeight )
    {
        final BufferedImage newImage = new BufferedImage( newWidth, newHeight, BufferedImage.TYPE_INT_ARGB );

        final Graphics2D g2d = newImage.createGraphics();

        g2d.drawImage( oldImage.getScaledInstance( newWidth, newHeight, Image.SCALE_SMOOTH ), 0, 0, null );

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        g2d.setColor( Color.BLACK );

        //////////////////////////////////////////////////////////// Top

        g2d.drawLine( 1, 0, 2, 0 );

        g2d.drawLine( newWidth - 3, 0, newWidth - 2, 0 );

        //////////////////////////////////////////////////////////// Left

        g2d.drawLine( 0, 1, 0, 2 );

        g2d.drawLine( 0, newHeight - 3, 0, newHeight - 2 );

        //////////////////////////////////////////////////////////// Right

        g2d.drawLine( newWidth - 1, 3, newWidth - 1, newHeight - 4 );

        //////////////////////////////////////////////////////////// Bottom

        g2d.drawLine( 3, newHeight - 1, newWidth - 4, newHeight - 1 );

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        g2d.dispose();

        return newImage;
    }

    public static boolean isTrimEmpty( final String string )
    {
        return ( string == null ? true : string.trim().length() == 0 );
    }
}

final class Item
{
    public final String mFolder;

    public final float mTimes;

    public Item( final String folder, final float times )
    {
        this.mFolder = folder;

        this.mTimes  = times;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值