I am making a system for compositioning an image from multiple images. Let's say I have two images and I want to compose an image like this one :
The thick border defines the complete image that I want. It is a div with the resolution of 600X540 and inside of it two divs, each one containing a different image that I can position as I want. At the end of the positioning, I get the left and top borders of each image (corresponding to the whole div).
I'm having trouble creating the image in code behind. I'm using the Bitmap.DrawImage Method. Here is my code :
oImgOut = New System.Drawing.Bitmap(600, 540)
oGraph = System.Drawing.Graphics.FromImage(oImgOut)
oGraph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
oGraph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
oGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality
oGraph.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality
oGraph.FillRectangle(Drawing.Brushes.White, 0, 0, 600, 540)
//image 1
oGraph.DrawImage(oImg1, CInt(left1), CInt(top1), CInt(width1), CInt(height1))
oImg1.Dispose()
//image2
oGraph.DrawImage(oImg2, CInt(left2), CInt(top2), CInt(width2), CInt(height2))
oImg2.Dispose()
oImgOut.Save(strDirectory)
oImgOut.Dispose()
This is what I have got so far :
I tried to give each image a width of 300px and height of 540px, but as you see the image on the right looks ugly :
I was wondering if there is a way to crop the image? I looked over most of the DrawImage prototypes but I couldn't find any that do the job I want. Surely you'll know better than me.
Can anyone help me?
I found a solution for cropping images with the DrawImage function
oGraph.DrawImage(oImg2, CInt(left2), CInt(top2), _
New Rectangle(0, 0, _
If(CInt(width2) > 600, 600, CInt(width2)), _
If(CInt(height2) > 270, 270, CInt(height2)) + CInt(top2) _
), GraphicsUnit.Pixel)
but i don't understand how it works, please guys i need your help :( .
Related
I've take some code and reduced it down to a few lines which still reproduce the error i am having. In this case, I am taking an image that is 448x298 in size and trying to overlay it on top of a white background that's 600x450.
So I'm expecting to get an image that's 600x450 with a white background and my original image laid on top of it starting in the upper right corner. And i expect my original image to remain it's original size. Instead the original image is going from 448x298 to approximately (give or take a pixel or two) 143x95
Here is the reduced code that's doing this:
System.Drawing.Image oImage = new Bitmap(600, 450);
Graphics oGraphic = Graphics.FromImage(oImage);
oGraphic.FillRectangle(Brushes.White, 0, 0, 600, 450);
oGraphic.DrawImage(image, new Point(0,0));
return (Bitmap)oImage;
You have to specify the target size. The overload you chose scales the image from the source dpi to the target dpi. As explained in another question, you should do this:
System.Drawing.Image oImage = new Bitmap(600, 450);
Graphics oGraphic = Graphics.FromImage(oImage);
oGraphic.FillRectangle(Brushes.White, 0, 0, 600, 450);
oGraphic.DrawImage(image, 0,0, image.Width, image.Height);
return (Bitmap)oImage;
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!
I am appending a mask to my mx:VideoDisplay element so that I can have rounded corners. The mask and even a dropshadow filter work great but I cannot get the stroke of the mask (using lineStyle) to show. Researched a ton and tried many fixes. At my wits end. Any help would be really appreciated.
private function applyMask():void {
myMask.graphics.clear();
myMask.graphics.lineStyle(2,0xFFFFFF);
myMask.graphics.beginFill(0xFFFFFF);
myMask.graphics.drawRoundRect(0, 0, 180, 156, 35);
myMask.x = 0;
myMask.y = 0;
videoMy.mask = myMask;
videoMy.filters = [new DropShadowFilter(3)]
}
later on I call the video element:
<mx:VideoDisplay id="videoMy" right="10" top="10" width="240" height="196"/>
You won't be able to do what you want with the mask directly-- it's a mask, so it is not drawn on, only used to mask other pixels.
What I would do is to create another child that is drawn on using the graphics calls you have above, but in a separate, normal display list sprite or some such added as an overlay of the masked VideoDisplay. This should accomplish what you're attempting to do.
i wrote the following code for drawing a rotate rectangle
var s:UIComponent = new UIComponent();
s.graphics.lineStyle(1, 0x0000FF);
s.graphics.drawRect(50, 50, 200, 200);
s.rotation = 30;
template.addChild(s);
where template is a canvas. Its rotate nicely but the problem is the position is not in right place. i.e. it is not in (50,50) after rotate. How can i solve this problem?
Thanks in advance.
What you're seeing is the default rotation around the origin in Flex (in your case the X,Y coordinates of 50,50) I am assuming that you want to rotate around the center (as I recently had to do). There is the jury rig way to do it, by adjusting the origin point based on rotation angle. Then there is the rotate effect:
import mx.effects.Rotate;
var s:UIComponent = new UIComponent();
var rotator:Rotate = new Rotate(s);
s.graphics.lineStyle(1, 0x0000FF);
s.graphics.drawRect(50, 50, 200, 200);
rotator.angleFrom = 0;
rotator.angleTo = 30;
rotator.originX = s.width/2;
rotator.originY = s.height/2;
template.addChild(s);
rotator.play();
Now I've noticed some problems with this that required me to set the width and height of the rotated object again after the play() method, but other than that I get the ideal rotation situation.
Another downside to this is that it's an effect, which means it visually rotates the object. I will post back when I correct that, if you don't want to see the object rotate.
The Answer is duration
just by adding rotator.duration = 1 before play it happens so quick the user won't see it. 1 being 1 millisecond. I tried 0, but that resulted in no rotation occurring. Obviously if you want to see the effect in action you can increase that length of time by using any value in milliseconds.
I need to do some emulation of some old DOS or mainframe terminals in Flex. Something like the image below for example.
The different coloured text is easy enough, but the ability to do different background colours, such as the yellow background is beyond the capabilities of the standard Flash text.
I may also need to be able to enter text at certain places and scroll text up the "terminal". Any idea how I'd attack this? Or better still, any existing code/components for this sort of thing?
Use TextField.getCharBoundaries to get a rectangle of the first and last characters in the areas where you want a background. From these rectangles you can construct a rectangle that spans the whole area. Use this to draw the background in a Shape placed behind the text field, or in the parent of the text field.
Update you asked for an example, here is how to get a rectangle from a range of characters:
var firstCharBounds : Rectangle = textField.getCharBoundaries(firstCharIndex);
var lastCharBounds : Rectangle = textField.getCharBoundaries(lastCharIndex);
var rangeBounds : Rectangle = new Rectangle();
rangeBounds.topLeft = firstCharBounds.topLeft;
rangeBounds.bottomRight = lastCharBounds.bottomRight;
If you want to find a rectangle for a whole line you can do this instead:
var charBounds : Rectangle = textField.getCharBoundaries(textField.getLineOffset(lineNumber));
var lineBounds : Rectangle = new Rectangle(0, charBounds.y, textField.width, firstCharBounds.height);
When you have the bounds of the text range you want to paint a background for, you can do this in the updateDisplayList method of the parent of the text field (assuming the text field is positioned at [0, 0] and has white text, and that textRangesWithYellowBackground is an array of rectangles that represent the text ranges that should have yellow backgrounds):
graphics.clear();
// this draws the black background
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, textField.width, textField.height);
graphics.endFill();
// this draws yellow text backgrounds
for each ( var r : Rectangle in textRangesWithYellowBackground )
graphics.beginFill(0xFFFF00);
graphics.drawRect(r.x, r.y, r.width, r.height);
graphics.endFill();
}
The font is fixed width and height, so making a background bitmap dynamically isn't difficult, and is probably the quickest and easiest solution. In fact, if you size it correctly there will only be one stretched pixel per character.
Color the pixel (or pixels) according to the background of the character.
-Adam