Skip to content

Commit

Permalink
Merge pull request #48 from ghostboats/dds_changes
Browse files Browse the repository at this point in the history
Dds changes
  • Loading branch information
ghostboats authored May 15, 2024
2 parents 1c7ebf5 + afaa516 commit e898b79
Show file tree
Hide file tree
Showing 60 changed files with 95 additions and 16,649 deletions.
81 changes: 24 additions & 57 deletions commands/DDSToPNG.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,36 @@
// DDSToPNG.js
//https://github.com/mmomtchev/magickwand.js/blob/main/example/example.mjs
const vscode = require('vscode');
const path = require('path');
const { exec } = require('child_process');
const { Magick } = require('magickwand.js');

const DDSToPNGCommand = vscode.commands.registerCommand('bg3-mod-helper.DDSToPNG', async (uri) => {
if (!uri) {
vscode.window.showErrorMessage('No file selected.');
return;
}

console.log('‾‾DDSToPNGCommand‾‾');
const checkWandScriptPath = path.join(__dirname, '..', 'support_files', 'python_scripts', 'check_wand.py');
const scriptPath = path.join(__dirname, '..', 'support_files', 'scripts', 'python', 'DDS_to_PNG.py');
const filePath = uri.fsPath;
const outputPath = filePath.replace(/\.[^/.]+$/, ".png");

// Check if Wand is installed
exec(`python "${checkWandScriptPath}"`, (error, stdout, stderr) => {
if (error) {
console.error('Error:', error);
return;
}
if (stderr) {
console.error('Script error:', stderr);
try {
let image = new Magick.Image();
await image.readAsync(filePath);

const infoDDS = new Magick.CoderInfo('DDS');
if (!infoDDS || !infoDDS.isReadable()) {
vscode.window.showErrorMessage("DDS format is not supported for reading.");
return;
}
if (stdout.trim() === "Wand not installed") {
vscode.window.showInformationMessage(
"Wand Python package is not installed. Open terminal to install wand? ENSURE PIP IS UPDATED, OTHERWISE RUN THIS MANUALLY IN TERMINAL: pip install wand",
"Yes",
"No"
).then(selection => {
if (selection === "Yes") {
// Open a new terminal with the command typed but not executed
const terminal = vscode.window.createTerminal(`Wand Install`);
terminal.show();
terminal.sendText("pip install wand", false); // false means don't execute

// Prompt user to press Enter in terminal
vscode.window.showInformationMessage("The terminal has opened with the pip install command. Please press Enter in the terminal to install Wand, then rerun this command.");
}
});
} else if (stdout.trim() === "ImageMagick not installed") {
// Prompt user to download ImageMagick
vscode.window.showInformationMessage(
"ImageMagick is not installed, which is required by Wand. Would you like to download it (installed headers as well in options when downlaoding)?",
"Download ImageMagick"
).then(selection => {
if (selection === "Download ImageMagick") {
vscode.env.openExternal(vscode.Uri.parse("https://imagemagick.org/script/download.php"));
}
});
} else {
// Wand is installed, proceed with conversion
const convertCommand = `python "${scriptPath}" -f "${filePath}"`;
exec(convertCommand, (convertError, convertStdout, convertStderr) => {
if (convertError) {
console.error('Error:', convertError);
vscode.window.showErrorMessage(`Error converting file: ${convertError.message}`);
return;
}
if (convertStderr) {
console.error('Script error:', convertStderr);
}
if (convertStdout) {
console.log('Script output:', convertStdout);
}
vscode.window.showInformationMessage(`File converted successfully.`);
});
}
});
await image.magickAsync('PNG');
await image.writeAsync(outputPath);

vscode.window.showInformationMessage(`DDS file converted successfully and saved as ${outputPath}`);
} catch (error) {
console.error('Error:', error);
vscode.window.showErrorMessage('Failed to convert DDS to PNG: ' + error.message);
}

console.log('__DDSToPNGCommand__');
});

Expand Down
88 changes: 23 additions & 65 deletions commands/PNGToDDS.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,33 @@
// PNGToDDS.js
//https://github.com/mmomtchev/magickwand.js/blob/main/example/example.mjs
const vscode = require('vscode');
const path = require('path');
const { exec } = require('child_process');
const { Magick } = require('magickwand.js');

const PNGToDDSCommand = vscode.commands.registerCommand('bg3-mod-helper.PNGToDDS', async (uri) => {
console.log('‾‾PNGToDDSCommand‾‾');
const checkWandScriptPath = path.join(__dirname, '..', 'support_files', 'python_scripts', 'check_wand.py');
const scriptPath = path.join(__dirname, '..', 'support_files', 'scripts', 'python', 'PNG_to_DDS.py');
if (!uri) {
vscode.window.showErrorMessage('No file selected.');
return;
}

const filePath = uri.fsPath;
const normalizedFilePath = filePath.toLowerCase().replace(/\\/g, '/');

const ddsCompression = normalizedFilePath.includes('assets/textures/icons') ? 'DXT5' : 'DXT1';
const outputExtension = normalizedFilePath.includes('assets/textures') ? '.dds' : '.DDS';
const outputPath = filePath.replace(/\.[^/.]+$/, outputExtension);

try {
let image = new Magick.Image();
await image.readAsync(filePath);

// Normalize file path and determine output format
const normalizedFilePath = filePath.replace(/\\/g, '/').toLowerCase(); // Replace backslashes with forward slashes and convert to lower case
const outputFormat = normalizedFilePath.includes('assets/textures/icons') ? '.dds' : '.DDS';
const ddsCompression = outputFormat === '.dds' ? 'dxt5' : 'dxt1';
await image.magickAsync('DDS');

// Check if Wand is installed
exec(`python "${checkWandScriptPath}"`, (error, stdout, stderr) => {
if (error) {
console.error('Error:', error);
return;
}
if (stderr) {
console.error('Script error:', stderr);
return;
}
if (stdout.trim() === "Wand not installed") {
vscode.window.showInformationMessage(
"Wand Python package is not installed. Open terminal to install wand? ENSURE PIP IS UPDATED, OTHERWISE RUN THIS MANUALLY IN TERMINAL: pip install wand",
"Yes",
"No"
).then(selection => {
if (selection === "Yes") {
// Open a new terminal with the command typed but not executed
const terminal = vscode.window.createTerminal(`Wand Install`);
terminal.show();
terminal.sendText("pip install wand", false); // false means don't execute
await image.writeAsync(outputPath);

// Prompt user to press Enter in terminal
vscode.window.showInformationMessage("The terminal has opened with the pip install command. Please press Enter in the terminal to install Wand, then rerun this command.");
}
});
} else if (stdout.trim() === "ImageMagick not installed") {
// Prompt user to download ImageMagick
vscode.window.showInformationMessage(
"ImageMagick is not installed, which is required by Wand. Would you like to download it (installed headers as well in options when downlaoding)?",
"Download ImageMagick"
).then(selection => {
if (selection === "Download ImageMagick") {
vscode.env.openExternal(vscode.Uri.parse("https://imagemagick.org/script/download.php"));
}
});
} else {
// Wand is installed, proceed with conversion
const convertCommand = `python "${scriptPath}" -o "${outputFormat}" --ddscompression "${ddsCompression}" -f "${filePath}"`;
exec(convertCommand, (convertError, convertStdout, convertStderr) => {
if (convertError) {
console.error('Error:', convertError);
vscode.window.showErrorMessage(`Error converting file: ${convertError.message}`);
return;
}
if (convertStderr) {
console.error('Script error:', convertStderr);
}
if (convertStdout) {
console.log('Script output:', convertStdout);
}
vscode.window.showInformationMessage(`File converted successfully.`);
});
}
});
console.log('__PNGToDDSCommand__');
vscode.window.showInformationMessage(`File converted successfully and saved as ${outputPath}`);
} catch (error) {
console.error('Error:', error);
vscode.window.showErrorMessage('Failed to convert image: ' + error.message);
}
});

module.exports = PNGToDDSCommand;
54 changes: 31 additions & 23 deletions commands/addIconBackground.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const vscode = require('vscode');
const sharp = require('sharp');
const path = require('path');
const fs = require('fs').promises; // Use promises version of fs for async/await compatibility
const fs = require('fs').promises;
const { Magick, MagickCore } = require('magickwand.js');

async function addIconBackground(uri) {
const inputPath = uri.fsPath;
Expand All @@ -10,17 +10,14 @@ async function addIconBackground(uri) {
try {
const files = await fs.readdir(backgroundsDir);
const pngFiles = files.filter(file => file.endsWith('.png'));
// Ensure each option has an isCustom property for consistent handling
const backgroundOptions = pngFiles.map(file => ({ label: file, isCustom: false }));
backgroundOptions.push({ label: 'Custom Background...', isCustom: true });

// Prompt user for background selection
const selectedBackground = await vscode.window.showQuickPick(backgroundOptions, { placeHolder: 'Select a background' });
if (!selectedBackground) return;

let backgroundPath;
if (selectedBackground.isCustom) {
// Handle custom background selection
const customUri = await vscode.window.showOpenDialog({
openLabel: 'Use Background',
canSelectMany: false,
Expand All @@ -29,42 +26,53 @@ async function addIconBackground(uri) {
if (customUri && customUri[0]) {
backgroundPath = customUri[0].fsPath;
} else {
return; // No file selected, exit the function
return;
}
} else {
// Use selected predefined background
backgroundPath = path.join(backgroundsDir, selectedBackground.label);
}

const outputPath = inputPath.replace(/\.\w+$/, `_with_background.png`);

// Load both images to compare sizes
const iconImage = sharp(inputPath);
const background = sharp(backgroundPath);
const [iconMetadata, backgroundMetadata] = await Promise.all([iconImage.metadata(), background.metadata()]);
const iconImage = new Magick.Image;
await iconImage.readAsync(inputPath);
const background = new Magick.Image;
await background.readAsync(backgroundPath);

const iconSize = await iconImage.sizeAsync();
const backgroundSize = await background.sizeAsync();
const iconWidth = iconSize.width();
const iconHeight = iconSize.height();
let backgroundWidth = backgroundSize.width();
let backgroundHeight = backgroundSize.height();

if (iconMetadata.width !== backgroundMetadata.width || iconMetadata.height !== backgroundMetadata.height) {
if (iconWidth !== backgroundWidth || iconHeight !== backgroundHeight) {
const resizeBackground = await vscode.window.showInformationMessage(
'The background and icon sizes do not match. Resize the background to match the icon?',
'Yes', 'No'
);
if (resizeBackground === 'Yes') {
await background.resize(iconMetadata.width, iconMetadata.height);
await background.resizeAsync(`${iconWidth}x${iconHeight}`);
const backgroundSizeResize = await background.sizeAsync();
backgroundWidth = backgroundSizeResize.width();
backgroundHeight = backgroundSizeResize.height();
} else {
return;
}
}

// Composite the icon over the resized background
background
.composite([{ input: await iconImage.toBuffer(), gravity: 'centre' }])
.toFile(outputPath)
.then(() => {
vscode.window.showInformationMessage(`Background added: ${outputPath}`);
})
.catch(err => {
vscode.window.showErrorMessage(`Error adding background: ${err}`);
});
const xOffset = Math.floor((backgroundWidth - iconWidth) / 2);
const yOffset = Math.floor((backgroundHeight - iconHeight) / 2);

console.log(`Calculated xOffset: ${xOffset}, yOffset: ${yOffset}`);

// Create a Geometry object for the composite operation
const geometry = new Magick.Geometry(iconWidth, iconHeight, xOffset, yOffset);
console.log('Attempting to composite with geometry:', geometry.toString());
await background.compositeAsync(iconImage, geometry, MagickCore.OverCompositeOp);

await background.writeAsync(outputPath);
vscode.window.showInformationMessage(`Background added: ${outputPath}`);
} catch (err) {
vscode.window.showErrorMessage(`Failed to read backgrounds directory or process images: ${err}`);
}
Expand Down
25 changes: 12 additions & 13 deletions commands/resizeImage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const sharp = require('sharp');
const vscode = require('vscode');
const { Magick } = require('magickwand.js');

async function resizeImage(uri, width = null, height = null) {
console.log('‾‾resizeImage‾‾');
Expand All @@ -24,22 +24,21 @@ async function resizeImage(uri, width = null, height = null) {

const outputPath = inputPath.replace(/\.\w+$/, `_resized_${width}x${height}.png`);

sharp(inputPath)
.resize(width, height)
.toFile(outputPath)
.then(() => {
vscode.window.showInformationMessage(`Image resized to ${width}x${height}: ${outputPath}`);
})
.catch(err => {
vscode.window.showErrorMessage(`Error resizing image: ${err}`);
});
try {
let image = new Magick.Image();
await image.readAsync(inputPath);
await image.scaleAsync(`${width}x${height}`);
await image.writeAsync(outputPath);
vscode.window.showInformationMessage(`Image resized to ${width}x${height}: ${outputPath}`);
} catch (err) {
vscode.window.showErrorMessage(`Error resizing image: ${err}`);
}
console.log('__resizeImage__');
}

module.exports = {
resizeImageTooltip: (uri) => resizeImage(uri, 380, 380),
resizeImageController: (uri) => resizeImage(uri, 144, 144),
resizeImageHotbar: (uri) => resizeImage(uri, 64, 64),
resizeImageCustom: resizeImage // Using the same function for custom resizing
// ... other exports ...
};
resizeImageCustom: resizeImage
};
Loading

0 comments on commit e898b79

Please sign in to comment.