﻿# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [9.0.3] - 03-Mar-2026
### Changed
- Updated JPN localization. (DOC-7055)

## [9.0.2] - 04-Feb-2026
### Fixed
- [macOS] Fixed an issue where empty frames were shown for GIF files in MacOS browsers. (DOC-7331)

## [9.0.1] - 23-Jan-2026
### Fixed
- Fixed an issue where imageGallery item width and height settings did not affect the displayed thumbnail size in the image gallery dropdown. (DOC-7172)
- Fixed ImageGallery to hide unsupported image formats, preventing broken preview thumbnails from being displayed. (DOC-7173)

## [9.0.0] - 05-Dec-2025
### Added
- [Text and Objects] [Image Object] Added support for skew transformations. (DOC-7060)
- [Text and Objects] Added ImageGallery dropdown for easier image selection. (DOC-7082)
- [Text and Objects] [Image Object] Added image alignment property.
### Fixed
- Fixed unexpected behavior when using Undo with Line or Arrow objects. (DOC-7038)

## [8.2.0] - 08-Aug-2025
### Added
- Added "Text and Objects" tool. (DOC-5662)
### Fixed
- Fixed incorrect image sizing caused by DPI scaling, which affected 100% zoom at 125% display scaling. (DOC-6430)

## [8.0.4] - 27-Feb-2025
## Fixed
- The onAfterOpen event is triggered every time a filter is applied, causing an infinite loop. (DOC-6754)

## [8.0.0] - 03-Dec-2024
### Changed
- Minor internal changes.

## [7.2.3] - 09-Oct-2024
### Changed
- Minor internal changes.

## [7.2.1] - 28-Aug-2024
## Fixed
- An error message is shown when opening certain ICO images. (DOC-6428)
- Unable to set frameIndex before ICO image fully loads. (DOC-6462)
- [API Docs] The "effectsTools" is missing. (DOC-6339)

## [7.2.0] - 07-Aug-2024
### Added
- [PaintTools] Added blur/pixelate tool. (DOC-5661)
- [PaintTools] Added the ability to select the entire image using Ctrl+A.
- [PaintTools] Added "Effects" toolbar.
- [PaintTools] Added the ability to save the current state of a modified image without applying changes and without closing the paint toolbar.
- [PaintTools] [Effects] Added the ability to resize rectangular and elliptical selections.
- Added new toolbar item "navigation-auto": displays the navigation panel only if the loaded image has more than one frame, such as a GIF or TIFF.
- Added localization support.
### Changed
- Page Tools icon updated.
- The default toolbar layout updated: the "$navigation" item replaced by "navigation-auto". 
- Paint/Text tools enhancements:
  - Selection tool no longer resets after selecting an area.
  - "Apply/Cancel" buttons moved to the beginning of the toolbar.
  - Items in the second toolbar are now aligned to the left instead of center.
- Confirmation messages, tooltips and labels updated.

## [7.1.4] - 23-Jul-2024
### Added
- [macOS] Added support for the "meta" key. Default keyboard shortcuts have been enhanced to include the "meta" key for macOS in all shortcuts that use the Ctrl key.

## [7.1.3] - 25-Jun-2024
### Fixed
- The split of the plugin is not deleted when a plugin is added to the last position. (DOC-6290)
- After adding the plugin for the first time, delete it and add it again, the location of the plug-in is incorrect. (DOC-6289)
- Improved the behavior of plugin toolbars. (DOC-6290, DOC-6289)
- [API Docs] Missing description of toolbarLayout for PaintToolsPlugin. (DOC-6196)

## [7.1.1] - 23-Apr-2024
### Added
- [PaintTools] Added toolbarLayout option to the PaintTools plugin. (DOC-6174)
```javascript
// Example 1 - modify paint tools toolbar:
viewer.addPlugin(new PaintToolsPlugin({
toolbarLayout: {
		paintTools: ["Pencil", "Size", "Color", "Splitter", "Apply", "Cancel"]
}
}));
```
```javascript
// Example 2 - modify text tools toolbar:
viewer.addPlugin(new PaintToolsPlugin({
toolbarLayout: {
		textTools:  ["Text", "FontSize", "Splitter", "Apply", "Cancel"]
}
}));
```

## [7.1.0] - 04-Apr-2024
### Added
- 'Save As' dropdown menu added to the 'Save' button, providing the ability to convert the image to another format. (DOC-5799).\
The supported formats for conversion include: PNG (image/png), JPEG (image/jpeg), WEBP (image/webp), BMP image/bmp, GIF (image/gif).
Note that WEBP may not be supported on certain platforms, such as Safari for Mac or iOS.
In such cases the 'Save as WEBP' menu item will be hidden.
- The save method has been enhanced to include the ability to specify save options, 
allowing you to customize the saving process, including changing the image format via the convertToFormat option.
  ```javascript
  // Example: save the modified image as PNG:
  const viewer = DsImageViewer.findControl("#root");
  viewer.save({ convertToFormat: "image/png" });
  ```

## [7.0.3] - 19-Feb-2024
### Fixed
- After using the removePlugins API an exception is thrown if an image filter is used. (DOC-6043)
- The paint tools display is incorrect after the image is rotated. (DOC-5603)
- In image filters preview mode, the display is incorrect after zooming the image in and out by mouse. (DOC-5627)
- The default value of 100% for clone stamp opacity does not take effect. (DOC-5625)
- After using the removePlugins API the paint tools icon is still displayed. (DOC-5648)
- [iOS] There are some issues with the horizontal scrollbar. (DOC-4868)

## [7.0.2] - 25-Jan-2024
### Fixed
- Display error when zooming while using image filters. (DOC-5989)
- Saving a selection produces a black image. (DOC-5748)
- Selection tools' prompts are inconsistent. (DOC-5755)
- [iOS] Image filters do not work. (DOC-5537)


## [7.0.1] - 04-Jan-2024
### Fixed
- The second toolbar of an image filter is still displayed when the image filter is folded. (DOC-5968)
- An unexpected black area appears after an image is rotated. (DOC-5753)

## [7.0.0] - 07-Dec-2023
### Added
- Added DsImageViewer class and "@mescius/dsimageviewer" package. Functionally DsImageViewer is identical to GcImageViewer. (DOC-5736)
- Brightness filter. (DOC-5656)
- Contrast filter. (DOC-5657)
- Selection tool, used for cut/copy/paste operations and for applying other tools to selection only. (DOC-5658)
### Changed
- [Paint tools] The "Use original image" toggle now only applies to the eraser tool; for other tools this option is disabled and ignored.
- Improvements to image filters' UI and functionality.
- Some tooltips updated.
### Fixed
- Miscellaneous bug fixes.

## [1.2.4] - 27-Oct-2023
### Fixed
- Transparent background becomes solid gray when using the text tool. (DOC-5626)

## [1.2.3] - 28-Sep-2023
### Fixed
- [Windows Touch] Zooming by hand does not work. (DOC-5712)

## [1.2.1] - 17-Aug-2023
### Fixed
- Improved layout in full screen mode. (DOC-5599)
- Some text is not visible when using the text tools. (DOC-5489)
- [iOS] The expand button of the second toolbar is not visible. (DOC-5617)

## [1.2.0] - 1-Aug-2023
### Fixed
- Thumbnail image can be dragged to the viewer area. (DOC-5497)
- Several issues with the image filter plugin when using different themes. (DOC-5453)
- [iOS] Zoom factor jitter during two finger pinch gesture. (ARF-4244)
- Miscellaneous UI/behavior improvements.
### Added
- Paint tools plugin (pencil, brush, clone stamp, eraser). (DOC-4973, DOC-4975)
- Text tools plugin. (DOC-4974)
- Added vibrance and saturation to image filters plugin. (DOC-4971, DOC-4972)
- Added "Save changes" confirmation prompts.
- Added imageQuality option: used for image formats that use lossy compression, such as JPEG and WEBP.
  The value should be a number between 0 and 1, where 0 represents the lowest, and 1 the highest quality.
  If this option is not specified, the default value of 0.92 is used. 
  Please note that this option only affects image editing capabilities.
  ```javascript
  // Example:
  var viewer = new GcImageViewer("#root", {
    // Set image quality to 50%:
    imageQuality: 0.5
  });
  ```

## [1.1.5] - 11-Jul-2023
### Fixed
- Incorrect display of ICO images with Rgb15 frame encoding. (DOC-5084)

## [1.1.3] - 31-May-2023
### Fixed
- The expand toolbar of second toolbar is not visible in the theme "dark". (DOC-5340)
- Cannot add image filters plugin to the left bar again if it was added and removed before. (DOC-5328)
- Add new PageToolsPlugin will affect old PageToolsPlugin. (DOC-5325)
- The ellipsis button should be hidden for PageTools/ImageFilters toolbars. (DOC-5371)

## [1.1.0] - 03-Apr-2023
### Added
- Added keyboard shortcuts: Undo/Redo: Ctrl+Z/Ctrl+Y, Rotate: R/Shift+R, 
  Zoom-in/Zoom-out: Ctrl++/Ctrl+-, Zoom to 100%: Ctrl+0, File open: Ctrl+O.
- [Crop/resize tools] Keyboard shortcuts: Ctrl+Enter to apply changes, Esc to cancel.
- [Resize tool] Press and hold Shift to temporarily toggle the 'keep aspect ratio' setting.
- Added the ability to specify a custom renderer function for the second toolbar layout.
```javascript
  // Example:
  viewer.secondToolbarLayout["hello-world-toolbar-key"] = (toolbarKey: string) => {
      return [<div>Hello world, second toolbar key is {toolbarKey}</div>];
  };
  viewer.showSecondToolbar("hello-world-toolbar-key");
```
### Changed
- Crop/resize tools improved (got rid of popup dialogs, toolbars changed). (DOC-4970)
### Fixed
- [Image Filters Plugin] Clicking custom image filter plugin has no effect. (DOC-5329)
- [Page Tools Plugin] After several rotations unexpected white space appears. (DOC-5330)
- Miscellaneous minor fixes.

## [1.0.4] - 06-Feb-2023
### Fixed
- Cannot display ICO images using Argb32 frame encoding format. (DOC-5077)

## [1.0.3] - 20-Jan-2023
### Added
- Added the ability to select/copy/search text content in SVG images. (DOC-4952)

## [1.0.1] - 21-Dec-2022
### Fixed
- [iOS] The flip vertical icon is incorrect. (DOC-4867)
- Cannot load a TIFF or GIF image when ImageFilters plugin is added without sidebar panel. (DOC-4967)
- The zoom toolbar buttons overlap the zoom input box. (DOC-4991)
- SVG image is clipped when its viewBox has a negative offset. (DOC-4990)

## [1.0.0] - 06-Dec-2022
### Added
- Added isAnimationStarted property: gets a value indicating whether the image animation has started.
```javascript
  // Example: toggle image animation:
  const viewer = GcImageViewer.findControl("#root");
  if(viewer.isAnimationStarted) {
    viewer.stopAnimation();
  } else {
    viewer.startAnimation();
  }
```
- [Page Tools plugin] [Crop dialog] Added the ability to select a crop area using the selection UI.
- Implemented standard licensing. (DOC-4586)
- Added image filters plugin. (DOC-4585)
- Added the ability to provide own image filter using the filters property.
```javascript
  // Example: create Image Filters plugin:
  const imageFiltersPlugin = new ImageFiltersPlugin();
  // Remove the default image filters, except for the "Invert" filter:
  const filters = imageFiltersPlugin.filters;
  for (const filterName in filters) {
    if(filterName === "invert")
      continue;
    delete filters[filterName];
  }
  // Add custom Image Filter:
  filters["lemon-effect"] = {
    filterId: "lemon-effect",
    toolbarKey: "lemon-effect",
    title: "Apply Custom Lemon effect",
    text: "Apply Lemon effect",
    action: function(imageData) {
      for (let i = 0; i < imageData.data.length; i += 4) {
        imageData.data[i + 1] = imageData.data[i] + 45; // increase green component
      }
      return imageData;
    }
  };
  // Register Image Filters plugin:
  viewer.addPlugin(imageFiltersPlugin);
```
- Added PageToolsPlugin, which replaces the Rotation plugin. This plugin provides crop/resize dialog and functionality.
```javascript
  // Example:
  viewer.addPlugin(new PageToolsPlugin());
```
- Added maxImageSize option, which replaces the maxCanvasPixels option. Use maxImageSize to limit the image size when editing an image.
```javascript
  // Example:
  var viewer = new GcImageViewer("#root", { maxImageSize: { width: 1080, height: 1350 } });
```
- Added vertical flip tool. (DOC-4582)
- Added close() method.
- Added the ability to disable individual undo operations using the skipCommands setting.\
  Available command names are: "Open", "Close", "FrameIndex", "Zoom", "Rotation", "Flip",
  "StartAnimation", "StopAnimation".\
  Note that the "Open"/"Close" and "StartAnimation"/"StopAnimation" commands are paired - if one command is skipped,
  the other command will also be skipped.
```javascript
  // Example:
  var viewer = new GcImageViewer("#root", { undo: { skipCommands: ["Open", "Close", "Zoom"] } });
```
- Added findPlugin method - finds a viewer plugin by its id.
```javascript
  // Example:
  var pluginRotate = viewer.findPlugin("rotation");
```
- Added command based undo state storage. (DOC-4583)
```javascript
  // Example 1: disable undo storage.
  var viewer = new GcImageViewer("#root", { undo: false });
```
```javascript
  // Example 2: Limit the maximum number of undo levels to 5.
  var viewer = new GcImageViewer("#root", { undo: { maxLevels: 5 } });
```
```javascript
  // Example 3: Create an undoable custom command that changes the opacity of the main viewer element.
  var viewer = new GcImageViewer("#root");
  function CustomOpacityCommand(opacity) {
      if(opacity !== undefined) {
      this.opacity = opacity;
    }
  }
  CustomOpacityCommand.prototype = {
    opacity: "0.5",
    prevOpacity: "",
    execute: function(viewer) {
      return new Promise((resolve) => {
        this.prevOpacity = viewer.hostElement.style.opacity;                                
        viewer.hostElement.style.opacity = this.opacity;
        resolve();
      })
    },
    undo: function(viewer) {
      return new Promise((resolve)=>{
        viewer.hostElement.style.opacity = this.prevOpacity;
        resolve();
      })
    }
  };
  // Open image:
  await viewer.open(https://example.com/download?file=images/image.jpg);
  // Clear undo storage:
  viewer.clearUndo();
  // Execute custom command:
  await viewer.executeCommand(new CustomOpacityCommand(0.2))
  // Undo to previous state:
  await viewer.undo();
  // Redo to next state:
  await viewer.redo();
```
### Fixed
- Incorrect SVG image size when the SVG contains elements that are larger than the outer "SVG" element. (DOC-4726)
- Zoom to cursor using mouse wheel does not work for SVG images. (DOC-4728)
- The frameIndex is incorrect when switching from BMP to TIFF using the undo button. (DOC-4637)
- [API reference] Added missing descriptions. (DOC-4681, DOC-4639)

## [1.0.0-beta.4] - 21-Oct-2022
### Fixed
- Incorrect button position when the RotationPluginOptions is false. (DOC-4633)
- The frameIndex is incorrect when switching from BMP to TIFF using the undo button. (DOC-4637)
- [API reference] Added missing descriptions. (DOC-4681, DOC-4639)
### Added
- Added PageToolsPlugin, which replaces the Rotation plugin. This plugin provides crop/resize dialog and functionality.
```javascript
  // Example:
  viewer.addPlugin(new PageToolsPlugin());
```
- Added maxImageSize option, which replaces the maxCanvasPixels option. Use maxImageSize to limit the image size when editing an image.
```javascript
  // Example:
  var viewer = new GcImageViewer("#root", { maxImageSize: { width: 1080, height: 1350 } });
```

## [1.0.0-beta.3] - 19-Sep-2022
### Fixed
- [docs] The description of "flipHorizontal" is incorrect. (DOC-4632)
- Errors when performing undo operations. (DOC-4631, DOC-4635, DOC-4634)
- UI issues. (DOC-4633)
### Changed
- Rotation plugin options changed, available options are:
  * rotatePosition - position of the "Rotate Image" button.
  * flipHorizontalPosition - position of the "Flip horizontal" button.
  * flipVerticalPosition - position of the "Flip vertical" button.
### Added
- Added vertical flip tool. (DOC-4582)
- Added close() method.
- Added the ability to disable individual undo operations using the skipCommands setting.
  Available command names are: "Open", "Close", "FrameIndex", "Zoom", "Rotation", "Flip",
  "StartAnimation", "StopAnimation".\
  Note that the "Open"/"Close" and "StartAnimation"/"StopAnimation" commands are paired - if one command is skipped,
  the other command will also be skipped.
```javascript
  // Example:
  var viewer = new GcImageViewer("#root", { undo: { skipCommands: ["Open", "Close", "Zoom"] } });
```
- Added findPlugin method - finds a viewer plugin by its id.
```javascript
  // Example:
    var pluginRotate = viewer.findPlugin("rotation");
```
- Added command based undo state storage. (DOC-4583)
```javascript
// Example 1: disable undo storage.
var viewer = new GcImageViewer("#root", { undo: false });
```
```javascript
// Example 2: Limit the maximum number of undo levels to 5.
var viewer = new GcImageViewer("#root", { undo: { maxLevels: 5 } });
```
```javascript
// Example 3: Create an undoable custom command that changes the opacity of the main viewer element.
var viewer = new GcImageViewer("#root");
function CustomOpacityCommand(opacity) {
    if(opacity !== undefined) {
    this.opacity = opacity;
  }
}
CustomOpacityCommand.prototype = {
  opacity: "0.5",
  prevOpacity: "",
  execute: function(viewer) {
    return new Promise((resolve) => {
      this.prevOpacity = viewer.hostElement.style.opacity;			
      viewer.hostElement.style.opacity = this.opacity;
      resolve();
    })
  },
  undo: function(viewer) {
    return new Promise((resolve)=>{
      viewer.hostElement.style.opacity = this.prevOpacity;
      resolve();
    })
  }
};
// Open image:
await viewer.open("https://example.com/download?file=images/image.jpg");
// Clear undo storage:
viewer.clearUndo();
// Execute custom command:
await viewer.executeCommand(new CustomOpacityCommand(0.2))
// Undo to previous state:
await viewer.undo();
// Redo to next state:
await viewer.redo();
```

## [1.0.0-beta.2] - 24-Aug-2022
### Fixed
- Fixed several issues with the toolbar layout. (DOC-4560, DOC-4561)
- [iOS] The "whole image" display option does not work correctly. (DOC-4478)
### Changed
- Default min/max zoom factors updated:
  - The default min zoom factor changed from 0.25 to 0.1 (10%).
  - The default max zoom factor changed from 3.0 to 10.0 (1000%).
### Added
- RotationPlugin: added "Flip image" button.
- Added "Print" feature.
- Zooming with the mouse wheel now respects the position of the cursor.
- Added theme option, use it to change the default viewer theme.\
  Available built-in themes are: "gc-blue", "viewer", "dark", "dark-yellow", "light", "light-blue".
  The default theme is "gc-blue".\
  Set this option to false if you want to disable theme loading
  (this can be helpful if you have already included a theme css).
```javascript
// Example 1: Use the built-in light theme:
var viewer = new GcImageViewer("#root", { theme: "light" });
```
```javascript
// Example 2: Load light theme using relative URL:
var viewer = new GcImageViewer("#root", { theme: "themes/light.css" });
```
```javascript
// Example 3: Load dark theme using absolute URL:
var viewer = new GcImageViewer("#root", { theme: "http://localhost:8080/themes/dark.css" });
```
```html
<!-- Example 4: load the theme CSS in HTML: -->
<link href="~/Content/light-blue.css" rel="stylesheet" />
...
// So do not load the built-in theme:
var viewer = new GcImageViewer("#root", { theme: false } );
```

## [1.0.0-beta.1] - 09-Aug-2022
- The first public BETA release of GcImageViewer.
