or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bucket.mdclient.mdcluster.mdimage.mdindex.mdmultipart.mdobject.mdrtmp.mdsts.md
tile.json

image.mddocs/

Image Processing

The Image Processing service provides specialized operations for images stored in OSS, including transformations, EXIF data extraction, style management, and format conversion through Alibaba Cloud's Image Processing service.

Image Client Creation

ImageClient Factory

function ImageClient(options: ImageClientOptions): ImageClient;

interface ImageClientOptions {
  region?: string;
  accessKeyId: string;
  accessKeySecret: string;
  stsToken?: string;
  bucket: string;
  imageHost: string;
  endpoint?: string;
  timeout?: number | number[];
  agent?: Agent;
  httpsAgent?: Agent;
}

Usage

const OSS = require('ali-oss');

// Create Image Client
const imgClient = OSS.ImageClient({
  region: 'oss-cn-hangzhou',
  accessKeyId: 'your-access-key-id',
  accessKeySecret: 'your-access-key-secret',
  bucket: 'your-image-bucket',
  imageHost: 'img-cn-hangzhou.aliyuncs.com'
});

Image Processing Operations

Get Processed Image

async function get(name: string, file?: string, options?: ImageGetOptions): Promise<ImageGetResult>;

interface ImageGetOptions {
  timeout?: number | number[];
  headers?: Record<string, string>;
  process?: string;
}

interface ImageGetResult {
  content?: Buffer;
  res: ResponseInfo;
  size?: number;
  aborted?: boolean;
  rt?: number;
}

Get Image as Stream

async function getStream(name: string, options?: ImageGetOptions): Promise<ImageStreamResult>;

interface ImageStreamResult {
  stream: ReadableStream;
  res: ResponseInfo;
  size?: number;
  aborted?: boolean;
  rt?: number;
}

Processing Examples

// Resize image to 200x200 pixels
const resized = await imgClient.get('photo.jpg', null, {
  process: 'image/resize,w_200,h_200'
});

// Get thumbnail with quality adjustment
const thumbnail = await imgClient.get('large-image.jpg', null, {
  process: 'image/resize,w_150,h_150/quality,q_80'
});

// Convert format and add watermark
const processed = await imgClient.get('source.png', null, {
  process: 'image/format,jpg/watermark,text_V2F0ZXJtYXJr,size_20,x_10,y_10'
});

// Get processed image as stream
const stream = await imgClient.getStream('photo.jpg', {
  process: 'image/resize,w_300,h_300/rotate,90'
});

Image Information

Get Image Metadata

async function getInfo(name: string, options?: RequestOptions): Promise<ImageInfoResult>;

interface ImageInfoResult {
  format: string;
  width: number;
  height: number;
  size: number;
  colorModel: string;
  frameCount?: number;
  res: ResponseInfo;
}

Get EXIF Data

async function getExif(name: string, options?: RequestOptions): Promise<ImageExifResult>;

interface ImageExifResult {
  exif: ExifData;
  res: ResponseInfo;
}

interface ExifData {
  make?: string;
  model?: string;
  dateTime?: string;
  orientation?: number;
  xResolution?: string;
  yResolution?: string;
  resolutionUnit?: number;
  software?: string;
  [key: string]: any;
}

Usage Examples

// Get basic image information
const info = await imgClient.getInfo('photo.jpg');
console.log(`Image: ${info.width}x${info.height}, ${info.format}, ${info.size} bytes`);

// Extract EXIF data
const exifData = await imgClient.getExif('photo.jpg');
console.log('Camera:', exifData.exif.make, exifData.exif.model);
console.log('Date taken:', exifData.exif.dateTime);

Image Styles

Create Image Style

async function putStyle(styleName: string, style: ImageStyle, options?: RequestOptions): Promise<PutStyleResult>;

interface ImageStyle {
  content: string;
}

interface PutStyleResult {
  res: ResponseInfo;
}

Get Image Style

async function getStyle(styleName: string, options?: RequestOptions): Promise<GetStyleResult>;

interface GetStyleResult {
  style: ImageStyle;
  res: ResponseInfo;
}

List Image Styles

async function listStyle(options?: RequestOptions): Promise<ListStyleResult>;

interface ListStyleResult {
  styles: StyleInfo[];
  res: ResponseInfo;
}

interface StyleInfo {
  name: string;
  content: string;
  createTime: Date;
  lastModifyTime: Date;
}

Delete Image Style

async function deleteStyle(styleName: string, options?: RequestOptions): Promise<DeleteStyleResult>;

interface DeleteStyleResult {
  res: ResponseInfo;
}

Style Management Examples

// Create a thumbnail style
await imgClient.putStyle('thumbnail', {
  content: 'image/resize,w_200,h_200/quality,q_90'
});

// Create a watermark style
await imgClient.putStyle('watermark', {
  content: 'image/watermark,text_Q29weXJpZ2h0,size_20,x_10,y_10,color_FFFFFF'
});

// List all styles
const styles = await imgClient.listStyle();
console.log('Available styles:', styles.styles.map(s => s.name));

// Use style in processing
const styled = await imgClient.get('photo.jpg', null, {
  process: 'style/thumbnail'
});

// Delete style
await imgClient.deleteStyle('old-style');

Image Processing Parameters

Resize Operations

// Resize parameters
'image/resize,w_width,h_height'          // Resize to specific dimensions
'image/resize,w_width'                   // Resize width, auto height
'image/resize,h_height'                  // Resize height, auto width
'image/resize,p_percentage'              // Resize by percentage
'image/resize,w_width,h_height,m_mode'   // Resize with mode

// Resize modes
'm_lfit'    // Long side fit (default)
'm_mfit'    // Short side fit  
'm_fill'    // Fill and crop
'm_pad'     // Pad to fit
'm_fixed'   // Force exact dimensions

Format Conversion

// Format conversion
'image/format,jpg'       // Convert to JPEG
'image/format,png'       // Convert to PNG
'image/format,webp'      // Convert to WebP
'image/format,bmp'       // Convert to BMP
'image/format,gif'       // Convert to GIF
'image/format,tiff'      // Convert to TIFF

// Quality adjustment (for JPEG/WebP)
'image/quality,q_80'     // Set quality to 80%

Image Enhancement

// Rotation
'image/rotate,90'        // Rotate 90 degrees clockwise
'image/rotate,180'       // Rotate 180 degrees
'image/rotate,270'       // Rotate 270 degrees

// Auto-orient based on EXIF
'image/auto-orient,1'    // Auto-orient image

// Brightness/Contrast
'image/bright,50'        // Increase brightness by 50
'image/contrast,20'      // Increase contrast by 20

// Sharpen/Blur
'image/sharpen,100'      // Sharpen image
'image/blur,r_3,s_2'     // Blur with radius 3, sigma 2

Cropping Operations

// Crop operations
'image/crop,w_300,h_200,x_10,y_10'      // Crop rectangle
'image/crop,w_300,h_200,g_center'        // Crop from center
'image/indexcrop,x_10,y_10,w_100,h_100'  // Index crop

// Crop gravity positions
'g_nw'      // North West (top-left)
'g_n'       // North (top-center)
'g_ne'      // North East (top-right)
'g_w'       // West (center-left)
'g_center'  // Center
'g_e'       // East (center-right)
'g_sw'      // South West (bottom-left)
'g_s'       // South (bottom-center)
'g_se'      // South East (bottom-right)

Watermarks

// Text watermark
'image/watermark,text_encoded_text,size_20,x_10,y_10,color_FFFFFF'

// Image watermark
'image/watermark,image_encoded_url,x_10,y_10,P_50'

// Watermark parameters
'size_20'       // Font size
'color_FFFFFF'  // Color in hex
'x_10'          // X position
'y_10'          // Y position  
'P_50'          // Transparency (0-100)
'g_center'      // Gravity position

Advanced Processing

Complex Processing Chains

// Complex processing pipeline
const complexProcess = [
  'image/resize,w_800,h_600,m_lfit',      // Resize
  'image/rotate,90',                       // Rotate
  'image/bright,10',                       // Brighten
  'image/quality,q_85',                    // Quality
  'image/format,jpg'                       // Convert format
].join('/');

const result = await imgClient.get('source.png', null, {
  process: complexProcess
});

Conditional Processing

// Process only if image is larger than 1000px
const conditionalProcess = 'image/resize,w_1000,h_1000,m_lfit/resize,w_800,h_600,m_lfit';

// Auto-format based on browser support
const autoFormat = 'image/format,webp';  // Falls back to original if not supported

Signed URLs for Images

Generate Signed URL

function signatureUrl(name: string, options?: ImageSignatureOptions): string;

interface ImageSignatureOptions {
  expires?: number;
  process?: string;
}

Usage

// Generate signed URL for processed image
const signedUrl = imgClient.signatureUrl('private-photo.jpg', {
  expires: 3600, // 1 hour
  process: 'image/resize,w_200,h_200/quality,q_90'
});

console.log('Temporary processed image URL:', signedUrl);

Error Handling

Image Processing Errors

try {
  const result = await imgClient.get('photo.jpg', null, {
    process: 'image/resize,w_2000,h_2000'
  });
} catch (error) {
  if (error.code === 'ImageTooLarge') {
    console.error('Image dimensions exceed limits');
  } else if (error.code === 'InvalidImageFormat') {
    console.error('Unsupported image format');
  } else {
    console.error('Processing failed:', error.message);
  }
}

Common Error Codes

  • InvalidImageFormat - Unsupported image format
  • ImageTooLarge - Image exceeds size limits
  • InvalidArgument - Invalid processing parameters
  • ProcessTimeout - Processing took too long
  • InternalError - Internal processing error

Image Processing Limits

Size and Format Limits

  • Maximum Image Size: 20MB
  • Maximum Dimensions: 30,000 x 30,000 pixels
  • Supported Formats: JPEG, PNG, BMP, GIF, WebP, TIFF
  • Output Formats: JPEG, PNG, WebP, BMP, GIF, TIFF

Processing Limits

  • Resize Range: 1px to 16,384px per dimension
  • Quality Range: 1-100 for JPEG/WebP
  • Rotation: 90°, 180°, 270° or arbitrary angles
  • Watermark Text: Up to 64 characters (Base64 encoded)

Best Practices

Performance Optimization

// Use appropriate quality settings
const webOptimized = 'image/resize,w_800,h_600/quality,q_85/format,webp';

// Cache processed images by using consistent naming
const cacheKey = `processed_${name}_${Buffer.from(process).toString('base64')}`;

// Use styles for frequently used transformations
await imgClient.putStyle('web-thumbnail', {
  content: 'image/resize,w_300,h_300,m_fill/quality,q_90/format,webp'
});

Advanced Processing Operations

Process and Save Objects

async function processObjectSave(sourceObject: string, targetObject: string, process: string, targetBucket?: string, options?: RequestOptions): Promise<ProcessObjectSaveResult>;

interface ProcessObjectSaveResult {
  bucket: string;
  fileSize: number;
  imageInfo?: {
    format: string;
    width: number;
    height: number;
  };
  object: string;
  status: string;
  res: ResponseInfo;
}

Process Object Save Usage

// Process image and save result to new object
const result = await client.processObjectSave(
  'photos/original.jpg',      // Source object
  'photos/thumbnail.jpg',     // Target object  
  'image/resize,w_300,h_300/quality,q_85',  // Processing parameters
  'processed-images-bucket',  // Optional: different target bucket
  { timeout: 30000 }
);

console.log('Processed image saved:');
console.log('Target:', result.object);
console.log('Size:', result.fileSize, 'bytes');
console.log('Dimensions:', `${result.imageInfo.width}x${result.imageInfo.height}`);

// Process with multiple transformations
const complexResult = await client.processObjectSave(
  'uploads/photo.png',
  'gallery/processed.jpg',
  [
    'image/resize,w_800,h_600,m_lfit',    // Resize
    'image/watermark,text_Q29weXJpZ2h0,size_20,x_10,y_10', // Watermark
    'image/quality,q_90',                  // Quality
    'image/format,jpg'                     // Convert format
  ].join('/')
);

Batch Processing

// Process multiple images
async function batchProcessImages(sourcePrefix, targetPrefix, processParams) {
  // List source images
  const list = await client.list({ prefix: sourcePrefix });
  
  const results = [];
  for (const obj of list.objects) {
    if (obj.name.match(/\.(jpg|jpeg|png|gif)$/i)) {
      try {
        const targetName = obj.name.replace(sourcePrefix, targetPrefix);
        
        const result = await client.processObjectSave(
          obj.name,
          targetName,
          processParams,
          null, // Same bucket
          { timeout: 60000 }
        );
        
        results.push({
          source: obj.name,
          target: targetName,
          status: 'success',
          size: result.fileSize
        });
        
        console.log(`Processed: ${obj.name} -> ${targetName}`);
        
      } catch (error) {
        console.error(`Failed to process ${obj.name}:`, error);
        results.push({
          source: obj.name,
          status: 'failed',
          error: error.message
        });
      }
    }
  }
  
  return results;
}

// Usage
const batchResults = await batchProcessImages(
  'uploads/',
  'thumbnails/',
  'image/resize,w_200,h_200,m_fill/quality,q_85'
);

Security Considerations

// Validate image dimensions before processing
const info = await imgClient.getInfo(imageName);
if (info.width > 5000 || info.height > 5000) {
  throw new Error('Image too large for processing');
}

// Use signed URLs for private images
const privateUrl = imgClient.signatureUrl(privateName, {
  expires: 1800, // 30 minutes
  process: 'image/resize,w_200,h_200'
});