UNPKG

@ngageoint/mage.image.service

Version:

Orient images attached to MAGE observations according to EXIF meta-data and generate configurable size thumbnails.

178 lines 9.71 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const adapters_images_sharp_1 = require("./adapters.images.sharp"); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const stream_1 = __importDefault(require("stream")); const sharp_1 = __importDefault(require("sharp")); const jimp_1 = __importDefault(require("jimp")); const util_spec_1 = require("./util.spec"); const imageBasePath = path_1.default.resolve(__dirname, '..', 'spec'); const unorientedPath = path_1.default.resolve(imageBasePath, 'majestic_ram.orient.raw-6.tag-6.jpg'); describe('sharp image service', () => { describe('auto-orient', () => { it('rotates the image to the correct orientation', () => __awaiter(void 0, void 0, void 0, function* () { const service = (0, adapters_images_sharp_1.SharpImageService)(); const source = { mediaType: 'image/jpeg', bytes: fs_1.default.createReadStream(unorientedPath) }; const dest = new util_spec_1.BufferWriteable(); const oriented = yield service.autoOrient(source, dest); if (oriented instanceof Error) { return fail(oriented); } const expectedPixels = yield (0, sharp_1.default)(path_1.default.resolve(imageBasePath, 'majestic_ram.oriented.jpg')).toBuffer(); const orientedByServiceJimp = yield jimp_1.default.read(dest.content); const expectedJimp = yield jimp_1.default.read(expectedPixels); const percentDifferent = jimp_1.default.diff(orientedByServiceJimp, expectedJimp).percent; expect(percentDifferent).toBeLessThan(1); expect(oriented.sizeInBytes).toEqual(dest.content.length); expect(Math.abs(oriented.sizeInBytes - expectedPixels.length)).toBeLessThanOrEqual(1000); expect(oriented).toEqual(jasmine.objectContaining({ mediaType: 'image/jpeg', dimensions: { width: 720, height: 720 } })); })); }); describe('scaling', () => { const service = (0, adapters_images_sharp_1.SharpImageService)(); it('scales the height to the target when height is less than width', () => __awaiter(void 0, void 0, void 0, function* () { const source = { bytes: fs_1.default.createReadStream(path_1.default.resolve(imageBasePath, 'tumbeasts-1800x1140.png')), dimensions: { width: 1800, height: 1140 } }; const dest = new util_spec_1.BufferWriteable(); const scaled = yield service.scaleToDimension(76, source, dest); if (scaled instanceof Error) { return fail(scaled); } const expectedPixels = yield (0, sharp_1.default)(path_1.default.resolve(imageBasePath, 'tumbeasts-120x76.png')).toBuffer(); const scaledJimp = yield jimp_1.default.read(dest.content); const expectedJimp = yield jimp_1.default.read(expectedPixels); const percentDifferent = jimp_1.default.diff(scaledJimp, expectedJimp).percent; expect(scaled).toEqual(jasmine.objectContaining({ mediaType: 'image/png', dimensions: { width: 120, height: 76 } })); expect(scaled.sizeInBytes).toEqual(dest.content.length); expect(Math.abs(scaled.sizeInBytes - expectedPixels.length)).toBeLessThanOrEqual(1200); expect(percentDifferent).toBeLessThan(1); })); it('scales the width to the target when width is less than height', () => __awaiter(void 0, void 0, void 0, function* () { const source = { bytes: fs_1.default.createReadStream(path_1.default.resolve(imageBasePath, 'tumbeasts-1140x1800.png')), dimensions: { width: 1140, height: 1800 } }; const dest = new util_spec_1.BufferWriteable(); const scaled = yield service.scaleToDimension(76, source, dest); if (scaled instanceof Error) { return fail(scaled); } const expectedPixels = yield (0, sharp_1.default)(path_1.default.resolve(imageBasePath, 'tumbeasts-76x120.png')).toBuffer(); const scaledJimp = yield jimp_1.default.read(dest.content); const expectedJimp = yield jimp_1.default.read(expectedPixels); const percentDifferent = jimp_1.default.diff(scaledJimp, expectedJimp).percent; expect(scaled).toEqual(jasmine.objectContaining({ mediaType: 'image/png', dimensions: { width: 76, height: 120 } })); expect(scaled.sizeInBytes).toEqual(dest.content.length); expect(Math.abs(scaled.sizeInBytes - expectedPixels.length)).toBeLessThanOrEqual(1000); expect(percentDifferent).toBeLessThan(2); })); it('uses the given dimension even when they are not accurate', () => __awaiter(void 0, void 0, void 0, function* () { const source = { bytes: fs_1.default.createReadStream(path_1.default.resolve(imageBasePath, 'tumbeasts-1140x1800.png')), dimensions: { width: 1800, height: 1140 } }; const dest = new util_spec_1.BufferWriteable(); const scaled = yield service.scaleToDimension(76, source, dest); if (scaled instanceof Error) { return fail(scaled); } const expectedPixels = yield (0, sharp_1.default)(path_1.default.resolve(imageBasePath, 'tumbeasts-48x76.png')).toBuffer(); const scaledJimp = yield jimp_1.default.read(dest.content); const expectedJimp = yield jimp_1.default.read(expectedPixels); const percentDifferent = jimp_1.default.diff(scaledJimp, expectedJimp).percent; expect(scaled).toEqual(jasmine.objectContaining({ mediaType: 'image/png', dimensions: { width: 48, height: 76 } })); expect(scaled.sizeInBytes).toEqual(dest.content.length); expect(Math.abs(scaled.sizeInBytes - expectedPixels.length)).toBeLessThanOrEqual(1000); expect(percentDifferent).toBeLessThan(2); })); it('scales the height to the target size when the source has no dimensions', () => __awaiter(void 0, void 0, void 0, function* () { const source = { bytes: fs_1.default.createReadStream(path_1.default.resolve(imageBasePath, 'tumbeasts-1140x1800.png')), }; const dest = new util_spec_1.BufferWriteable(); const scaled = yield service.scaleToDimension(76, source, dest); if (scaled instanceof Error) { return fail(scaled); } const expectedPixels = yield (0, sharp_1.default)(path_1.default.resolve(imageBasePath, 'tumbeasts-48x76.png')).toBuffer(); const scaledJimp = yield jimp_1.default.read(dest.content); const expectedJimp = yield jimp_1.default.read(expectedPixels); const percentDifferent = jimp_1.default.diff(scaledJimp, expectedJimp).percent; expect(scaled).toEqual(jasmine.objectContaining({ mediaType: 'image/png', dimensions: { width: 48, height: 76 } })); expect(scaled.sizeInBytes).toEqual(dest.content.length); expect(Math.abs(scaled.sizeInBytes - expectedPixels.length)).toBeLessThanOrEqual(1000); expect(percentDifferent).toBeLessThan(2); })); }); describe('corrupted image tolerance', () => { it('returns an error loading this test image found on a demo server', () => __awaiter(void 0, void 0, void 0, function* () { const service = (0, adapters_images_sharp_1.SharpImageService)(); const corruptedBytes = fs_1.default.readFileSync(path_1.default.join(imageBasePath, 'corrupted.jpeg')); const corruptedSource = { mediaType: 'image/jpeg', bytes: stream_1.default.Readable.from(corruptedBytes) }; const corruptedDest = new util_spec_1.BufferWriteable(); const err = yield service.autoOrient(corruptedSource, corruptedDest); expect(err).toBeInstanceOf(Error); })); }); }); //# sourceMappingURL=adapters.images.sharp.spec.js.map