Преобразовать 8-битный (16 цветовая палитра) PNG в правильные 4-битные (16 цветовая палитра) с Java или Python? - PullRequest
3 голосов
/ 24 сентября 2011

У меня есть куча изображений, многие из которых я могу сделать вручную в 16-цветном 8-битном формате PNG, который мне нужен в 16-битном формате, все они имеют одинаковую палитру.

Я прочесываю Googleдля лучшей библиотеки для использования, но я не нахожу много по этой конкретной проблеме, поэтому я прихожу сюда для, надеюсь, более целенаправленных решений.

Я пытаюсь использовать PIL на основе других ответов, которые у меня естьнашел здесь , но безуспешно.

img = Image.open('DownArrow_focused.png')
img = img.point(lambda i: i * 16, "L")
img.save('DownArrow_focused.png', 'PNG')

но это дает мне изображение в градациях серого, а не то, что я хочу.

PIL не будет работать, пытаясь PyPNG.GIMP делает это, но у меня есть сотни таких вещей, которые мне нужны для пакетной обработки.И получайте эти пакеты для конвертации, так что это не разовая вещь.

Также было бы приемлемо решение на основе Java, практически все, что я могу запустить из командной строки на компьютере с Linux / OSX.будет приемлемым.

Ответы [ 2 ]

1 голос
/ 26 сентября 2011

В PNG палитра всегда сохраняется в RGB8 (3 байта для каждого индекса = цвет) с произвольным (до 256) количеством записей.Если в настоящее время у вас есть 8-битное изображение с 16-цветовой палитрой (всего 16 записей), вам не нужно изменять палитру, только для перепаковки пиксельных байтов (два индекса на байт).Если это так, я думаю, вы могли бы сделать это с PNGJ с этим кодом (не проверено):

public static void reencode(String orig, String dest) {
    PngReader png1 = FileHelper.createPngReader(new File(orig));
    ImageInfo pnginfo1 = png1.imgInfo;
    ImageInfo pnginfo2 = new ImageInfo(pnginfo1.cols, pnginfo1.rows, 4, false,false,true);  
    PngWriter png2 = FileHelper.createPngWriter(new File(dest), pnginfo2, false);
    png2.copyChunksFirst(png1, ChunksToWrite.COPY_ALL);
    ImageLine l2 = new ImageLine(pnginfo2);
    for (int row = 0; row < pnginfo1.rows; row++) {
        ImageLine l1 = png1.readRow(row);
        l2.tf_pack(l1.scanline, false);
        l2.setRown(row);
        png2.writeRow(l2);
    }
    png1.end();
    png2.copyChunksLast(png1, ChunksToWrite.COPY_ALL);
    png2.end();
    System.out.println("Done");
}

В другом месте, если ваша текущая палитра имеет 16 «используемых» цветов (но ее длинабольше, потому что он включает в себя неиспользуемые цвета), вам нужно выполнить некоторую работу, изменив блок палитры (но это также можно сделать).

0 голосов
/ 25 сентября 2011

Вызовите программы Netpbm http://netpbm.sourceforge.net/ из скрипта Python, используя следующие команды:

$ pngtopnm test.png | pnmquant 16 | pnmtopng > test16.png

$ file test16.png
test16.png: PNG image data, 700 x 303, 4-bit colormap, non-interlaced

И GIMP сообщает, что test16.png имеет Color space: Indexed color (16 colors), что, я полагаю, то, что вам нужно.

Это не чисто решение Python, но PIL также не является чистым Python и также зависит от разделяемых библиотек.Я думаю, что вы не можете избежать зависимости от какого-либо внешнего программного обеспечения для изображений.

...