export async function chooseImage(params: ESObject): Promise<ESObject> {
const sourceType: string[] = params?.sourceType || ['album', 'camera'];
let count: number = params?.count || 0;
let isSaveToAlbum: number = params?.isSaveToAlbum || 1;
let watermark: string[] = params?.watermark || [];
let context = getContext();
if (!Array.isArray(sourceType) || typeof count !== 'number' || !Array.isArray(watermark)) {
return Promise.reject(new Error('Invalid parameters'));
}
try {
const win = await window.getLastWindow(context);
let promptAction: PromptAction = win.getUIContext().getPromptAction();
if (sourceType.includes('album')) {
const data = await promptAction.showActionMenu({
title: '',
buttons: [
{
text: $r('app.string.ZKGJ001534'),
color: '#1a1a1a'
},
{
text: $r('app.string.ZKGJ000402'),
color: '#1a1a1a'
}
]
});
if (data.index === 0) {
return captureImage(isSaveToAlbum, watermark);
} else {
return pickImage(count, watermark);
}
} else {
return captureImage(isSaveToAlbum, watermark);
}
} catch (error) {
return Promise.reject(error);
}
}
async function captureImage(isSaveToAlbum: number, watermark: string[]): Promise<string[]> {
const context = getContext() as common.UIAbilityContext;
const localId = `${dayjs().format('YYYYMMDDHHmmssSSS')}_openHarmony.jpg`;
const saveDir = `${CAMERA_DIRECTORY}/`;
const filePath = `${saveDir}${localId}`;
try {
const result = await checkPermissions(['ohos.permission.WRITE_IMAGEVIDEO'], context);
if (result !== 'success') {
throw new Error('No permission');
}
if (!isFileExist(saveDir)) {
fs.mkdirSync(saveDir, true);
}
fs.createRandomAccessFileSync(filePath, fs.OpenMode.CREATE);
const src = fileUri.getUriFromPath(filePath);
const pickerProfile: picker.PickerProfile = {
cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK,
saveUri: src
};
const pickerResult = await picker.pick(context, [picker.PickerMediaType.PHOTO], pickerProfile);
if (!pickerResult.resultUri) {
throw new Error('Failed to capture image');
}
if (isSaveToAlbum) {
await saveToAlbum(src);
}
await addWaterMark(localId, watermark);
return [localId];
} catch (error) {
throw new Error(`Failed to capture image: ${error.message}`);
}
}
async function saveToAlbum(imageUri: string): Promise<void> {
const context = getContext() as common.UIAbilityContext;
try {
const helper = photoAccessHelper.getPhotoAccessHelper(context);
const dest = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg');
const srcFile = fs.openSync(imageUri, fs.OpenMode.READ_ONLY);
const destFile = fs.openSync(dest, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
fs.copyFileSync(srcFile.fd, destFile.fd);
fs.closeSync(srcFile);
fs.closeSync(destFile);
console.log('Image saved to album successfully:', dest);
} catch (error) {
console.error('Failed to save image to album:', error);
throw new Error(`Failed to save image to album: ${error.message}`);
}
}
async function pickImage(count: number, watermark: string[]): Promise<string[]> {
const PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
PhotoSelectOptions.maxSelectNumber = count;
try {
const photoPicker = new photoAccessHelper.PhotoViewPicker();
const PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);
const localIds: string[] = [];
for (const photoUri of PhotoSelectResult.photoUris) {
const fileName = getFileName(photoUri);
const fileType = fileName.lastIndexOf('.') > -1 ? fileName.substring(fileName.lastIndexOf('.')) : '';
const localId = `${dayjs().format('YYYYMMDDHHmmssSSS')}_openHarmony${fileType}`;
const saveDir = `${CAMERA_DIRECTORY}/`;
const dest = `${saveDir}${localId}`;
if (!isFileExist(saveDir)) {
fs.mkdirSync(saveDir, true);
}
const srcFile = fs.openSync(photoUri, fs.OpenMode.READ_ONLY);
const destFile = fs.openSync(dest, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
fs.copyFileSync(srcFile.fd, destFile.fd);
fs.closeSync(srcFile);
fs.closeSync(destFile);
await addWaterMark(localId, watermark);
localIds.push(localId);
}
return localIds;
} catch (error) {
throw new Error(`Failed to pick images: ${error.message}`);
}
}
async function addWaterMark(localId: string, watermark: string[]): Promise<void> {
const uri = `${CAMERA_DIRECTORY}/${localId}`;
const buffer = readFile(uri);
const imageSource: image.ImageSource = image.createImageSource(buffer);
try {
const value = await imageSource.getImageInfo();
const pixelMap = await createPixelMap(imageSource, value.size);
if (!pixelMap) {
throw new Error("Failed to create PixelMap");
}
const modifiedPixelMap = await addWatermarkToPixelMap(pixelMap, value.size, watermark);
if (!modifiedPixelMap) {
throw new Error("Failed to create modified PixelMap");
}
await saveToFile(modifiedPixelMap, uri);
console.log('Watermark added and image saved successfully:', uri);
} catch (error) {
console.error('Failed to add watermark:', error);
throw new Error(`Failed to add watermark: ${error.message}`);
}
}
export function uploadImage(params: ESObject): Promise<ESObject> {
const localId: string = params?.localId || '';
const fileName: string = params?.fileName || '';
const filePath: string = `${CAMERA_DIRECTORY}${viewId}files/${localId}`;
let uploadDir: string = params?.uploadDir || '';
const imageStore:ImageRelationalStore = ImageRelationalStore.getInstance()
if (isFileExist(filePath) && isFile(filePath)) {
let buffer: ArrayBuffer = readFile(filePath);
let formData = new FormData();
formData.append('uploadfile', buffer, localId);
formData.append('uploadDir', uploadDir);
formData.append('fileName', fileName || localId);
formData.append('fileSize', String(getFileSize(filePath)));
return new Promise(async (resolve, reject) => {
let hashCode = await generateHash(localId, getFileSize(filePath));
formData.append('hashCode', hashCode);
let uploadUrl = Global.getInstance().getImageUploadUrl();
let fileData: FileData = {
localId:localId,
fileName:fileName || localId,
uploadDir:uploadDir,
filePath:filePath,
}
imageStore?.insert(fileData)?.then(() => {
imageStore.upload()
resolve({
serverId: localId,
fileName: fileName,
baseUrl: Global.getInstance().getImageUrl(),
path: `${uploadDir}${localId}`,
localPath: 'file://' + filePath
})
})?.catch((err: ESObject) => {
console.info('imageStore err' + JSON.stringify(err))
})
});
} else {
return Promise.reject(new Error('localFile is not exist'))
}
}
async function createPixelMap(imageSource: image.ImageSource, imageSize: image.Size): Promise<image.PixelMap> {
const defaultSize: image.Size = {
height: Math.round(imageSize.height * 1),
width: Math.round(imageSize.width * 1)
};
const opts: image.DecodingOptions = {
editable: true,
desiredSize: defaultSize
};
return new Promise((resolve, reject) => {
imageSource.createPixelMap(opts).then(pixelMap => {
resolve(pixelMap);
}).catch((err: BusinessError) => {
reject(err);
})
});
}
function addWatermarkToPixelMap(pixelMap: image.PixelMap, imageSize: image.Size, watermarks: string[]): image.PixelMap {
const imageScale = imageSize.width / display.getDefaultDisplaySync().width;
const canvas = new drawing.Canvas(pixelMap);
const pen = new drawing.Pen();
pen.setColor({ alpha: 255, red: 255, green: 255, blue: 255 });
const font = new drawing.Font();
font.setSize(32 * imageScale);
const brush = new drawing.Brush();
brush.setColor({ alpha: 255, red: 255, green: 255, blue: 255 });
const lineHeight = font.getSize() * 1.5;
let yPos = 0;
if (imageSize.width > imageSize.height) {
yPos = imageSize.height - 50 * imageScale;
} else {
yPos = imageSize.width - 50 * imageScale;
}
for (let i = watermarks.length - 1; i >= 0; i--) {
const watermark = watermarks[i];
let lines = breakTextIntoLines(watermark, font, imageSize.width - 40 * imageScale);
lines.forEach(line => {
const textBlob = drawing.TextBlob.makeFromString(line, font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
canvas.attachBrush(brush);
canvas.attachPen(pen);
canvas.drawTextBlob(textBlob, 20 * imageScale, yPos);
canvas.detachBrush();
canvas.detachPen();
yPos -= lineHeight;
});
}
return pixelMap;
}
function breakTextIntoLines(text: string, font: drawing.Font, maxWidth: number): string[] {
const lines: string[] = [];
let currentLine = '';
const words = text.split(' ');
words.forEach(word => {
const testLine = currentLine.length === 0 ? word : `${currentLine} ${word}`;
const testWidth = font.measureText(testLine, drawing.TextEncoding.TEXT_ENCODING_UTF8);
if (testWidth <= maxWidth) {
if (currentLine.length === 0) {
currentLine = word;
} else {
currentLine += ` ${word}`;
}
} else {
lines.push(currentLine);
currentLine = word;
}
});
if (currentLine.length > 0) {
lines.push(currentLine);
}
return lines;
}
export async function saveToFile(pixelMap: image.PixelMap, imagePath: string): Promise<void> {
let fd: number | null = null;
try {
const filePath = imagePath;
const imagePacker = image.createImagePacker();
const imageBuffer = await imagePacker.packing(pixelMap, {
format: 'image/jpeg',
quality: 100
});
const mode = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE;
fd = (await fs.open(filePath, mode)).fd;
await fs.truncate(fd);
await fs.write(fd, imageBuffer);
} catch (err) {
console.error('saveToFile error: ' + err);
throw new Error(`Failed to save image to file: ${err}`);
} finally {
if (fd) {
fs.close(fd);
}
}
}