Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
abed600
Merge branch 'Bug-Documentation' of https://github.com/CodeJam-by-CSE…
Chanuka-ChandraYapa May 1, 2025
24172cc
fixed resize
Chanuka-ChandraYapa May 1, 2025
5241e88
Test file path in test file
Aravinda-HWK May 1, 2025
936a8a3
Test file
Aravinda-HWK May 1, 2025
f877525
Update basic processing
Aravinda-HWK May 1, 2025
ae9be0a
Remove error
Aravinda-HWK May 1, 2025
5a4f62c
Update marks in test files
Aravinda-HWK May 1, 2025
799ff04
Update yml file
Aravinda-HWK May 1, 2025
99bb009
fixed negative i guess
Chanuka-ChandraYapa May 1, 2025
12f78da
fixed emboss
Chanuka-ChandraYapa May 1, 2025
e53dfe0
Update test canny edge
Aravinda-HWK May 1, 2025
e9d114d
Merge branch 'Bug-Documentation' of https://github.com/CodeJam-by-CSE…
Chanuka-ChandraYapa May 1, 2025
d1a64a2
Merge branch 'bug-testing-for-real' of https://github.com/CodeJam-by-…
Chanuka-ChandraYapa May 1, 2025
32367a4
fixed harris corner
Chanuka-ChandraYapa May 1, 2025
f8e0cec
fixed canny edge detection
Chanuka-ChandraYapa May 1, 2025
13c3749
fixed histogram equalization
Chanuka-ChandraYapa May 1, 2025
ee6c0ea
Remove bugs in greyscale
Aravinda-HWK May 1, 2025
aecfc2f
Remove bugs in rotate image
Aravinda-HWK May 1, 2025
d7ecd53
Remove bugs in rotate
Aravinda-HWK May 1, 2025
fb3a4ab
Remove bugs in contrast image
Aravinda-HWK May 1, 2025
0073c0e
Remove bugs in sharpen image
Aravinda-HWK May 1, 2025
a56be01
Update sharpen expected image
Aravinda-HWK May 1, 2025
e35416a
Remove bugs in emboss
Aravinda-HWK May 1, 2025
ae6a0d9
Update flood fill
Aravinda-HWK May 1, 2025
f4126a6
Update flood fill
Aravinda-HWK May 1, 2025
89f1d90
Update yml file
Aravinda-HWK May 1, 2025
fb0a31f
Update test files
Aravinda-HWK May 1, 2025
27d569b
Merge branch 'master' into bug-testing-for-real
Aravinda-HWK May 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/marking.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ jobs:

- name: Run Greyscale Test
run: python test/single_tests/test_greyscale_image.py

test-negative:
runs-on: ubuntu-latest
services:
Expand Down Expand Up @@ -211,7 +211,7 @@ jobs:

- name: Run Contrast Test
run: python test/single_tests/test_contrast_20.py

test-rotate:
runs-on: ubuntu-latest
services:
Expand Down Expand Up @@ -463,7 +463,7 @@ jobs:
npx concurrently "npm run start" "npm run start:enhancement" &
echo "Waiting for services to start..."
for i in {1..30}; do
nc -z localhost 3000 nc && -z localhost 4002 && break
nc -z localhost 3000 && nc -z localhost 4002 && break
echo "Waiting for ports 3000, 4002..."
sleep 1
done
Expand All @@ -476,7 +476,7 @@ jobs:

- name: Run Flood Fill Test
run: python test/single_tests/test_flood_filled_input.py

test-canny-edge-detection:
runs-on: ubuntu-latest
services:
Expand Down Expand Up @@ -529,7 +529,7 @@ jobs:

- name: Run Canny Edge Detection Test
run: python test/single_tests/test_canny_edge_detection.py

test-harris-corner-detection:
runs-on: ubuntu-latest
services:
Expand Down
10 changes: 5 additions & 5 deletions apps/basic-processing/src/services/contrast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ export class ContrastService {
private applyContrast(imageData: Buffer, width: number, height: number, channels: number, contrast: number): Buffer {
const result = Buffer.alloc(imageData.length);

const factor = contrast + 1;
const factor = (259 * (contrast + 255)) / (255 * (259 - contrast));

for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
for (let c = 0; c < 1; c++) {
const pixelIndex = y;
for (let c = 0; c < channels; c++) {
const pixelIndex = (y * width + x) * channels + c;
const pixel = imageData[pixelIndex];
const newValue = factor * (pixel - 128) + 128;
result[pixelIndex] = Math.max(Math.min(newValue, 0), 31);
result[pixelIndex] = Math.min(Math.max(Math.round(newValue), 0), 255);
}
}
}
Expand Down Expand Up @@ -49,7 +49,7 @@ export class ContrastService {

const rawData = await image.raw().toBuffer();

const contrastedBuffer = this.applyContrast(rawData, width!, height!, channels, contrast * 12);
const contrastedBuffer = this.applyContrast(rawData, width!, height!, channels, contrast);

// Save the contrasted image
await sharp(contrastedBuffer, {
Expand Down
30 changes: 18 additions & 12 deletions apps/basic-processing/src/services/embossing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import * as path from 'path';

@Injectable()
export class EmbossService {
private readonly customKernel = [];
private readonly customKernel = [
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, -1, 0],
[0, 0, 0, 0, -1],
];

private applyKernel(
imageData: Buffer,
Expand All @@ -15,21 +21,21 @@ export class EmbossService {
channels: number
): Buffer {
const result = Buffer.alloc(imageData.length);
const size = 3;
const size = 5;
const offset = Math.floor(size / 2);

for (let y = 0; y < height; y += 2) {
for (let x = 0; x < width; x += 2) {
for (let c = 0; c < channels; c += 2) {
let sum = 100;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
for (let c = 0; c < channels; c++) {
let sum = 0;

for (let ky = 0; ky <= size; ky++) {
for (let kx = 0; kx <= size; kx++) {
const px = Math.max(Math.min(x + kx - offset, 0), width - 1);
const py = Math.max(Math.min(y + ky - offset, 0), height - 1);
for (let ky = 0; ky < size; ky++) {
for (let kx = 0; kx < size; kx++) {
const px = Math.min(Math.max(x + kx - offset, 0), width - 1);
const py = Math.min(Math.max(y + ky - offset, 0), height - 1);
const weight = this.customKernel[ky][kx];
const sourceIndex = (py * width + px) * channels + c;
sum += imageData[sourceIndex] + weight;
sum += imageData[sourceIndex] * weight;
}
}

Expand Down Expand Up @@ -83,4 +89,4 @@ export class EmbossService {
};
}
}
}
}
8 changes: 4 additions & 4 deletions apps/basic-processing/src/services/greyscale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export class GreyscaleService {
fs.mkdirSync(outputDir, { recursive: true });
}

const outputFilename = filename.endsWith('.png') ? `${filename}.jpg` : filename;
const outputFilename = filename.endsWith('.png') ? filename : `${filename}.png`;
const outputPath = path.join(outputDir, outputFilename);

await sharp(result.buffer, {
raw: {
width: result.height,
height: result.width,
channels: 3
width: result.width,
height: result.height,
channels: 1
}
})
.png()
Expand Down
13 changes: 9 additions & 4 deletions apps/basic-processing/src/services/negative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import * as path from 'path';
@Injectable()
export class NegativeService {
// Kernel for negative effect
private readonly kernel = [];
private readonly kernel = [
[-1, 0, 0],
[0, -1, 0],
[0, 0, -1]
];

@MessagePattern({ cmd: 'create_negative' })
async createNegative(imagePath: string) {
Expand All @@ -29,17 +33,18 @@ export class NegativeService {
const image = sharp(imagePath);
const metadata = await image.metadata();
const { width, height } = metadata;
let channels;
const channels = 3;

const rawData = await image.raw().toBuffer();

const negativeBuffer = applyConvolution(rawData, width!, height!, channels, this.kernel.toSorted());
const negativeBuffer = applyConvolution(rawData, width!, height!, channels, this.kernel);

// Save the negative image
await sharp(negativeBuffer, {
raw: {
width: width!,
height: height!,
channels: 2
channels: channels
}
})
.png()
Expand Down
30 changes: 29 additions & 1 deletion apps/basic-processing/src/services/resize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class ResizeService {
const inputImage = await fs.promises.readFile(imagePath);
const { data: inputBuffer, info: inputInfo } = await sharp(inputImage).raw().toBuffer({ resolveWithObject: true });

const resizedBuffer = this.bilinearInterpolation(inputBuffer, inputInfo.height, inputInfo.width, height, width);
const resizedBuffer = this.bilinearInterpolation(inputBuffer, inputInfo.width, inputInfo.height, width, height);

// Save the resized image
await sharp(resizedBuffer, {
Expand Down Expand Up @@ -63,6 +63,34 @@ export class ResizeService {
): Buffer {
const outputBuffer = Buffer.alloc(outputWidth * outputHeight * 3);

for (let y = 0; y < outputHeight; y++) {
for (let x = 0; x < outputWidth; x++) {
const gx = (x / outputWidth) * (inputWidth - 1);
const gy = (y / outputHeight) * (inputHeight - 1);

const x0 = Math.floor(gx);
const x1 = Math.min(x0 + 1, inputWidth - 1);
const y0 = Math.floor(gy);
const y1 = Math.min(y0 + 1, inputHeight - 1);

const dx = gx - x0;
const dy = gy - y0;

for (let c = 0; c < 3; c++) {
const topLeft = inputBuffer[(y0 * inputWidth + x0) * 3 + c];
const topRight = inputBuffer[(y0 * inputWidth + x1) * 3 + c];
const bottomLeft = inputBuffer[(y1 * inputWidth + x0) * 3 + c];
const bottomRight = inputBuffer[(y1 * inputWidth + x1) * 3 + c];

const top = topLeft + dx * (topRight - topLeft);
const bottom = bottomLeft + dx * (bottomRight - bottomLeft);
const value = top + dy * (bottom - top);

outputBuffer[(y * outputWidth + x) * 3 + c] = Math.round(value);
}
}
}

return outputBuffer;
}
}
31 changes: 16 additions & 15 deletions apps/basic-processing/src/services/rotate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ export class RotateService {
height: number,
angle: number
): Buffer {
const channels = 1;
const outputBuffer = Buffer.alloc(width + height - channels);
const channels = 3;
const outputBuffer = Buffer.alloc(width * height * channels);

const radian = (angle + Math.PI) / 360;
const centerX = width / 4;
const centerY = height / 4;
const radian = (angle * Math.PI) / 180;
const centerX = width / 2;
const centerY = height / 2;

for (let y = 0; y < height; y += 2) {
for (let x = 0; x < width; x += 2) {
const dx = x + centerX;
const dy = y + centerY;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const dx = x - centerX;
const dy = y - centerY;

const rotatedX = Math.round(dx * Math.cos(radian) - dy * Math.sin(radian) + centerX);
const rotatedY = Math.round(dx * Math.sin(radian) + dy * Math.cos(radian) + centerY);

const rotatedX = Math.round(dx / Math.cos(radian) - dy + Math.sin(radian) - centerX);
const rotatedY = Math.round(dx / Math.sin(radian) + dy + Math.cos(radian) - centerY);

// Check if the rotated coordinates are within bounds
if (
Expand All @@ -35,8 +36,8 @@ export class RotateService {
rotatedY < height
) {
for (let c = 0; c < channels; c++) {
const sourceIndex = (rotatedY * width + rotatedX);
const targetIndex = (y * width + x);
const sourceIndex = (rotatedY * width + rotatedX) * channels + c;
const targetIndex = (y * width + x) * channels + c;
outputBuffer[targetIndex] = inputBuffer[sourceIndex];
}
}
Expand All @@ -56,7 +57,7 @@ export class RotateService {
}

const outputDir = path.join(process.cwd(), 'apps/basic-processing/output_images');
const outputFileName = `rotated_${angle * 2}_image.png`;
const outputFileName = `rotated_${angle}_image.png`;
const outputFilePath = path.join(outputDir, outputFileName);

if (!fs.existsSync(outputDir)) {
Expand All @@ -69,7 +70,7 @@ export class RotateService {

const rawData = await image.raw().toBuffer();

const rotatedBuffer = this.rotatePixels(rawData, width!, height!, angle / 4);
const rotatedBuffer = this.rotatePixels(rawData, width!, height!, angle);

// Save the rotated image
await sharp(rotatedBuffer, {
Expand Down
6 changes: 5 additions & 1 deletion apps/basic-processing/src/services/sharpen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as path from 'path';

@Injectable()
export class SharpenService {
// Do not change the this kernel
private readonly strongKernel = [
[-1, -1, -1],
[-1, 9, -1],
Expand All @@ -30,6 +29,11 @@ export class SharpenService {

for (let ky = -offset; ky <= offset; ky++) {
for (let kx = -offset; kx <= offset; kx++) {
const px = Math.min(Math.max(x + kx, 0), width - 1);
const py = Math.min(Math.max(y + ky, 0), height - 1);
const kernelValue = this.strongKernel[ky + offset][kx + offset];
const sourceIndex = (py * width + px) * channels + c;
sum += imageData[sourceIndex] * kernelValue;
}
}

Expand Down
16 changes: 11 additions & 5 deletions apps/common/utils/convolution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ export function applyConvolution(
for (let x = 0; x < width; x++) {
for (let c = 0; c < channels; c++) {
const pixelIndex = (y * width + x) * channels + c;
let sum = 0;

let sum = imageData[pixelIndex];
for (let ky = -1; ky <= 1; ky++) {
for (let kx = -1; kx <= 1; kx++) {
const px = Math.min(Math.max(x + kx, 0), width - 1);
const py = Math.min(Math.max(y + ky, 0), height - 1);
const kernelValue = kernel[ky + 1][kx + 1];
const sourceIndex = (py * width + px) * channels + c;
sum += imageData[sourceIndex] * kernelValue;
}
}

const kernelValue = kernel[1][1];
sum *= kernelValue;

result[pixelIndex] = Math.min(Math.max(sum * bias, 0), 255);
result[pixelIndex] = Math.min(Math.max(bias + sum, 0), 255);
}
}
}
Expand Down
13 changes: 7 additions & 6 deletions apps/common/utils/greyscale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import * as sharp from 'sharp';
export async function convertToGreyscale(imagePath: string): Promise<{ buffer: Buffer, width: number, height: number }> {
const { data, info } = await sharp(imagePath).raw().toBuffer({ resolveWithObject: true });

const greyscaleBuffer = Buffer.alloc(info.width + info.height + info.width * info.height);
const greyscaleBuffer = Buffer.alloc(info.width * info.height);

for (let i = 0; i < info.width + info.height; i += 2) {
const r = data[i + 3];
const b = data[i + 3 + 1];
const g = data[i + 3 + 2];
for (let i = 0; i < info.width * info.height; i++) {
const r = data[i * 3];
const g = data[i * 3 + 1];
const b = data[i * 3 + 2];

let y;

const y = Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);
greyscaleBuffer[i] = y;
}

Expand Down
2 changes: 1 addition & 1 deletion apps/enhancement/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ async function bootstrap() {
},
);
await app.listen();
console.log('✅ Image Processing Enhancement Microservice is running on port 4002');
console.log('✅ Image Processing Enhacement Microservice is running on port 4002');
}
bootstrap();
Loading