mirror of
https://github.com/igorski/bitmappery.git
synced 2026-06-17 03:34:56 +02:00
Transparent layers are now also stored with transparency
This commit is contained in:
@@ -57,9 +57,9 @@ npm run lint
|
||||
# TODO / Roadmap
|
||||
|
||||
* Implement loaders on document load/save, image export and dropbox import
|
||||
* Canvas util : store transparency of images into saved document
|
||||
* Drawing masks on a rotated layer that is panned (or mirrored) is broken
|
||||
* Dragging of masks on rotated/mirror content is kinda broken
|
||||
* Restoring of document with rotated layers (smaller than document size) restores at incorrect offset
|
||||
* Pasted selections should appear in center
|
||||
* Zoom should always be center based
|
||||
* Restoring documents containing rotated text is inaccurate
|
||||
|
||||
@@ -24,12 +24,22 @@ export const JPEG = "image/jpeg";
|
||||
export const PNG = "image/png";
|
||||
export const GIF = "image/gif";
|
||||
|
||||
const TRANSPARENT_TYPES = [ PNG, GIF ];
|
||||
|
||||
export const ACCEPTED_FILE_TYPES = [ JPEG, PNG, GIF ];
|
||||
export const ACCEPTED_FILE_EXTENSIONS = [ "jpg", "jpeg", "png", "gif" ];
|
||||
export const EXPORTABLE_FILE_TYPES = [ JPEG, PNG ];
|
||||
|
||||
export const isCompressableFileType = type => type === JPEG;
|
||||
|
||||
export const isTransparent = ({ name, type }) => {
|
||||
if ( type === "dropbox" ) {
|
||||
// files imported from Dropbox don't list their mime type, derive from filename instead
|
||||
return name.includes( ".png" ) || name.includes( ".gif" );
|
||||
}
|
||||
return TRANSPARENT_TYPES.includes( type );
|
||||
}
|
||||
|
||||
export const typeToExt = type => {
|
||||
switch ( type ) {
|
||||
default:
|
||||
|
||||
@@ -33,7 +33,7 @@ const LayerFactory = {
|
||||
*/
|
||||
create({
|
||||
name = "New Layer",
|
||||
type = LAYER_GRAPHIC, source = null, mask = null,
|
||||
type = LAYER_GRAPHIC, transparent = true, source = null, mask = null,
|
||||
x = 0, y = 0, maskX = 0, maskY = 0, width = 1, height = 1, visible = true,
|
||||
effects = {}, text = {}
|
||||
} = {}) {
|
||||
@@ -42,6 +42,7 @@ const LayerFactory = {
|
||||
name,
|
||||
type,
|
||||
source,
|
||||
transparent,
|
||||
mask,
|
||||
x,
|
||||
y,
|
||||
@@ -65,8 +66,9 @@ const LayerFactory = {
|
||||
return {
|
||||
n: layer.name,
|
||||
t: layer.type,
|
||||
s: imageToBase64( layer.source, layer.width, layer.height ),
|
||||
m: imageToBase64( layer.mask, layer.width, layer.height ),
|
||||
tr: layer.transparent,
|
||||
s: imageToBase64( layer.source, layer.width, layer.height, layer.transparent ),
|
||||
m: imageToBase64( layer.mask, layer.width, layer.height, true ),
|
||||
x: layer.x,
|
||||
y: layer.y,
|
||||
x2: layer.maskX,
|
||||
@@ -89,6 +91,7 @@ const LayerFactory = {
|
||||
return LayerFactory.create({
|
||||
name: layer.n,
|
||||
type: layer.t,
|
||||
transparent: layer.tr,
|
||||
source,
|
||||
mask,
|
||||
x: layer.x,
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
import { mapGetters, mapMutations, mapActions } from "vuex";
|
||||
import { LAYER_IMAGE } from "@/definitions/layer-types";
|
||||
import { isTransparent } from "@/definitions/image-types";
|
||||
import { LAYER_IMAGE } from "@/definitions/layer-types";
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
@@ -51,8 +52,10 @@ export default {
|
||||
source: image,
|
||||
type: LAYER_IMAGE,
|
||||
name: file.name,
|
||||
transparent: isTransparent( file ),
|
||||
...size,
|
||||
};
|
||||
|
||||
switch ( this.fileTarget) {
|
||||
default:
|
||||
case "layer":
|
||||
|
||||
@@ -40,15 +40,15 @@ export const createCanvas = ( optWidth = 0, optHeight = 0 ) => {
|
||||
return { cvs, ctx };
|
||||
};
|
||||
|
||||
export const imageToBase64 = ( bitmap, width, height ) => {
|
||||
export const imageToBase64 = ( bitmap, width, height, transparent ) => {
|
||||
let cvs;
|
||||
if ( bitmap instanceof Image ) {
|
||||
({ cvs } = createCanvas( width, height ));
|
||||
cvs.getContext( "2d" ).drawImage( bitmap, 0, 0 );
|
||||
return cvs.toDataURL( JPEG ); // assume photographic content TODO: check transparency
|
||||
return cvs.toDataURL( transparent ? PNG : JPEG );
|
||||
} else if ( bitmap instanceof HTMLCanvasElement ) {
|
||||
cvs = bitmap;
|
||||
return cvs.toDataURL( PNG ); // assume transparent content
|
||||
return cvs.toDataURL( PNG ); // Canvas sources are always transparent
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ describe( "Layer factory", () => {
|
||||
id: expect.any( String ),
|
||||
name: expect.any( String ),
|
||||
type: LAYER_GRAPHIC,
|
||||
transparent: true,
|
||||
source: null,
|
||||
mask: null,
|
||||
x: 0,
|
||||
@@ -57,6 +58,7 @@ describe( "Layer factory", () => {
|
||||
const layer = LayerFactory.create({
|
||||
name: "foo",
|
||||
type: LAYER_IMAGE,
|
||||
transparent: false,
|
||||
source: { src: "bitmap" },
|
||||
mask: { src: "mask" },
|
||||
x: 100,
|
||||
@@ -77,6 +79,7 @@ describe( "Layer factory", () => {
|
||||
id: expect.any( String ),
|
||||
name: "foo",
|
||||
type: LAYER_IMAGE,
|
||||
transparent: false,
|
||||
source: { src: "bitmap" },
|
||||
mask: { src: "mask" },
|
||||
x: 100,
|
||||
@@ -102,6 +105,7 @@ describe( "Layer factory", () => {
|
||||
const layer = LayerFactory.create({
|
||||
name: "foo",
|
||||
type: LAYER_IMAGE,
|
||||
transparent: false,
|
||||
source: { src: "bitmap" },
|
||||
mask: { src: "mask" },
|
||||
x: 100,
|
||||
@@ -119,8 +123,8 @@ describe( "Layer factory", () => {
|
||||
mockUpdateFn = jest.fn(( fn, data ) => data );
|
||||
|
||||
const serialized = LayerFactory.serialize( layer );
|
||||
expect( mockUpdateFn ).toHaveBeenNthCalledWith( 1, "imageToBase64", layer.source, layer.width, layer.height );
|
||||
expect( mockUpdateFn ).toHaveBeenNthCalledWith( 2, "imageToBase64", layer.mask, layer.width, layer.height );
|
||||
expect( mockUpdateFn ).toHaveBeenNthCalledWith( 1, "imageToBase64", layer.source, layer.width, layer.height, layer.transparent );
|
||||
expect( mockUpdateFn ).toHaveBeenNthCalledWith( 2, "imageToBase64", layer.mask, layer.width, layer.height, true );
|
||||
expect( mockUpdateFn ).toHaveBeenNthCalledWith( 3, "serializeText", layer.text );
|
||||
expect( mockUpdateFn ).toHaveBeenNthCalledWith( 4, "serializeEffect", layer.effects );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user