[MagickWand] Keep SVG background transparency when compositing
Posted: 2018-07-18T09:47:25-07:00
Hi everyone,
I'm using the C API like to do some picture watermarking but I can't get it working.
Basically, I want to do the following command programmatically :
The SVG file is taken from wikimedia and the JPG file is a picture I took with my camera.
My code works except:
- I have to manually compute the watermark offset. I tried MagickSetGravity but it seems it doesn't do anything in my case.
- I'm loosing the transparent background. I tried PixelSetColor + MagickSetImageBackgroundColor, played with MagickSetImageAlpha, checked the colorspace is sRGB.. with no success. If I manually convert the SVG file to a PNG one using GIMP and update my code to point to the right file it works so I guess it may be related to the SVG parser.
My code is a bit long but it's very straightforward.
Any idea ?
Thanks for reading me!
I'm using the C API like to do some picture watermarking but I can't get it working.
Basically, I want to do the following command programmatically :
Code: Select all
composite -background none -dissolve 25% -gravity center Vector-based_exemple.svg IMG_1780.JPG out.jpg
My code works except:
- I have to manually compute the watermark offset. I tried MagickSetGravity but it seems it doesn't do anything in my case.
- I'm loosing the transparent background. I tried PixelSetColor + MagickSetImageBackgroundColor, played with MagickSetImageAlpha, checked the colorspace is sRGB.. with no success. If I manually convert the SVG file to a PNG one using GIMP and update my code to point to the right file it works so I guess it may be related to the SVG parser.
My code is a bit long but it's very straightforward.
Code: Select all
#include <stdio.h> /* For printf */
#include <stdbool.h> /* For bool */
#include <stdint.h> /* For uint8_t */
#include <MagickWand/MagickWand.h>
bool loadPictureIntoBuffer(char *pictureFilePath,
uint8_t **pictureBuffer, size_t *pictureBufferLen)
{
size_t nbRead;
FILE *pictureFile;
size_t pictureFileLen;
uint8_t *pictureBufferTemp;
if (!pictureFilePath) return false;
if (!pictureBuffer) return false;
if (!pictureBufferLen) return false;
pictureFile = NULL;
pictureBufferTemp = NULL;
pictureFile = fopen(pictureFilePath, "rb");
if (!pictureFile) goto cleanup;
fseek(pictureFile, 0, SEEK_END);
pictureFileLen = ftell(pictureFile) * sizeof(uint8_t);
if (!pictureFileLen) goto cleanup;
fseek(pictureFile, 0, SEEK_SET);
pictureBufferTemp = malloc(pictureFileLen);
if (!pictureBufferLen) goto cleanup;
nbRead = fread(pictureBufferTemp, 1, pictureFileLen, pictureFile);
if (nbRead != pictureFileLen) goto cleanup;
fclose(pictureFile);
*pictureBuffer = pictureBufferTemp;
*pictureBufferLen = pictureFileLen;
return true;
cleanup:
if (pictureBufferTemp) free(pictureBufferTemp);
if (pictureFile) fclose(pictureFile);
return false;
}
bool readPictureFromMemory(MagickWand *magickWand,
uint8_t *pictureBuffer, size_t pictureBufferLen,
size_t *pictureWidth, size_t *pictureHeight)
{
PixelWand *pxWand;
MagickBooleanType ret;
size_t pictureWidthTemp;
size_t pictureHeightTemp;
OrientationType pictureOrientation;
if (!magickWand) return false;
if (!pictureBuffer) return false;
if (!pictureBufferLen) return false;
if (!pictureWidth) return false;
if (!pictureHeight) return false;
pxWand = NULL;
ret = MagickReadImageBlob(magickWand, pictureBuffer, pictureBufferLen);
if (!ret) return false;
pictureOrientation = MagickGetImageOrientation(magickWand);
switch (pictureOrientation)
{
case LeftTopOrientation:
case TopRightOrientation:
case RightBottomOrientation:
case LeftBottomOrientation:
{
pictureWidthTemp = MagickGetImageHeight(magickWand);
pictureHeightTemp = MagickGetImageWidth(magickWand);
}
default:
{
pictureWidthTemp = MagickGetImageWidth(magickWand);
pictureHeightTemp = MagickGetImageHeight(magickWand);
}
}
if (!pictureWidthTemp || !pictureHeightTemp) return false;
switch (pictureOrientation)
{
case UndefinedOrientation:
case TopLeftOrientation:
default:
break;
case TopRightOrientation:
{
ret = MagickFlopImage(magickWand);
if (!ret) return false;
}
case BottomRightOrientation:
{
pxWand = NewPixelWand();
if (!pxWand) goto cleanup;
ret = MagickRotateImage(magickWand, pxWand, 180.0);
if (!ret) goto cleanup;
}
case BottomLeftOrientation:
{
ret = MagickFlipImage(magickWand);
if (!ret) return false;
}
case LeftTopOrientation:
{
ret = MagickTransposeImage(magickWand);
if (!ret) return false;
}
case RightTopOrientation:
{
pxWand = NewPixelWand();
if (!pxWand) goto cleanup;
ret = MagickRotateImage(magickWand, pxWand, 90.0);
if (!ret) goto cleanup;
}
case RightBottomOrientation:
{
ret = MagickTransverseImage(magickWand);
if (!ret) return false;
}
case LeftBottomOrientation:
{
pxWand = NewPixelWand();
if (!pxWand) goto cleanup;
ret = MagickRotateImage(magickWand, pxWand, 270.0);
if (!ret) goto cleanup;
}
}
ret = MagickSetImageOrientation(magickWand, TopLeftOrientation);
if (!ret) goto cleanup;
*pictureWidth = pictureWidthTemp;
*pictureHeight = pictureHeightTemp;
return true;
cleanup:
if (pxWand) DestroyPixelWand(pxWand);
return false;
}
int main(int argc, char **argv)
{
bool bret;
size_t pictureWidth;
size_t pictureHeight;
MagickBooleanType ret;
uint8_t *pictureBuffer;
size_t pictureBufferLen;
ssize_t watermarkOffsetX;
ssize_t watermarkOffsetY;
MagickWand *mainMagickWand;
size_t watermarkPictureWidth;
size_t watermarkPictureHeight;
MagickWand *watermarkMagickWand;
uint8_t *watermarkPictureBuffer;
size_t watermarkPictureBufferLen;
pictureBuffer = NULL;
pictureBufferLen = 0;
mainMagickWand = NULL;
watermarkMagickWand = NULL;
watermarkPictureBuffer = NULL;
watermarkPictureBufferLen = 0;
MagickWandGenesis();
mainMagickWand = NewMagickWand();
if (!mainMagickWand) goto cleanup;
watermarkMagickWand = NewMagickWand();
if (!watermarkMagickWand) goto cleanup;
bret = loadPictureIntoBuffer("IMG_1780.JPG",
&pictureBuffer, &pictureBufferLen);
if (!bret) goto cleanup;
bret = readPictureFromMemory(mainMagickWand,
pictureBuffer, pictureBufferLen,
&pictureWidth, &pictureHeight);
if (!bret) goto cleanup;
bret = loadPictureIntoBuffer("Vector-based_example.svg",
&watermarkPictureBuffer, &watermarkPictureBufferLen);
if (!bret) goto cleanup;
bret = readPictureFromMemory(watermarkMagickWand,
watermarkPictureBuffer, watermarkPictureBufferLen,
&watermarkPictureWidth, &watermarkPictureHeight);
if (!bret) goto cleanup;
ret = MagickEvaluateImage(watermarkMagickWand, MultiplyEvaluateOperator, 0.5);
if (!ret) goto cleanup;
if (pictureWidth < watermarkPictureWidth) goto cleanup;
if (pictureHeight < watermarkPictureHeight) goto cleanup;
watermarkOffsetX = (pictureWidth - watermarkPictureWidth)/2;
watermarkOffsetY = (pictureHeight - watermarkPictureHeight)/2;
ret = MagickCompositeImage(mainMagickWand,
watermarkMagickWand, OverCompositeOp,
MagickTrue, watermarkOffsetX, watermarkOffsetY);
if (!ret) goto cleanup;
ret = MagickWriteImage(mainMagickWand, "out.jpg");
if (!ret) goto cleanup;
printf("done\n");
if (watermarkPictureBuffer) free(watermarkPictureBuffer);
if (pictureBuffer) free(pictureBuffer);
DestroyMagickWand(watermarkMagickWand);
DestroyMagickWand(mainMagickWand);
MagickWandTerminus();
return 0;
cleanup:
printf("error\n");
if (watermarkPictureBuffer) free(watermarkPictureBuffer);
if (pictureBuffer) free(pictureBuffer);
DestroyMagickWand(watermarkMagickWand);
DestroyMagickWand(mainMagickWand);
MagickWandTerminus();
return -1;
}
Thanks for reading me!