Каков наилучший способ изменить размер объекта BitmapData?
Скажем, у меня есть BitmapData 600x600, и я хочу уменьшить его до 100x100.
6 ответов
Это работает:
var scale:Number = 1.0/6.0;
var matrix:Matrix = new Matrix();
matrix.scale(scale, scale);
var smallBMD:BitmapData = new BitmapData(bigBMD.width * scale, bigBMD.height * scale, true, 0x000000);
smallBMD.draw(bigBMD, matrix, null, null, null, true);
var bitmap:Bitmap = new Bitmap(smallBMD, PixelSnapping.NEVER, true);
public function drawScaled(obj:IBitmapDrawable, thumbWidth:Number, thumbHeight:Number):Bitmap {
var m:Matrix = new Matrix();
m.scale(WIDTH / obj.width, HEIGHT / obj.height);
var bmp:BitmapData = new BitmapData(thumbWidth, thumbHeight, false);
bmp.draw(obj, m);
return new Bitmap(bmp);
}
IBitmapDrawable - это интерфейс для DisplayObject и BitmapData.
от: http://www.nightdrops.com/2009/02/quick-reference-drawing-a-scaled-object-in-actionscript/
С сглаживанием:
function BitmapScaled(source:IBitmapDrawable, thumbWidth:Number, thumbHeight:Number):BitmapData {
var mat:Matrix = new Matrix();
mat.scale(thumbWidth/source.width, thumbHeight/source.height);
var bmpd_draw:BitmapData = new BitmapData(thumbWidth, thumbHeight, false);
bmpd_draw.draw(source, mat, null, null, null, true);
return bmpd_draw;
}
Метод draw принимает IBitmapDrawable, который является интерфейсом для DisplayObject и BitmapData.
Без написания кода сам. Для этого я бы хотел создать новый объект BitmapData нужного размера, а затем использовать метод bitmap.draw для копирования большого в маленький. Метод bitmap.draw также принимает аргумент матрицы, который можно использовать для масштабирования при копировании.
Вот вариант выше, который добавляет поддержку масштабирования, растяжения и почтового ящика. Это может не обеспечить поддержку отсечения.
var newSizeBitmapData:BitmapData = resizeBitmapData(myBitmapData, newWidth, newHeight);
/**
* Resize display object or bitmap data to a new size
**/
public static function resizeBitmapData(bitmapDrawable:IBitmapDrawable, width:Number, height:Number, scaleMode:String="none",
smooth:Boolean = true, transparent:Boolean = true, fillColor:Number = 0x00000000):BitmapData {
var sizedBitmapData:BitmapData;
var matrix:Matrix;
matrix = getSizeByScaleMode(width, height, Object(bitmapDrawable).width, Object(bitmapDrawable).height, scaleMode);
sizedBitmapData = new BitmapData(width, height, transparent, fillColor);
sizedBitmapData.draw(bitmapDrawable, matrix, null, null, null, smooth);
return sizedBitmapData;
}
// Get correct scale. Inspired from code in Apache Flex (license Apache 2.0)
public static function getSizeByScaleMode(maxWidth:int, maxHeight:int,
width:int, height:int,
scaleMode:String="letterbox",
dpi:Number=NaN):Matrix {
var aspectRatio:String = (maxWidth < maxHeight) ? "portrait" : "landscape";
var orientation:String = aspectRatio;
var matrix:Matrix = new Matrix();
var scaleX:Number = 1;
var scaleY:Number = 1;
switch(scaleMode) {
case "zoom":
scaleX = Math.max( maxWidth / width, maxHeight / height);
scaleY = scaleX;
break;
case "letterbox":
scaleX = Math.min( maxWidth / width, maxHeight / height);
scaleY = scaleX;
break;
case "stretch":
scaleX = maxWidth / width;
scaleY = maxHeight / height;
break;
}
if (scaleX != 1 || scaleY != 0) {
width *= scaleX;
height *= scaleY;
matrix.scale(scaleX, scaleY);
}
matrix.translate(-width / 2, -height / 2);
matrix.translate(maxWidth / 2, maxHeight / 2);
return matrix;
}
Проблема с использованием матричного масштабирования заключается в том, что он не выполняет сглаживание или сглаживание - это, вероятно, нормально, если вы уверены, что когда-либо выполняли только масштабирование, но более общий метод будет использовать класс Image для изменения размера. В AS3 это никогда не будет добавлено в список отображения, поэтому будет использоваться просто "за кадром". Примерно так (с вашими растровыми данными как "sourceBitmapData"):
var image:Image = new Image();
image.load(new Bitmap(sourceBitmapData, PixelSnapping.NEVER, true));
var scale:uint = 100/600; // this is from your example of 600x600 => 100x100
var scaledWidth:uint = sourceBitmapData.width * scale;
var scaledHeight:uint = sourceBitmapData.height * scale;
image.content.width = scaledWidth;
image.content.height = scaledHeight;
var scaledBitmapData:BitmapData = new BitmapData(scaledWidth, scaledHeight);
scaledBitmapData.draw(image.content);
image = null;
Затем вы можете использовать "scaledBitmapData" вместо "sourceBitmapData", чтобы делать что угодно.