前段时间我使用WinRT API编写了一些代码来修改现代UI WinJS应用程序中的图像大小。
现在我被要求将图像分辨率更改为其最大值的2.7倍(不要问)。
问题是我无法找到正确的方法 - 如果存在 - 使用WinRT设置图像的分辨率。
到目前为止,这是代码。请注意,它会考虑多个帧图像(如GIF)。
function resizePictureAsync(file) {
const MAX_HEIGHT = 1600,
MAX_WIDTH = 1600,
RATIO_FOR_TWO_COLUMN_WORD_FIT = 2.7;
var inStream = null, outStream = null;
return file.openAsync(Windows.Storage.FileAccessMode.read).then(function (stream) {
inStream = stream;
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(stream);
}).then(function (decoder) {
return Windows.Storage.ApplicationData.current.temporaryFolder.createFileAsync("temp-picture-resize", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (resizedFile) {
return resizedFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
outStream = stream;
return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(outStream, decoder);
}).then(function (encoder) {
var framesMasterPromise = WinJS.Promise.wrap(null);
for (var i = 0; i < decoder.frameCount; i++) {
(function (i) {
framesMasterPromise = framesMasterPromise.then(function () {
return decoder.getFrameAsync(i).then(function (bitmapFrame) {
return bitmapFrame.getPixelDataAsync().then(function (pixelDataContainer) {
var pixelData = pixelDataContainer.detachPixelData();
var newWidth = bitmapFrame.orientedPixelWidth,
newHeight = bitmapFrame.orientedPixelHeight;
if (bitmapFrame.orientedPixelWidth > MAX_WIDTH || bitmapFrame.orientedPixelHeight > MAX_HEIGHT) {
if (bitmapFrame.orientedPixelWidth > bitmapFrame.orientedPixelHeight) {
newWidth = MAX_WIDTH;
newHeight = Math.round(MAX_HEIGHT * bitmapFrame.orientedPixelHeight / bitmapFrame.orientedPixelWidth);
} else {
newWidth = Math.round(MAX_WIDTH * bitmapFrame.orientedPixelWidth / bitmapFrame.orientedPixelHeight);
newHeight = MAX_HEIGHT;
}
}
var biggestSide = Math.max(newWidth, newHeight);
var dpiForBothSides = biggestSide / RATIO_FOR_TWO_COLUMN_WORD_FIT;
encoder.setPixelData(
bitmapFrame.bitmapPixelFormat,
bitmapFrame.bitmapAlphaMode,
bitmapFrame.orientedPixelWidth,
bitmapFrame.orientedPixelHeight,
dpiForBothSides/*bitmapFrame.dpiX*/,
dpiForBothSides/*bitmapFrame.dpiY*/,
pixelData
);
encoder.bitmapTransform.scaledWidth = newWidth;
encoder.bitmapTransform.scaledHeight = newHeight;
if (i >= decoder.frameCount - 1)
return encoder.flushAsync();
return encoder.goToNextFrameAsync();
});
});
});
})(i);
}
return framesMasterPromise;
}).then(function () {
if (inStream) inStream.close();
if (outStream) outStream.close();
return resizedFile;
});
});
});
}
setPixelData()似乎是唯一接受分辨率的方法,但它对生成的图像没有影响。实际上,我可以删除整个 encoder.setPixelData(...)部分,看看根本没有变化。
getPixelDataAsync()可以使用其他参数,但这似乎没有帮助。
感谢您提供的任何帮助。
答案 0 :(得分:0)
知道了。找到了一些解决方案here。
我正在使用BitmapEncoder.CreateForTranscodingAsync我本来应该使用BitmapEncoder.CreateAsync,因为第一个是简单转换,不允许你更改图像分辨率(我只注意忽略值)。
这是完整的解决方案,需要一些重构:
function resizePictureAsync(file) {
var inStream = null, outStream = null;
return file.openAsync(Windows.Storage.FileAccessMode.read).then(function (stream) {
inStream = stream;
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(stream);
}).then(function (decoder) {
return Windows.Storage.ApplicationData.current.temporaryFolder.createFileAsync("temp-picture-resize", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (resizedFile) {
return resizedFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
outStream = stream;
outStream.size = 0;
var encoderCodecId = getEncoderCodecIdFromDecoderCodecId(decoder.decoderInformation.codecId);
return Windows.Graphics.Imaging.BitmapEncoder.createAsync(encoderCodecId, outStream);
}).then(function (encoder) {
return processAllBitmapFramesAsync(decoder, encoder);
}).then(function () {
return resizedFile;
});
});
}).then(null, function (err) {
var errorMessage = "Error transforming an image.\n" + err;
console.error(errorMessage);
return file;
}).then(function(resultFile) {
if (inStream) inStream.close();
if (outStream) outStream.close();
return resultFile;
});
};
function getEncoderCodecIdFromDecoderCodecId(decoderCodecId) {
var encoderCodecId;
switch (decoderCodecId) {
case Windows.Graphics.Imaging.BitmapDecoder.bmpDecoderId:
encoderCodecId = Windows.Graphics.Imaging.BitmapEncoder.bmpEncoderId;
break;
case Windows.Graphics.Imaging.BitmapDecoder.jpegDecoderId:
encoderCodecId = Windows.Graphics.Imaging.BitmapEncoder.jpegEncoderId;
break;
case Windows.Graphics.Imaging.BitmapDecoder.jpegXRDecoderId:
encoderCodecId = Windows.Graphics.Imaging.BitmapEncoder.jpegXREncoderId;
break;
case Windows.Graphics.Imaging.BitmapDecoder.gifDecoderId:
encoderCodecId = Windows.Graphics.Imaging.BitmapEncoder.gifEncoderId;
break;
case Windows.Graphics.Imaging.BitmapDecoder.pngDecoderId:
encoderCodecId = Windows.Graphics.Imaging.BitmapEncoder.pngEncoderId;
break;
case Windows.Graphics.Imaging.BitmapDecoder.tiffDecoderId:
encoderCodecId = Windows.Graphics.Imaging.BitmapEncoder.tiffEncoderId;
break;
default:
throw new Error("Impossible de déterminer le codec de l'encoder à partir de celui du decoder");
break;
}
return encoderCodecId;
}
function processAllBitmapFramesAsync(decoder, encoder) {
var framesMasterPromise = WinJS.Promise.wrap(null);
for (var i = 0; i < decoder.frameCount; i++) {
(function (i) {
framesMasterPromise = framesMasterPromise.then(function () {
return decoder.getFrameAsync(i).then(function (bitmapFrame) {
return processBitmapFrameAsync(bitmapFrame, encoder);
}).then(function () {
if (i >= decoder.frameCount - 1)
return encoder.flushAsync();
return encoder.goToNextFrameAsync();
});
});
})(i);
}
return framesMasterPromise;
}
function processBitmapFrameAsync(bitmapFrame, encoder) {
const MAX_HEIGHT = 1600,
MAX_WIDTH = 1600,
RATIO_FOR_TWO_COLUMN_WORD_FIT = 2.7;
var newWidth = bitmapFrame.orientedPixelWidth,
newHeight = bitmapFrame.orientedPixelHeight;
if (bitmapFrame.orientedPixelWidth > MAX_WIDTH || bitmapFrame.orientedPixelHeight > MAX_HEIGHT) {
if (bitmapFrame.orientedPixelWidth > bitmapFrame.orientedPixelHeight) {
newWidth = MAX_WIDTH;
newHeight = Math.round(MAX_HEIGHT * bitmapFrame.orientedPixelHeight / bitmapFrame.orientedPixelWidth);
} else {
newWidth = Math.round(MAX_WIDTH * bitmapFrame.orientedPixelWidth / bitmapFrame.orientedPixelHeight);
newHeight = MAX_HEIGHT;
}
}
var biggestSide = Math.max(newWidth, newHeight);
var dpiForBothSides = biggestSide / RATIO_FOR_TWO_COLUMN_WORD_FIT;
return bitmapFrame.getPixelDataAsync().then(function(pixelDataContainer) {
var pixelData = pixelDataContainer.detachPixelData();
encoder.setPixelData(
bitmapFrame.bitmapPixelFormat,
bitmapFrame.bitmapAlphaMode,
bitmapFrame.orientedPixelWidth,
bitmapFrame.orientedPixelHeight,
dpiForBothSides /*bitmapFrame.dpiX*/,
dpiForBothSides /*bitmapFrame.dpiY*/,
pixelData
);
encoder.bitmapTransform.scaledWidth = newWidth;
encoder.bitmapTransform.scaledHeight = newHeight;
});
}