GtkToolButton with custom icon but of stock icon size - icons

I've a GtkToolBar which has say 3 GtkToolButtons with each of these having a stock icon value, and hence they all appear in the same size; now I added a 4th GtkToolButton with a custom image (.png), which was of an arbitrary dimension and only this button ended up looking huge (since the image was of higher resolution). What do I do to scale this GtkToolButton to match the other 3 buttons?
Here's the code which does what I briefed about:
GtkWidget *custom_icon = gtk_image_new_from_file(path);
GtkToolItem *toolbar_item = gtk_toggle_tool_button_new();
gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbar_item), custom_icon);
gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolbar_item), "Custom Item");
gtk_toolbar_insert(toolbar, toolbar_item, -1);

Here is another solution.
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(icon_file_path, NULL);
int width, height;
gdk_pixbuf_get_file_info (icon_file_path, &width, &height);
gtk_icon_theme_add_builtin_icon ("custom_icon", width, pixbuf);
g_object_unref (G_OBJECT (pixbuf));
GtkToolItem *toolbar_item = gtk_toggle_tool_button_new();
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON(toolbar_item), "custom_icon");
If you have the image in different sizes, you can add them all and let Gtk choose the one of the correct size (or resize if not found): Just repeat the first five lines for each of the image files.
You can use your icon anywhere else and its size will also be adjusted automatically.
For example, to use it for your main window:
gtk_window_set_icon_name(GTK_WINDOW(main_window), "custom_icon");

Found it out myself! Here's the trick so that it helps someone like me. Query the icon size from the stock menu item, which is a enum (standard values like GTK_ICON_SIZE_BUTTON, GTK_ICON_SIZE_LARGE_TOOLBAR, etc.). Now get the pixel size using gtk_icon_size_lookup. Create a pixbuf from the custom icon/image file with the right dimensions. Create a GtkImage from that and set it to the new menu item and you're done!
GtkToolItem *stock_menu_item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_NEW);
GtkIconSize toolbar_icon_size = gtk_tool_item_get_icon_size(stock_menu_item);
gint width = 0, height = 0;
gtk_icon_size_lookup(toolbar_icon_size, &width, &height);
GdkPixbuf *app_icon = gdk_pixbuf_new_from_file_at_size(icon_file_path, width, height, NULL);
GtkImage *tray_icon = gtk_image_new_from_pixbuf(app_icon);
g_object_unref(app_icon);
app_icon = NULL;
GtkToolItem *toolbar_item = gtk_toggle_tool_button_new();
gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(toolbar_item), tray_icon);

Related

How would I make a color relative to images in the background?

For example, if you go to Twitter and click on an image, you can see they have a nice color that is close to what you see on the image. I tried looking up ways to achieve this as well as trying to figure it out on my own but no luck. I'm not sure if there's a color: relative property or not.
if you want to use the a colour that exists in your image and set it as a background colour you need to use the canvas element in the following manner:
HTML (this is your image)
<img src="multicolour.jpg" id="mainImage">
JS
window.onload = function() {
// get the body element to set background (this can change dependending of your needs)
let body = document.getElementsByTagName("body")
// get references to the image element that contains the picture you want to match with background
let referenceImage = document.getElementById("mainImage");
// create a canvas element (but don't add it to the page)
let canvas = document.createElement("canvas");
// make the canvas size the same as your image
canvas.width = referenceImage.offsetWidth
canvas.height = referenceImage.offsetHeight
// create the canvas context
let context = canvas.getContext('2d')
// usage your image reference to draw the image in the canvas
context.drawImage(referenceImage,0,0);
// select a random X and Y coordinates inside the drawn image in the canvas
// (you don't have to do this one, but I did to demonstrate the code)
let randomX = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
// THIS IS THE MOST IMPORTANT LINE
// getImageData takes 4 arguments: coord x, coord y, sample size w, and sample size h.
// in our case the sample size is going to be of 1 pixel so it retrieves only 1 color
// the method gives you the data object which constains and array with the r, b, g colour data from the selected pixel
let color = context.getImageData(randomX, randomY, 1, 1).data
// use the data to dynamically add a background color extracted from your image
body[0].style.backgroundColor = `rgb(${color[0]},${color[1]},${color[2]})`
}
here is a gif of the code working... hopefully this helps
UPDATE
Here is the code to select two random points and create a css3 background gradient
window.onload = function() {
// get the body element to set background (this can change dependending of your needs)
let body = document.getElementsByTagName("body")
// get references to the image element that contains the picture you want to match with background
let referenceImage = document.getElementById("mainImage");
// create a canvas element (but don't add it to the page)
let canvas = document.createElement("canvas");
// make the canvas size the same as your image
canvas.width = referenceImage.offsetWidth
canvas.height = referenceImage.offsetHeight
// create the canvas context
let context = canvas.getContext('2d')
// usage your image reference to draw the image in the canvas
context.drawImage(referenceImage,0,0);
// select a random X and Y coordinates inside the drawn image in the canvas
// (you don't have to do this one, but I did to demonstrate the code)
let randomX = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
// THIS IS THE MOST IMPORTANT LINE
// getImageData takes 4 arguments: coord x, coord y, sample size w, and sample size h.
// in our case the sample size is going to be of 1 pixel so it retrieves only 1 color
// the method gives you the data object which constains and array with the r, b, g colour data from the selected pixel
let colorOne = context.getImageData(randomX, randomY, 1, 1).data
// THE SAME TO OBTAIN ANOTHER pixel data
let randomX2 = Math.floor(Math.random() * (referenceImage.offsetWidth - 1) + 1)
let randomY2 = Math.floor(Math.random() * (referenceImage.offsetHeight - 1) + 1)
let colorTwo = context.getImageData(randomX2, randomY2, 1, 1).data
// use the data to dynamically add a background color extracted from your image
//body[0].style.backgroundColor = `rgb(${allColors[0]},${allColors[1]},${allColors[2]})`
body[0].style.backgroundImage = `linear-gradient(to right, rgb(${colorOne[0]},${colorOne[1]},${colorOne[2]}),rgb(${colorTwo[0]},${colorTwo[1]},${colorTwo[2]}))`;
}
The following are your options.
1. Use an svg.
As far as I know there's no way to have javascript figure out what color is being used in a png and set it as a background color. But you can work the other way around. You can have javascript set the background color and an svg image to be the same color.
See this stackoverflow answer to learn more about modifying svgs with javascript.
2. Use a custom font.
There are fonts out there that provide a bunch of icons instead of letters, you can also create your own font if you feel so inclined to do so. With css you just have to set the font-color of that icon to be the same as the background-color of your other element.
Font Awesome provides a bunch of useful custom icons. If the image you need to use happens to be similar to one of theirs, you can just go with them.
3. Use canvas
If you really want to spend the time to code it up you can use a html <canvas/> element and put the image into it. From there you can inspect certain details about the image like its color, then apply that color to other elements. I won't go into too much detail about using this method as it seems like it's probably overkill for what you're trying to do, but you can read up more about from this stackoverflow answer.
4. Just live with it.
Not a fun solution, but this is usually the option I go with. You simply have to hard-code the color of the image into your css and live with it. If you ever need to modify the color of the image, you have to remember to update your css also.

JavaFX: maximum ImageView size

This may sound like a duplicate of Set maximum size for JavaFX ImageView but it's different.
I'd like to restrict the maximum size of an ImageView. Unfortunately, the only way to set the ImageView's size seems to be fitWidth and fitHeight which however enlarges the image if it's smaller than the fit values.
I tried setting fitWidth/fitHeight to 0/0 and wrap the ImageView into a pane with maxWidth set - no success (image is displayed in original size).
To me it seems as this is not achievable by JavaFX, however I can't believe it. But I couldn't find anything online. Are there any tricks/bugs/workarounds on this?
If you dont want the image to stretch, you can use:
setPreserveRatio(true);
Then you are able to fit width and height as you want
ImageView setPreserveRatio javadoc
In javadoc in this method there are the rules of scaling too
You just needed to add in if statement to set those larger than maxsize to a fixed size. The rest would remain their original size.
ImageView im = new ImageView();
im.setImage(image);
im.maxHeight(690 - 10);
int yoursize = 690;
if(im.maxHeight(690 - 10)> yoursize ){
im.setFitHeight(690- 10);
System.out.println("Fix Size : 690 ");
}
im.setPreserveRatio(true);
im.setSmooth(true);
im.setCache(true);
You can get the actual Image resource and query its width/height to use for the fit values:
Image image = imageView.getImage();
double nativeWidth = image.getWidth();
double nativeHeight = image.getHeight();

Fill the QLabel/QGraphics widget placed in the grid with the image

I have placed two QGraphicsView's and one QLabel inside a horizontal layout (QHBoxLayout) with its layoutStretch set to 1, 1, 1. The problem is when I try to load images inside them, the images does not fill the widgets area. Here is the code:
QPixmap pix1("image1.jpg");
pix1 = pix1.scaled(ui->label1->size());
ui->label1->setPixmap(pix);
QPixmap pix2("image2.jpg");
pix2 = pix2.scaled(ui->graphicsView1->size());
ui->graphicsView1->scene()->addPixmap(pix2);
QPixmap pix3("image3.jpg");
pix3 = pix3.scaled(ui->graphicsView2->size());
ui->graphicsView2->scene()->addPixmap(pix3);
And here is the undesired output:
I have tried setting HorizontalPolicy and VerticalPolicy property of widget to Expanding and also Minimum, but none of them helped either.
Set size policy to QSizePolicy::Ignored and scale with Qt::KeepAspectRatioByExpanding:
ui->label1->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
pix1 = pix1.scaled(ui->label1->size(), Qt::KeepAspectRatioByExpanding);
ui->label1->setPixmap(pix);
You probably want to scale pixmaps in resizeEvent().

Twitter bootstrap carousel with pictures that are not uniform

Let me start with i am sorry for the long post.
I'm attempting to use the bootstrap carousel and unfortunately the pictures i have been given are NOT uniform. for example some are 100x200, doe are 150x100, etc. The aspect ratios are different, letter vs landscape. Ive attempted a number of things, including the using the following helper function on load of each of my images in the Carousel:
function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {
var result = { width: 0, height: 0, fScaleToTargetWidth: true };
if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
return result;
}
// scale to the target width
var scaleX1 = targetwidth;
var scaleY1 = (srcheight * targetwidth) / srcwidth;
// scale to the target height
var scaleX2 = (srcwidth * targetheight) / srcheight;
var scaleY2 = targetheight;
// now figure out which one we should use
var fScaleOnWidth = (scaleX2 > targetwidth);
if (fScaleOnWidth) {
fScaleOnWidth = fLetterBox;
}
else {
fScaleOnWidth = !fLetterBox;
}
if (fScaleOnWidth) {
result.width = Math.floor(scaleX1);
result.height = Math.floor(scaleY1);
result.fScaleToTargetWidth = true;
}
else {
result.width = Math.floor(scaleX2);
result.height = Math.floor(scaleY2);
result.fScaleToTargetWidth = false;
}
result.targetleft = Math.floor((targetwidth - result.width) / 2);
result.targettop = Math.floor((targetheight - result.height) / 2);
return result;
}
function OnImageLoad(evt) {
var img = evt.currentTarget;
// what's the size of this image and it's parent
var w = $(img).prop('naturalWidth');
var h = $(img).prop('naturalHeight');
//var tw = $(img).parent().width();
//var th = $(img).parent().height();
var tw = $(img).parent().parent().parent().parent().width();
var th = $(img).parent().parent().parent().parent().height();
// compute the new size and offsets
var result = ScaleImage(w, h, tw, th, true);
// adjust the image coordinates and size
img.width = result.width;
img.height = result.height;
$(img).css("left", result.targetleft);
$(img).css("top", result.targettop);
}
and using the following for each of my images for the carousel
<img src="~/Images/Img1_Tall.jpg" alt="Tall" id="firstImage" onload="OnImageLoad(event);" />
and for the FIRST image in the carousel it works great, but each one after that they seem to just end up their natural size and are horizontally centered but are just against the top boarder of the carousel.
I've even changed the "onload" to pass the values of the length and width of the image but that didn't work either, in debug it seems only the first image kicks off the "onload" event.
the effect i am going for is if the ratio of the container is 3:4 and the ratio of the image is 1:2, the image stretch to meet the left and right edges and would center vertically and have letter box above and below, but the container does not change so that the navigation buttons of the carousel do not move. if the image is 2:1, the image would stretch to meet the top and bottom centered horizontally with letterboxes on the right and left, again keeping the navigation buttons unmoved.
any help would be appreciated... including:
what you are trying to do is crazy
do you want to do something like http://jsbin.com/zotelasa/1 . With that code I can get the active items w,h or any other variables you used in your code to run scale image. Because of parent.parent codes it applies to carousels main divs but you can set your own container.
The quick and dirty solution would be to resize the images using an image editor, and save the properly-sized images to a folder named eg carousel_images. Then whenever you get new content you simply run the image through your editor. With a carousel you're most likely dealing with a number of images in the several to dozens range and not hundreds or thousands.
A more complicated solution is explain to your image provider that you need everything one size. The images aren't going to look right if you're stretching and skewing them on the fly, and you can show them an image with the aspect ratios wrong to explain what you mean.
Finally, as a technical solution, I would try to find out why your image resizer is only being run on the first image. From the sound of it, other images just aren't being run through your function. I think that the technical solution should be a last resort in this case because, like I said, the end results are just not going to be as good. You should at a minimum, if possible, handle each image by hand to make sure the result is adequate.
...And the answer is a little long too...
• I assume that the width’s image’s parent is a constant, and while you don’t change the width’s viewport that must remain.
A-. Get the width’s image’s parent…
(Because the id attribute I took the grand parent’s parameter, that is (must be) the same than the parent’s one).
B-. With the below value deduce the height’s image’s parent, including the preferred ratio (in this case 16x9…
C-. … And with this, set the images’ parents height collection (all the elements with class=”item”).
D-. In order to conserve your carousel’s responsive characteristic, you must add the $F_getAdjustImagesParents function to the window resize event.
E-. Set the slide’s images position to absolute (Note: That must be via JQuery because if you do it in Css the bootstrap carousel will not display correctly. I did it with a new class for the images ('myCarouselImgs').
• Bootstrap carousel’s event 'slide.bs.carousel' and 'slid.bs.carousel'.
As you know, after the ‘click’ event, the slide.bs.carousel event is one of the firsts events that imply the change from the present slide to the next one; while the 'slid.bs.carousel' one is the end of the process.
F-. In the first one (slide.bs.carousel event), using the ‘relatedTarget’ variable of the Bootstrap’s plugin, the item’s id attribute and a item’s data attribute, get the number of the next item (ensure that these last ones -id attribute and data attribute- be present).
G-. In the second one, 'slid.bs.carousel', get the image’s size. For that you need to identify the implied image. I gave an id to each one. With this and the value obtained in previus step, it can do it.
H-. Well, now you already have the four values required for the ScaleImage function. You can call it…
I-. … And apply the result with some effect
var $parentImgW = ' '
var $parentImgH = ' ';
var $myCarousel = $('#myCarousel')
var $carouseItems = $('.item');
function $F_getAdjustImagesParents(){
$parentImgW = $myCarousel.width(); // A
$parentImgH = ($parentImgW*9)/16; // B
$carouseItems.height($parentImgH+'px').css('max-height',$parentImgH+'px'); //C
console.log('$parentImgW ====> '+$parentImgW);
console.log('$parentImgH ====> '+$parentImgH)
};
$F_getAdjustImagesParents();
$(window).on('resize',function(){ // D
$F_getAdjustImagesParents();
});
$('.myCarouselImgs').css('position','absolute'); // E
$myCarousel.on('slide.bs.carousel', function(event) {// The slide’s change process starts
var $slideNum = $("#"+event.relatedTarget.id).data('slide_num'); // F
console.log('$lideNum ====> '+$slideNum)
$myCarousel.on('slid.bs.carousel', function(event) {//The slide’s change process ends
var $imgW = $('#myCarouselSlideImage'+$slideNum).width(); //G
var $imgH = $('#myCarouselSlideImage'+$slideNum).height(); //G
console.log('$imgW ====> '+$imgW);
console.log('$imgH ====> '+$imgH);
var $result = '';
$result = ScaleImage($imgW, $imgH, $parentImgW, $parentImgH, true); //H
console.log('$result.width ====> '+$result.width);
console.log('$result.height ====> '+$result.height);
console.log('$result.targetleft ====> '+$result.targetleft);
console.log('$result.targettop ====> '+$result.targettop);
$('#myCarouselSlideImage'+$slideNum).animate({ // I
width:$result.width+'px',
height:$result.height+'px',
left:$result.targetleft+'px',
top:$result.targettop+'px' },
300);
});
});
See it runnig at https://jsfiddle.net/nd90r1ht/57/ or at https://jsfiddle.net/omarlin25/nd90r1ht/59/

How can an image be cropped based on a set scale of random image?

Working on allowing the upload of images which can range in a variety of size, then allowing to crop a predefined area of the image for a thumbnail.
The thumbnail size is predefined to 150x150. Using the Jcrop.js tool to select a section of the image.
Problem:
When displaying the uploaded image in a smaller size than the original image by implementing set height/width on the image rendered, then there is a scale factor that comes into play when selecting an area to crop.
You either have to scale down the cropping area proportionately or you have to scale the image in relation to the actual image's size in comparison to its displayed size.
Question:
How do I figure out the scale of the browser displayed image vs. original image? I am currently using the following code to save the image, but how would I take into consideration the scaling?
public static Image CropImage(Image originalImage, int x, int y, int width, int height)
{
var bmp = new Bitmap(width, height);
bmp.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
using (var graphic = Graphics.FromImage(bmp))
{
graphic.SmoothingMode = SmoothingMode.AntiAlias;
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.PixelOffsetMode = PixelOffsetMode.HighSpeed;
graphic.DrawImage(originalImage, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel);
return bmp;
}
}
Bonus Question:
Another problem I discovered, is that there seems to be no efficient way to transfer the original file's ImageFormat when creating a new Bitmap which creates a ImageFormatMemoryBMP and when you attempt to call Bitmap.Save(memorystream, original rawformat) it will blow up. And bitmap RawFormat has no setter.
So how can you set the format on a new bitmap?
I think perhaps that this problem is solved purely on the front end, no need to use any server side for this.
Jcrop has a built in scale factor handler.
http://deepliquid.com/content/Jcrop_Sizing_Issues.html
Now you can use this in two ways, as I understand it. Either to 'resize' the image for you on the front end using 'box sizing', or you can tell it the 'truesize' of the image and it will work out the scale factor and handle the coordinates for you on it's own.
Box sizing
$('#cropbox').Jcrop({ boxWidth: 450, boxHeight: 400 });
True Size
$.Jcrop('#cropbox',{ trueSize: [500,370] });
Using the true size method you will need to invoke jcrop using the api method:
http://deepliquid.com/content/Jcrop_API.html#API_Invocation_Method
var jcrop_api,
options = { trueSize: [500,370] };
$('#target').Jcrop(options,function(){
jcrop_api = this;
});
Good luck!

Resources