SwiftUI tint for image but preserving Black and White - colors

I need to shift the color in an image, e.g. from gray to green. But only the parts that are not white and/or black...
For UIKit I had a handy extension:
// colorize image with given tint color
// this is similar to Photoshop's "Color" layer blend mode
// this is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved
// white will stay white and black will stay black as the lightness of the image is preserved
func tint(tintColor: UIColor) -> UIImage {
return modifiedImage { context, rect in
// draw black background - workaround to preserve color of partially transparent pixels
context.setBlendMode(.normal)
UIColor.black.setFill()
context.fill(rect)
// draw original image
context.setBlendMode(.normal)
context.draw(self.cgImage!, in: rect)
// tint image (loosing alpha) - the luminosity of the original image is preserved
context.setBlendMode(.color)
tintColor.setFill()
context.fill(rect)
// mask by alpha values of original image
context.setBlendMode(.destinationIn)
context.draw(self.cgImage!, in: rect)
}
}
is there any way to generate the same functionality with the tint options in SwiftUI?
".colorMultiply" colors white as well.
".saturation(0.5)" directly generates a grayscale image.

You can continue to use your extension, like
var body: some View {
Image(uiImage: UIImage(named: "some")!.tint(tintColor: UIColor.red))
}

I was looking for the wrong keyword.
The actually way to do this in SwiftUI is hueRotation!
It only works with coloured images and not with grayscale images though.
See example below:
Color.blue
.hueRotation(.degrees(-45.0))

Related

MagickWand: transparent SVG part rendered as white background

I am trying to read SVG images using ImageMagick (6.8.8-7) and get valid transparent pixels.
The code below is working well with PNG format, but for SVG i can only have some white background.
So i tried to add MagickSetBackgroundColor, and MagickSetImageBackgroundColor with some merging layers but i still can't make it works.
Below an extract from the PoC:
MagickWandGenesis();
m_wand = NewMagickWand();
MagickReadImage(m_wand, file_name);
hasAlfa = MagickGetImageAlphaChannel(m_wand);
fprintf(stderr, "alpha channel detection: %d\n", hasAlfa);
if (hasAlfa == MagickTrue) {
PixelWand *color;
MagickWand *new_wand;
imagedata = malloc(w*h*4);
color = NewPixelWand();
PixelSetColor(color, "none");
MagickSetBackgroundColor(m_wand, color);
MagickSetImageBackgroundColor(m_wand, color);
new_wand = MagickMergeImageLayers(m_wand, MergeLayer);
DestroyMagickWand(m_wand);
m_wand = new_wand;
mrc = MagickExportImagePixels(m_wand, 0, 0, (size_t)w, (size_t)h, "RGBA", CharPixel, imagedata);
fprintf(stderr, "R:%d G:%d B:%d A:%d\nR:%d G:%d B:%d A:%d\n", imagedata[0], imagedata[1], imagedata[2], imagedata[3], imagedata[4], imagedata[5], imagedata[6], imagedata[7]);
}
Result using a PNG image:
size: 9 x 11
alpha channel detection: 1
R:0 G:0 B:0 A:0
R:0 G:0 B:0 A:0
Result using a SVG image:
size: 640 x 1000
alpha channel detection: 1
R:255 G:255 B:255 A:255
R:255 G:255 B:255 A:255
Any clues ?
I hope, I understood your question. To convert transparence from svg to png a pixel has to be defined as transparent.
You can define transparency in svg using "opacity", but in svg transparency is only given for next layer (not alpha-layer, that shines through all objects like in alpha).
If you want alpha transparency on an png, it's really the best way to define (i.e. white), and set that to alpha transperency

Gradient text fill using GD - PHP

I need a function that renders gradient on a text using GD
something like
function gradientText($text,$font,$color1,$color2)
{
..
}
I suggest you try to build that function based your own needs.
You will want to center the text vertically/horizontal, change font size, etc...
Start on this function by Christopher Kramer, code is also below this answer...
http://www.php.net/manual/en/function.imagefill.php#93920
then you can use imagettfbbox if you want to use custom font files.
http://www.php.net/manual/en/function.imagettfbbox.php
Here is a sample image I generated using those 2 functions.
Pasting Chris' code of gradient here for reference:
<?php
function gradient($w=100, $h=100, $c=array('#FFFFFF','#FF0000','#00FF00','#0000FF'), $hex=true) {
/*
Generates a gradient image
Author: Christopher Kramer
Parameters:
w: width in px
h: height in px
c: color-array with 4 elements:
$c[0]: top left color
$c[1]: top right color
$c[2]: bottom left color
$c[3]: bottom right color
if $hex is true (default), colors are hex-strings like '#FFFFFF' (NOT '#FFF')
if $hex is false, a color is an array of 3 elements which are the rgb-values, e.g.:
$c[0]=array(0,255,255);
*/
$im=imagecreatetruecolor($w,$h);
if($hex) { // convert hex-values to rgb
for($i=0;$i<=3;$i++) {
$c[$i]=hex2rgb($c[$i]);
}
}
$rgb=$c[0]; // start with top left color
for($x=0;$x<=$w;$x++) { // loop columns
for($y=0;$y<=$h;$y++) { // loop rows
// set pixel color
$col=imagecolorallocate($im,$rgb[0],$rgb[1],$rgb[2]);
imagesetpixel($im,$x-1,$y-1,$col);
// calculate new color
for($i=0;$i<=2;$i++) {
$rgb[$i]=
$c[0][$i]*(($w-$x)*($h-$y)/($w*$h)) +
$c[1][$i]*($x *($h-$y)/($w*$h)) +
$c[2][$i]*(($w-$x)*$y /($w*$h)) +
$c[3][$i]*($x *$y /($w*$h));
}
}
}
return $im;
}
function hex2rgb($hex)
{
$rgb[0]=hexdec(substr($hex,1,2));
$rgb[1]=hexdec(substr($hex,3,2));
$rgb[2]=hexdec(substr($hex,5,2));
return($rgb);
}
// usage example
$image=gradient(300, 300, array('#000000', '#FFFFFF', '#FF0000', '#0000FF'));
header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
Using GD
http://planetozh.com/blog/my-projects/images-php-gd-gradient-fill/ offers a class to create a gradient with GD.
Gradient can be linear (horizontal or vertical), radial, rectangle, diamond. That's the same options you would find on Adobe Photoshop.
The class methods fill rectangular areas with a gradient, so you could achieve a rather great gradient effect with the following method:
create a gradient rectangle with this class
write your text in the specified font
mix them:
you could cut the gradient picture with the shape of the text picture
you could apply the gradient picture as a pattern for the text picture
Using ImageMagick
Instead to use GD, I would use ImageMagick.
See http://www.imagemagick.org/Usage/fonts/#gradient for a sample of how to use ImageMagick to achieve that, and http://www.imagemagick.org/Usage/canvas/#gradient for all the gradients options.

fix a splash screen image to display in j2me

In my j2me App I have tried canvas which works great on Nokia phone but doesn't run on samsung. For that I have to switch to some FORM which in both cases works but only issue is of size, if I create smaller image to fit for both phone screens, one (samsung) shows that ok but other (nokia) leaves a lot more space and vice versa.
I need to have code that could stretch my image and just fix if to the screen size which I basically get by form.getHeight() and form.getWidth() property. I wonder if there is property of Image.createImage(width, height) then why doesn't it stretch it to the value I provide?
my code for that is below
try {
System.out.println("Height: " + displayForm.getHeight());
System.out.println("Width: " + displayForm.getWidth());
Image img1 = Image.createImage("/bur/splashScreen1.PNG");
img1.createImage(displayForm.getHeight(), displayForm.getWidth());
displayForm.append(new ImageItem(null, img1, Item.LAYOUT_CENTER, null));
} catch (Exception ex) {
}
Image
A single image will not fit all screens. But more will do.
The smaller logo image should be less than 96x54, as this is the smallest screen resolution. This image can be used up to the resolution of 128x128 without problems. With bigger resolutions it will look tiny, though.
The bigger logo image should be a bit bigger than 128x128 and can be used up to 240x320.
The code bellow gives as example of how to implement this.
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.Graphics;
class Splash extends javax.microedition.lcdui.Canvas {
Image logo;
Splash () {
if (getWidth() <= 128) {
// sl stands for Small Logo and does not need to have a file extension
// this will use less space on the jar file
logo = Image.createImage("/sl");
} else {
// bl stands for Big Logo
logo = Image.createImage("/bl");
}
}
protected void paint (Graphics g) {
// With these anchors your logo image will be drawn on the center of the screen.
g.drawImage(logo, getWidth()/2, getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
}
}
As seen in http://smallandadaptive.blogspot.com.br/2008/10/showing-splash.html
wonder if there is property of Image.createImage(width, height) then why doesn't it stretch it to the value I provide?
Parameters in this method have nothing to do with stretching, see API javadocs:
public static Image createImage(int width, int height)
Creates a new, mutable image for off-screen drawing.
Every pixel within the newly created image is white.
The width and height of the image must both be greater than zero.
Parameters:
width - the width of the new image, in pixels
height - the height of the new image, in pixels
Image class (API javadocs) has two more createImage methods that use parameters called "width" and "height" - one with six, another with four arguments but none of these has anything to do with stretching.
In createImage with six arguments, width and height specify size of the region to be copied (without stretching) from source image.
In method with four arguments, width and height specify how to interpret source ARGB array, without these it would be impossible to find out if, say, array of 12 values represents 3x4 image or 4x3. Again, this has nothing to do with stretching.

How to change bitmap image runtime based on condition and set on canvas?

I have nine rectangles drawn on canvas and I had set image on it through bitmap by decoding it from resources. I am generating random numbers between 1 to 10 and set it to text view.
When user moves to rectangle based on number displaying in text view the image of that particular rectangle should be changed
if(textview.getText().toString()==1)
{
canvas.drawBitmap(bitmapHolo,null,rect[i],null);
}
else
{
canvas.drawBitmap(bitmapRectangle,null,rect[i],null);
}

Retrieving a CGRect from a transformed CGContext and apply to a UIView

I am drawing a PDF page into a CGContext.
In order to properly draw it, I am applying some transformations to the context.
The pdf page rendered rect is smaller than the view's rect.
I want to create a third view that has exact same frame as the part of the view that has a pdf rendered.
My solution works, but not entirely. Sometimes (a lot of times) the rect is wrong.
This is what I am doing:
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
CGContextSaveGState(context);
// apply transforms to context
// draw pdf page
CGRect calculatedFromRect = CGRectApplyAffineTransform(pageRect, CGContextGetCTM(context));
CGContextRestoreGState(context);
// now draw a green rect to test the frame on a not transformed context
GContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
CGContextFillRect(context, calculatedFromRect);
self.thirdView.frame = calculatedFromRect;
}
The thirdView is red. When both rects (view and drawing) are equal, I see a brown rect on the screen (red with alpha on top of the green rect). But sometimes I can see they two separated from each other (offset and size difference...when this happens, the thirdView.frame is bigger than calcularedRect).
Since all the involved views have the same size and coordinates, not converting the coordinates with convertRect:fromView: shouldn't be a problem. But I tried this and the result was the same.

Resources