Инструмент для обрезки и склеивания набора png
Недавно озадачился скриптиком для обрезки и склеивания битмап изображений ( в данном случае прозрачного png) и генерации xml с координатами обрезки..
попросил помощи здесь:http://www.flasher.ru/forum/showthread.php?t=130000
Ответа не услышал))
пришлось написать самому.
Сделал AIR приложение.
кому интересно вот код, исходники во вложении.
pngConverter.zip - flashDevelop project
allFlashCS3Components.zip - либа с флэшевскими компонентами ( нужно закинуть в папку lib проекта)
package { import fl.controls.Button; import fl.controls.ComboBox; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.MouseEvent; import flash.filesystem.File; import flash.events.FileListEvent; import flash.filesystem.FileMode; import flash.filesystem.FileStream; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.URLRequest; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFieldType; import flash.utils.ByteArray; import org.aswing.image.png.*; /** * Интсрумент для обрезки и склеивания набора битмап в "простыню" * на выходе получаем png файл и xml с параметрами обрезки и склеивания * @author k0t0vich */ public class Main extends Sprite { private var file:File; private var counter:int = 0; private var btn:Button; private var tfLabel:TextField = new TextField(); private var tfCols:TextField = new TextField(); private var encoderCombo:ComboBox = new ComboBox(); private var colCombo:ComboBox = new ComboBox(); //var dp:DataProvider = new DataProvider(); private var fileListArray:Array = []; private var fileListCounter:int = 0; private var bitmapArray:Array = []; private var trimedBitmapDataArray:Array = []; private var loader:Loader = new Loader(); private var ext:String = "png"; private var encoder:AsPngEncoder = new AsPngEncoder(); private var encoders:Array = [ new Strategy32BitAlpha(), new Strategy32BitOpaque(), new Strategy8BitMedianCutAlpha(256, 4), new Strategy8BitMedianCutAlpha(128, 4), new Strategy8BitMedianCutAlpha(64), new Strategy8BitMedianCutAlpha(16), new Strategy8BitMedianCutAlpha(8), new Strategy8BitMedianCutAlpha(4), new Strategy8BitMedianCutAlpha(2), new Strategy8BitMedianCutOpaque(256), new Strategy8BitMedianCutOpaque(64), new Strategy8BitMedianCutOpaque(9), new Strategy8BitUniformQuantAlpha(), new Strategy8BitUniformQuant(6, 7, 6), new Strategy8BitUniformQuant(6, 6, 6), new Strategy8BitUniformQuant(8, 8, 4), new Strategy8BitUniformQuant(5, 5, 5), new Strategy8BitUniformQuant(4, 4, 4), new Strategy8BitUniformQuant(2, 2, 2) ]; private var trimXML:XML = <data/>; private var saveFile:File; private var encodedPng:ByteArray; private var cols:int = 8; public function Main():void { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.LOW; loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadPNG); drawUI(); Output.trace("В начале работы необходимо выбрать количество изображений на ряд,\nзатем формат сохранения изображения,\nпосле этого выбирайте папку назначения"); } private function drawUI():void { addChild(new Output()); btn = new Button(); btn.label = "Выбрать директорию исходных изображений"; btn.width = 300; btn.y =10; btn.addEventListener(MouseEvent.CLICK, btn_click); addChild(btn); tfLabel.x = btn.x +btn.width + 10; tfLabel.y = btn.y; tfLabel.text = "Изображений в ряду:"; tfLabel.autoSize = TextFieldAutoSize.LEFT; tfLabel.selectable = false; addChild(tfLabel); colCombo.width = 40; colCombo.editable = false; colCombo.x = tfLabel.x +tfLabel.width+ 10; colCombo.y = tfLabel.y; for (var i:int = 0; i <32; i++) { colCombo.addItem( { label:String(i+1) } ); } colCombo.selectedIndex = 7; addChild(colCombo); encoderCombo.width =240; encoderCombo.editable=false; encoderCombo.x = colCombo.x+60 encoderCombo.y = colCombo.y; for (i= 0; i < encoders.length; i++) { encoderCombo.addItem( { label:encoders[i].toString() } ); } encoderCombo.selectedIndex = 2; addChild(encoderCombo); } private function fileListLoaded(evt:FileListEvent):void { fileListArray = evt.files; loadNextFile();; } private function loadNextFile():void { var len:int = fileListArray.length; if (fileListCounter == len) { trimImages(); return; } var file:File = fileListArray[fileListCounter]; if (String(file.extension).toLowerCase() == ext) { loader.load(new URLRequest(file.url)); var imgXML:XML = <img/>; imgXML.@img = file.name; trimXML.appendChild(imgXML); } else { fileListCounter++; loadNextFile(); } } private function trimImages():void { var len:int = bitmapArray.length; Output.trace("Обрезка исходных изображений len= "+len); for (var i:int = 0; i < len; i++) { var sourceBitmapData:BitmapData = bitmapArray[i].bitmapData; var rect:Rectangle = sourceBitmapData.getColorBoundsRect(0xFF000000, 0x00000000,false); var trimedBitmapData:BitmapData = new BitmapData(rect.width, rect.height, true, 0); // запись вырезанных параметров в XML var imgXML:XML = trimXML.img[i]; imgXML.@top = rect.top; imgXML.@left = rect.left; imgXML.@width = rect.width; imgXML.@heigth = rect.height; trimedBitmapData.copyPixels(sourceBitmapData, rect, new Point()); trimedBitmapDataArray.push(trimedBitmapData); // удаляем sourceBitmapData.dispose(); bitmapArray[i] = null; } montageTrimmedBitmaps(); } private function montageTrimmedBitmaps():void { Output.trace("Main.montageTrimmedBitmaps"); // вычисляем размер результирующей битмапы var maxH:int = 0; var maxW:int = 0; var h:int = 0; var w:int = 0; var maxHArray:Array = []; var maxWArray:Array = []; cols = colCombo.selectedIndex+1; var len:int = trimedBitmapDataArray.length; var rows:int = Math.ceil(len / cols); for (var i:int = 0; i <rows; i++) { maxH = 0; maxW = 0; for (var j:int = 0; j < cols && i*(cols) + j < len; j++) { var bitmapData:BitmapData = trimedBitmapDataArray[i*(cols) + j]; maxH = Math.max(maxH, bitmapData.height); maxW += bitmapData.width; } // сохранем в массив, для последующего монтажа maxWArray.push(maxW) maxHArray.push(maxH); h += maxH; } var wlen:int = maxWArray.length; for (i = 0; i < wlen; i++) { w = Math.max(maxWArray[i], w); } // создаём результирующую битмапдату Output.trace("w, h : " + w, h); if (w > 2880 || h > 2880) Output.trace("Слишком большой размер бимапы > 2880"); trimXML.@width = w; trimXML.@heiht = h; var resultBitmapData:BitmapData = new BitmapData(w, h, true, 0); // текущая точка вставки var curX:int = 0; var curY:int = 0; for ( i= 0; i < rows; i++) { curX = 0; for (j = 0; j < cols && i*(cols) + j < len; j++) { var id:int = i * (cols) + j; var point:Point = new Point(curX, curY); var imgXML:XML = trimXML.img[id]; imgXML.@x = curX; imgXML.@y = curY; //imgXML.@id = id; bitmapData= trimedBitmapDataArray[id]; var rect:Rectangle = new Rectangle(0, 0, bitmapData.width, bitmapData.height); resultBitmapData.copyPixels(bitmapData, rect, point); curX += bitmapData.width; // удаляем bitmapData.dispose(); trimedBitmapDataArray[id] = null; } curY += maxHArray[i]; } //тест //addChild(new Bitmap(resultBitmapData)); // запись saveBitmapDataAsPng(resultBitmapData); } private function saveBitmapDataAsPng(bitmapData:BitmapData):void { Output.trace("Main.saveBitmapDataAsPng "); encodedPng = encoder.encode(bitmapData, encoders[encoderCombo.selectedIndex]); saveFile = new File(); saveFile.addEventListener(Event.SELECT, fileSaveSelected); save(new Event("!!")); } private function saveTrimXML():void { Output.trace("Main.saveXML"); saveFile = new File(); saveFile.addEventListener(Event.SELECT, xmlSaveSelected); saveXML(new Event("!!")); } private function xmlSaveSelected(e:Event):void { saveFile.removeEventListener(Event.SELECT, xmlSaveSelected); var stream:FileStream = new FileStream(); if(!saveFile.exists){ Output.trace("Создан новый файл"); } stream.open(saveFile, FileMode.WRITE); stream.writeUTFBytes(trimXML.toXMLString()); stream.close(); restart(); } /** * Повторное использование - удаление всего лишнего */ private function restart():void { fileListArray= []; fileListCounter=0; bitmapArray= []; trimedBitmapDataArray = []; addChild(btn); Output.trace("Готов к работе"); } private function onLoadPNG(e:Event):void { bitmapArray.push(e.target.content); fileListCounter++; loadNextFile(); } private function btn_click(evt:MouseEvent):void { removeChild(btn); Output.trace("Выберите каталог с изображениями для склейки"); file = new File(); file.addEventListener(Event.SELECT, directorySelected); file.browseForDirectory("Выберите каталог с изображениями для склейки"); } private function directorySelected(evt:Event):void { file.getDirectoryListingAsync(); file.addEventListener( FileListEvent.DIRECTORY_LISTING, fileListLoaded ); } // сохранение png private function save(e:Event):void{ saveFile.browseForSave("Сохранить файл как png (в имени файла впишите нужное расширение)"); } private function saveXML(e:Event):void{ saveFile.browseForSave("Сохранить файл как xml (в имени файла впишите нужное расширение)"); } private function fileSaveSelected(e:Event):void { saveFile.removeEventListener(Event.SELECT, fileSaveSelected); var stream:FileStream = new FileStream(); if(!saveFile.exists){ Output.trace("Создан новый файл"); } stream.open(saveFile, FileMode.WRITE); stream.writeBytes(encodedPng); stream.close(); saveTrimXML(); } } }
Всего комментариев 5
Комментарии
23.09.2009 20:02 | |
isNaN(int(e.target.text))
всегда будет false |
25.09.2009 11:52 | |
07.02.2011 13:39 | |
докопаюсь по-мелочи )
Цитата:
Интсрумент
|
07.02.2011 13:42 | |
п.с. топик выкинуло в рандомизаторе. потом только глянул дату )
|
07.02.2011 16:07 | |
о, хорошо, что "отнекропостил" интересная штуковина.
|
Последние записи от Котяра
- Страх и ненависть в Нью-Дели или сборка мультипака для arm7 и x86 c Adobe AIR 14 в FB (16.06.2014)
- Нативный EventDispatcher в старлинге (27.11.2013)
- Нужны ошибки компиляции при создании экземпляра синглетона извне? Запросто! (13.09.2013)
- ARP - новый формат упаковки ресурсов (07.02.2013)
- DropShadowFilter и GlowFilter в Starling (16.01.2013)