🌈 Added a color histogram method
This commit is contained in:
@@ -121,7 +121,7 @@ export default class ApiService extends Service {
|
|||||||
usePolling: true,
|
usePolling: true,
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
atomic: true,
|
atomic: true,
|
||||||
depth: 1,
|
depth: 10,
|
||||||
awaitWriteFinish: {
|
awaitWriteFinish: {
|
||||||
stabilityThreshold: 2000,
|
stabilityThreshold: 2000,
|
||||||
pollInterval: 100,
|
pollInterval: 100,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
Errors,
|
Errors,
|
||||||
} from "moleculer";
|
} from "moleculer";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { analyze, resizeImage } from "../utils/imagetransformation.utils";
|
import { analyze, getColorHistogramData, resizeImage } from "../utils/imagetransformation.utils";
|
||||||
export default class ImageTransformation extends Service {
|
export default class ImageTransformation extends Service {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
public constructor(
|
public constructor(
|
||||||
@@ -62,9 +62,15 @@ export default class ImageTransformation extends Service {
|
|||||||
const url = new URL(ctx.params.imageFilePath);
|
const url = new URL(ctx.params.imageFilePath);
|
||||||
const pathName = url.pathname;
|
const pathName = url.pathname;
|
||||||
const decodedImageFileURI = decodeURI(pathName);
|
const decodedImageFileURI = decodeURI(pathName);
|
||||||
|
const finalImagePath = path.resolve("." + decodedImageFileURI);
|
||||||
|
|
||||||
return await analyze(path.resolve("." + decodedImageFileURI));
|
const analyzedData = await analyze(finalImagePath);
|
||||||
|
const colorHistogramData = await getColorHistogramData(finalImagePath, false);
|
||||||
|
|
||||||
|
return {
|
||||||
|
analyzedData,
|
||||||
|
colorHistogramData,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ export default class ImportService extends Service {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
inferredMetadata: {
|
inferredMetadata: {
|
||||||
issue: Object,
|
issue: Object;
|
||||||
},
|
};
|
||||||
rawFileDetails: {
|
rawFileDetails: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
@@ -166,7 +166,7 @@ export default class ImportService extends Service {
|
|||||||
) {
|
) {
|
||||||
let volumeDetails;
|
let volumeDetails;
|
||||||
const comicMetadata = ctx.params;
|
const comicMetadata = ctx.params;
|
||||||
|
|
||||||
// When an issue is added from the search CV feature
|
// When an issue is added from the search CV feature
|
||||||
if (
|
if (
|
||||||
comicMetadata.sourcedMetadata.comicvine &&
|
comicMetadata.sourcedMetadata.comicvine &&
|
||||||
@@ -191,7 +191,7 @@ export default class ImportService extends Service {
|
|||||||
resolve(data);
|
resolve(data);
|
||||||
} else if (error) {
|
} else if (error) {
|
||||||
console.log("data", data);
|
console.log("data", data);
|
||||||
console.log("error", error)
|
console.log("error", error);
|
||||||
throw new Errors.MoleculerError(
|
throw new Errors.MoleculerError(
|
||||||
"Failed to import comic book",
|
"Failed to import comic book",
|
||||||
400,
|
400,
|
||||||
@@ -400,7 +400,7 @@ export default class ImportService extends Service {
|
|||||||
];
|
];
|
||||||
}>
|
}>
|
||||||
) => {
|
) => {
|
||||||
// 2a. Enqueue the Elasticsearch job
|
// 2a. Elasticsearch query
|
||||||
const { queryObjects } = ctx.params;
|
const { queryObjects } = ctx.params;
|
||||||
// construct the query for ElasticSearch
|
// construct the query for ElasticSearch
|
||||||
let elasticSearchQuery = {};
|
let elasticSearchQuery = {};
|
||||||
@@ -426,7 +426,10 @@ export default class ImportService extends Service {
|
|||||||
{
|
{
|
||||||
term: {
|
term: {
|
||||||
"inferredMetadata.issue.number":
|
"inferredMetadata.issue.number":
|
||||||
parseInt(queryObject.issueNumber, 10),
|
parseInt(
|
||||||
|
queryObject.issueNumber,
|
||||||
|
10
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -438,29 +441,8 @@ export default class ImportService extends Service {
|
|||||||
index: "comics",
|
index: "comics",
|
||||||
search_type: "dfs_query_then_fetch",
|
search_type: "dfs_query_then_fetch",
|
||||||
},
|
},
|
||||||
// { issueId: queryObject.issueId },
|
|
||||||
{
|
{
|
||||||
query: elasticSearchQuery,
|
query: elasticSearchQuery,
|
||||||
// script_fields: {
|
|
||||||
// issueId: {
|
|
||||||
// script: {
|
|
||||||
// lang: "painless",
|
|
||||||
// params: {
|
|
||||||
// match: {
|
|
||||||
// issueId:
|
|
||||||
// queryObject.issueId,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// inline: "params.match",
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// fileName: {
|
|
||||||
// script: {
|
|
||||||
// lang: "painless",
|
|
||||||
// inline: "params['_source']['rawFileDetails']",
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -473,11 +455,15 @@ export default class ImportService extends Service {
|
|||||||
elasticSearchQueries,
|
elasticSearchQueries,
|
||||||
queryObjects,
|
queryObjects,
|
||||||
});
|
});
|
||||||
// await ctx.broker.call("queue.issuesForSeries", {
|
|
||||||
// elasticSearchQueries,
|
|
||||||
// });
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
libraryStatistics: {
|
||||||
|
rest: "GET /libraryStatistics",
|
||||||
|
params: {},
|
||||||
|
handler: async (ctx: Context<{}>) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
flushDB: {
|
flushDB: {
|
||||||
rest: "POST /flushDB",
|
rest: "POST /flushDB",
|
||||||
params: {},
|
params: {},
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ export const resizeImage = async (
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Image file resized with the following parameters: %o", info);
|
console.log(
|
||||||
|
"Image file resized with the following parameters: %o",
|
||||||
|
info
|
||||||
|
);
|
||||||
return info;
|
return info;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -44,7 +47,63 @@ export const analyze = async (inputFilePath: string | Buffer) => {
|
|||||||
const stats = await sharp(inputFilePath).stats();
|
const stats = await sharp(inputFilePath).stats();
|
||||||
// const { r, g, b } = dominant;
|
// const { r, g, b } = dominant;
|
||||||
return stats;
|
return stats;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const getColorHistogramData = async (
|
||||||
|
inputFilePath: string | Buffer,
|
||||||
|
isValueHistogram: Boolean
|
||||||
|
) => {
|
||||||
|
const { data, info } = await sharp(inputFilePath)
|
||||||
|
// output the raw pixels
|
||||||
|
.raw()
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
const src = new Uint32Array(data.buffer);
|
||||||
|
// const src = new Uint8ClampedArray(data.buffer);
|
||||||
|
console.log(src);
|
||||||
|
|
||||||
|
let histBrightness = new Array(256).fill(0);
|
||||||
|
let histR = new Array(256).fill(0);
|
||||||
|
let histG = new Array(256).fill(0);
|
||||||
|
let histB = new Array(256).fill(0);
|
||||||
|
|
||||||
|
for (let i = 0; i < src.length; i++) {
|
||||||
|
let r = src[i] & 0xff;
|
||||||
|
let g = (src[i] >> 8) & 0xff;
|
||||||
|
let b = (src[i] >> 16) & 0xff;
|
||||||
|
histBrightness[r]++;
|
||||||
|
histBrightness[g]++;
|
||||||
|
histBrightness[b]++;
|
||||||
|
histR[r]++;
|
||||||
|
histG[g]++;
|
||||||
|
histB[b]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxBrightness = 0;
|
||||||
|
if (isValueHistogram) {
|
||||||
|
for (let i = 1; i < 256; i++) {
|
||||||
|
if (maxBrightness < histBrightness[i]) {
|
||||||
|
maxBrightness = histBrightness[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < 256; i++) {
|
||||||
|
if (maxBrightness < histR[i]) {
|
||||||
|
maxBrightness = histR[i];
|
||||||
|
} else if (maxBrightness < histG[i]) {
|
||||||
|
maxBrightness = histG[i];
|
||||||
|
} else if (maxBrightness < histB[i]) {
|
||||||
|
maxBrightness = histB[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
r: histR,
|
||||||
|
g: histG,
|
||||||
|
b: histB,
|
||||||
|
maxBrightness,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const calculateLevenshteinDistance = async (
|
export const calculateLevenshteinDistance = async (
|
||||||
imagePath1: string,
|
imagePath1: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user