( Index )
Month

 

Brief Information about the April 2015 CSIG Meeting

CROP.cs - A Graphics Utility to Crop a Photograph ......    by B. Arnold

LATE BREAKING NEWS:   http://www.techsupportalert.com/content/microsoft-visual-studio-now-free-non-commercial-use.htm

(General Csig Info)    This month's application is a Microsoft C-sharp program that deals with graphics. Although programmed in C# it is easily converted to C++ since it uses the DOT NET libraries. See below for further information.


Sample               Sample

Sample of Crop Photo App

The program application for this month is an intermediate level DOT NET C# utility that will process a photo file. The major sections of the code include

Global variables
Drag and Drop Jpg file input
PrintScreen (Clipboard) input
Calculations and Math
Graphical Microsoft Net Framework functions
Graphical Mouse Selection paradigm
Memory handling
Jpg file output functions

Here's the full operating manual: Drop a Jpg file onto the app. Rubberband a box around the section of the photo that interests you. Let go of the mouse button. The photo will be cropped and then zoomed to the window. Click the Save File button to save it permanently. End of Manual.

I usually mention that it's an exciting time for programming using the various C languages. On a more targeted level, it's also an exciting time for this CROP Program Project. The basic operation of the program has been verified and now we can add some features to make it more friendly and more valuable. (And, of course, we can correct any bugs that were introduced in the original code.) Here's what was done for this month (Version 1.20):

 (Compare the above picture with the one from last month.)
Bug Correction - Set Image to null after Dispose().
Bug Correction - Modify pictureBox1_MouseUp() to ignore small selections like 16x16 pixels.
New button and code added to UNDO  IMAGE change when zooming allowing INFINITE  UNDO.
Modify zoom rectangle (Paint) to show red fill in.
Removed Green and Yellow coloring. Background is now dark gray.
Selection of Crop now uses Intersecting Rectangles algorithm.
WindowsDefaultBounds now used for start size and position.
ColorizeButtons_Tick() routine added to set green buttons.
 

Welcome to the CSIG, a Special Interest Group of the ACGNJ. This is an exciting time for the C Language programming since Microsoft now has 4 different language compilers: C++, C++ Express, C-Sharp, and C-Sharp Express. These are all capable of creating Windows (tm) programs. (Some are FREE!)

This is a CLI DOT NET program is coded using C-sharp (C#) and is very similar to C++.  It also still uses the same DOT NET libraries.

The program uses a number of DOT NET Library functions including the following:
DragDrop Windows Forms CLASSES Buttons
DialogResult GetDataPresent Image Close
Show Dispose C# Format
String Button_Click  DOT NET Rectangle
Height Width MouseDown DragEnter
GetProperty PropertyInfo GetValue Graphics
Drawing2d SaveFileDialog MessageBox Visible
IntersectsWith Rectangle Intersect Stack
Stack.Push Stack.Pop Stack.Count Timer

There are a number of ways to refer to Microsoft's latest compilers and code. Here's what Wikipedia says: The Common Language Infrastructure (CLI) is an open specification developed by Microsoft that describes the executable code and runtime environment that form the core of the Microsoft .NET Framework. The specification defines an environment that allows multiple high-level languages to be used on different computer platforms without being rewritten for specific architectures.

Microsoft .Net Framework 4.5
C++ 9.0, etc.
.Net 4.5, etc.
CLI
Common Language Infrastructure

Sample Code

namespace Crop
    {
    public partial class Form1 : Form
        {
        public Form1()
            {
            InitializeComponent();
            }

        ////////////////////////////////////////////////////////////////////////////////////////////
        //
        //   Suffix _SC = Screen Coordinates
        //   Suffix _CC = Client Coordinates
        //
        Rectangle cropRectangle_CC;
        Point startPoint_CC;
        bool isDrag = false;
        bool fileChanged = false;

        ////////////////////////////////////////////////////////////////////////////////////////////
        //
        // Drag and Drop step 3 of 3.  The users releases the mouse to drop the image.
        //
        private void Form1_DragDrop(object sender, DragEventArgs e)
            {
            if (fileChanged)   // Prompt user.
                {
                //  Title = Bad Result     //  Default Button = No     //  Message = Caution
                System.Windows.Forms.DialogResult Result;
                Result = MessageBox.Show(this, "Cropped Image will be Disregarded! Continue?", "Drop New File",
                        MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                if (Result != System.Windows.Forms.DialogResult.Yes) return;
                }
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                {
                if (this.pictureBox1.Image != null)
                    this.pictureBox1.Image.Dispose();
                // Get a list of filenames but use only the 1st name.
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                if (files.Length > 0)
                    {
                    files[0] = files[0].ToLower();
                    if (files[0].EndsWith(".jpg"))
                        {
                        try
                            {
                            this.pictureBox1.Image = Image.FromFile(files[0]);
                            imageData.Text = String.Format("{0} x {1}", pictureBox1.Image.Width, pictureBox1.Image.Height);
                            fileChanged = false;
                            this.pictureBox1.Visible = true;
                            }
                        catch (Exception ex)
                            {
                            MessageBox.Show(ex.Message, "E R R O R"); return;
                            }
                        }
                    }
                }
            this.Activate();
            }

        //  Drag and Drop step 2 of 3.  The users drags the image into the program's GUI.
        //    Note: Step 1 is Form1 AllowDrop property has been set to true.
        //
        private void Form1_DragEnter(object sender, DragEventArgs e)
            {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
            }

        ////////////////////////////////////////////////////////////////////////////////////////////
        //
        //  Adjust for backwards rectangles.
        //
        private System.Drawing.Rectangle Normalize(Rectangle arg)
            {
            Rectangle foo = arg;
            if (foo.Width < 0)            // Normalize
                {
                foo.X += foo.Width; foo.Width = -foo.Width;
                }
            if (foo.Height < 0)         // Normalize
                {
                foo.Y += foo.Height; foo.Height = -foo.Height;
                }
            return foo;
            }


        ////////////////////////////////////////////////////////////////////////////////////////////
        //  PAINT THE RECTANGLE HERE.  PAINT THE RECTANGLE HERE.  PAINT THE RECTANGLE HERE.  
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
            {
            Graphics mFrame = e.Graphics;
            Pen mPen = new Pen(Color.Red, 6.0F);
            mPen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
            mFrame.DrawRectangle(mPen, cropRectangle_CC);
            mPen.Dispose();
            }

        ////////////////////////////////////////////////////////////////////////////////////////////
        //
        // File / Save has been clicked.  Save image to JPG file.
      //
      private void FileSave_Click(System.Object  sender, System.EventArgs  e)
         {
            if (pictureBox1.Image == null) return;
         System.IO.Stream myStream;
         SaveFileDialog saveFileDialog1 = new SaveFileDialog();
         saveFileDialog1.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*";
         saveFileDialog1.FilterIndex = 1;
         saveFileDialog1.RestoreDirectory = true;
         if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
            if ((myStream = saveFileDialog1.OpenFile()) != null)
               {
               pictureBox1.Image.Save(myStream, System.Drawing.Imaging.ImageFormat.Jpeg);
               myStream.Close();
                    fileChanged = false;
               }
            }
         }

Sample Code from Past Meetings

// FORM1.H      ACGNJ CSIG MEETING December 16, 2014 - WRITTEN BY BRUCE ARNOLD

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace Circles
    {

    public partial class Form1 : Form
        {
        const int FIFTY_CIRCLES = 50;
        const int DIAMETER = 250;
        const int TIMER_INTERVAL = 2000;    // milliseconds
        static ArrayList CircleArray = new ArrayList();

        public Form1()
            {
            InitializeComponent();
            this.DoubleBuffered = true;   // for better, smoother screen updates.
            this.WindowState = FormWindowState.Maximized;
            }
        ~Form1()
            {
            CircleArray.RemoveRange(0, CircleArray.Count);      // Clear memory.
            }


        // Here is where we create a brand new circle. The default constructor of "Circle" 
        // then calls the constructors of its "base" classes. Remember: "It's turtles all
        // the way down!" A loop creates 50 circles at a time.
        private void timer1_Tick(object sender, EventArgs e)
            {
            this.timer1.Interval = TIMER_INTERVAL;
            int windowWidth = this.ClientRectangle.Width;
            int windowHeight = this.ClientRectangle.Height;
            Random autoRand = new Random();
            int xorg, yorg;
            CircleArray.RemoveRange(0, CircleArray.Count);      // Clear memory.
            for (int loop = 0; loop < FIFTY_CIRCLES; ++loop)
                {
                Circle cc = new Circle();      // Create new circle.
                cc.Diameter(windowHeight / 4);
                int bkg = autoRand.Next(9);
                switch (bkg)
                    {
                    case 0: cc.BkGround(Brushes.SandyBrown); break;       // Random
                    case 1: cc.BkGround(Brushes.Red); break;           // color
                    case 2: cc.BkGround(Brushes.Orange); break;           // pick.
                    case 3: cc.BkGround(Brushes.Yellow); break;
                    case 4: cc.BkGround(Brushes.Green); break;
                    case 5: cc.BkGround(Brushes.Blue); break;
                    case 6: cc.BkGround(Brushes.Violet); break;
                    case 7: cc.BkGround(Brushes.LightGray); break;
                    case 8: cc.BkGround(Brushes.White); break;
                    }
                xorg = windowWidth - cc.cx + 200; if (xorg < 0) xorg = 0;     // Calculate limits.
                yorg = windowHeight - cc.cy + 200; if (yorg < 0) yorg = 0;

                xorg = autoRand.Next(xorg) - 100;     // Randomize values
                yorg = autoRand.Next(yorg) - 100;

                cc.Position(xorg, yorg);
                CircleArray.Add(cc);
                }
            Invalidate();
            }

        private void Form1_Paint(object sender, PaintEventArgs e)
            {
            foreach (Circle obj in CircleArray)
                {
                obj.Paint(e);
                }
            }

SOURCE CODE

Source Code Files

For help, email me at b a r n o l d @ i e e e . o r g
Back to C++ Main Page