@applitools/image
Advanced tools
Comparing version 1.0.36 to 1.1.0
# Changelog | ||
## [1.1.0](https://github.com/applitools/eyes.sdk.javascript1/compare/js/image@1.0.36...js/image@1.1.0) (2023-07-10) | ||
### Features | ||
* prevent animated gif images from playing in ufg ([#1721](https://github.com/applitools/eyes.sdk.javascript1/issues/1721)) ([30f39cc](https://github.com/applitools/eyes.sdk.javascript1/commit/30f39cc8ef2cdfa1d85bd7a0037b818db1b52e1b)) | ||
## [1.0.36](https://github.com/applitools/eyes.sdk.javascript1/compare/js/image@1.0.35...js/image@1.0.36) (2023-06-28) | ||
@@ -4,0 +11,0 @@ |
@@ -30,8 +30,8 @@ "use strict"; | ||
exports.makeImage = void 0; | ||
const png_1 = require("./formats/png"); | ||
const jpeg_1 = require("./formats/jpeg"); | ||
const bmp_1 = require("./formats/bmp"); | ||
const gif_1 = require("./formats/gif"); | ||
const fs_1 = __importDefault(require("fs")); | ||
const stream_1 = __importDefault(require("stream")); | ||
const path_1 = __importDefault(require("path")); | ||
const png = __importStar(require("png-async")); | ||
const jpeg = __importStar(require("jpeg-js")); | ||
const bmp = __importStar(require("bmpimagejs")); | ||
const utils = __importStar(require("@applitools/utils")); | ||
@@ -48,14 +48,18 @@ function makeImage(data) { | ||
else if (Buffer.isBuffer(data)) { | ||
if (isPngBuffer(data)) { | ||
image = fromPngBuffer(data); | ||
size = extractPngSize(data); | ||
if ((0, png_1.isPngBuffer)(data)) { | ||
image = (0, png_1.fromPngBuffer)(data); | ||
size = (0, png_1.extractPngSize)(data); | ||
} | ||
else if (isJpegBuffer(data)) { | ||
image = fromJpegBuffer(data); | ||
size = extractJpegSize(data); | ||
else if ((0, jpeg_1.isJpegBuffer)(data)) { | ||
image = (0, jpeg_1.fromJpegBuffer)(data); | ||
size = (0, jpeg_1.extractJpegSize)(data); | ||
} | ||
else if (isBmpBuffer(data)) { | ||
image = fromBmpBuffer(data); | ||
size = extractBmpSize(data); | ||
else if ((0, bmp_1.isBmpBuffer)(data)) { | ||
image = (0, bmp_1.fromBmpBuffer)(data); | ||
size = (0, bmp_1.extractBmpSize)(data); | ||
} | ||
else if ((0, gif_1.isGifBuffer)(data)) { | ||
image = (0, gif_1.fromGifBuffer)(data); | ||
size = (0, gif_1.extractGifSize)(data); | ||
} | ||
else { | ||
@@ -183,3 +187,3 @@ throw new Error('Unable to create an image abstraction from buffer with unknown data'); | ||
async toPng() { | ||
return toPng(await this.toObject()); | ||
return (0, png_1.toPng)(await this.toObject()); | ||
}, | ||
@@ -206,74 +210,7 @@ async toFile(path) { | ||
exports.makeImage = makeImage; | ||
function isPngBuffer(buffer) { | ||
return buffer.slice(12, 16).toString('ascii') === 'IHDR'; | ||
} | ||
function isJpegBuffer(buffer) { | ||
return ['JFIF', 'Exif'].includes(buffer.slice(6, 10).toString('ascii')); | ||
} | ||
function isBmpBuffer(buffer) { | ||
return buffer.slice(0, 2).toString('ascii') === 'BM'; | ||
} | ||
function extractPngSize(buffer) { | ||
return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) }; | ||
} | ||
function extractJpegSize(buffer) { | ||
// skip file signature | ||
let offset = 4; | ||
while (buffer.length > offset) { | ||
// extract length of the block | ||
offset += buffer.readUInt16BE(offset); | ||
// if next segment is SOF0 or SOF2 extract size | ||
if (buffer[offset + 1] === 0xc0 || buffer[offset + 1] === 0xc2) { | ||
return { width: buffer.readUInt16BE(offset + 7), height: buffer.readUInt16BE(offset + 5) }; | ||
} | ||
else { | ||
// skip block signature | ||
offset += 2; | ||
} | ||
} | ||
return { width: 0, height: 0 }; | ||
} | ||
function extractBmpSize(buffer) { | ||
return { width: buffer.readUInt32LE(18), height: buffer.readUInt32LE(22) }; | ||
} | ||
function fromSize(size) { | ||
return new png.Image({ width: size.width, height: size.height }); | ||
return { ...size, data: Buffer.alloc(4 * size.width * size.height) }; | ||
} | ||
async function fromPngBuffer(buffer) { | ||
return new Promise((resolve, reject) => { | ||
const image = new png.Image(); | ||
image.parse(buffer, (err, image) => { | ||
if (err) | ||
return reject(err); | ||
resolve(image); | ||
}); | ||
}); | ||
} | ||
async function fromJpegBuffer(buffer) { | ||
return jpeg.decode(buffer, { tolerantDecoding: true, formatAsRGBA: true }); | ||
} | ||
async function fromBmpBuffer(buffer) { | ||
const image = bmp.decode(buffer); | ||
return { data: Buffer.from(image.pixels), width: image.width, height: image.height }; | ||
} | ||
async function toPng(image) { | ||
return new Promise((resolve, reject) => { | ||
let buffer = Buffer.alloc(0); | ||
const writable = new stream_1.default.Writable({ | ||
write(chunk, _encoding, next) { | ||
buffer = Buffer.concat([buffer, chunk]); | ||
next(); | ||
}, | ||
}); | ||
const wrapper = new png.Image({ width: image.width, height: image.height }); | ||
wrapper.data = image.data; | ||
wrapper | ||
.pack() | ||
.pipe(writable) | ||
.on('finish', () => resolve(buffer)) | ||
.on('error', (err) => reject(err)); | ||
}); | ||
} | ||
async function toFile(image, filepath) { | ||
const buffer = await toPng(image); | ||
const buffer = await (0, png_1.toPng)(image); | ||
return new Promise((resolve, reject) => { | ||
@@ -293,3 +230,3 @@ fs_1.default.mkdirSync(path_1.default.dirname(filepath), { recursive: true }); | ||
: imageOrSize; | ||
image = new png.Image(size); | ||
image = fromSize(size); | ||
} | ||
@@ -346,3 +283,3 @@ image = await transforms.modifiers.reduce(async (image, modifier) => { | ||
} | ||
const extracted = new png.Image(dstSize); | ||
const extracted = fromSize(dstSize); | ||
if (srcX === 0 && dstWidth === image.width) { | ||
@@ -364,3 +301,3 @@ const srcOffset = srcY * image.width * 4; | ||
degrees = (360 + degrees) % 360; | ||
const dstImage = new png.Image({ width: image.width, height: image.height }); | ||
const dstImage = fromSize({ width: image.width, height: image.height }); | ||
if (degrees === 90) { | ||
@@ -430,3 +367,3 @@ dstImage.width = image.height; | ||
} | ||
const dstImage = new png.Image({ | ||
const dstImage = fromSize({ | ||
width: topImage.width + Math.max(srcImage.width - region.width, 0), | ||
@@ -433,0 +370,0 @@ height: topImage.height + Math.max(srcImage.height - region.height, 0), |
@@ -18,1 +18,5 @@ "use strict"; | ||
__exportStar(require("./image"), exports); | ||
__exportStar(require("./formats/png"), exports); | ||
__exportStar(require("./formats/jpeg"), exports); | ||
__exportStar(require("./formats/bmp"), exports); | ||
__exportStar(require("./formats/gif"), exports); |
{ | ||
"name": "@applitools/image", | ||
"version": "1.0.36", | ||
"version": "1.1.0", | ||
"description": "Image primitive used for capturing and manipulating screenshots", | ||
@@ -42,2 +42,3 @@ "homepage": "https://applitools.com", | ||
"jpeg-js": "0.4.4", | ||
"omggif": "1.0.10", | ||
"png-async": "0.9.4" | ||
@@ -47,2 +48,3 @@ }, | ||
"@types/node": "^12.20.55", | ||
"@types/omggif": "^1.0.3", | ||
"@types/pixelmatch": "^5.2.4", | ||
@@ -49,0 +51,0 @@ "pixelmatch": "^5.3.0" |
/// <reference types="node" /> | ||
import type { ImageRaw } from './types'; | ||
import type { Location, Size, Region } from '@applitools/utils'; | ||
@@ -28,7 +29,2 @@ export interface Image { | ||
}; | ||
type ImageRaw = { | ||
width: number; | ||
height: number; | ||
data: Buffer; | ||
}; | ||
type Transforms = { | ||
@@ -35,0 +31,0 @@ rotate: number; |
export * from './image'; | ||
export * from './formats/png'; | ||
export * from './formats/jpeg'; | ||
export * from './formats/bmp'; | ||
export * from './formats/gif'; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55649
17
914
5
4
+ Addedomggif@1.0.10
+ Addedomggif@1.0.10(transitive)