|
|
/**************************************************************************
* * Copyright (c) 2000 Microsoft Corporation * * Program Name: * * Crop * * This is a sample application that loads an image and shrinks it down * to 128x96 using the HighQualityBicubic resampling filter. It crops the * image to preserve the aspect ratio. * * This app is particularly useful for creating a set of thumbnail images * from a directory of pictures for use in a web page index. * * This example will produce a directory (idx) containing 128x96 jpeg * thumbnails for all the jpeg files in the pictures directory: * cd pictures * md idx * for %i in (*.jpg) do crop %~nxi idx\%~nxi * * Usage (command line): * * Crop input_filename output_filename * * Created: * * 06/25/2000 asecchia * Created it. * 03/16/2001 minliu * add -w, -h, -? -s, -q switches support. New ValidateArguments() and * USAGE() function * 05/10/2001 gillesk * added -a to crop the excess of the file and keep the w and h * **************************************************************************/
#include <stdio.h>
#include <windows.h>
#include <objbase.h>
#include <gdiplus.h>
#include "../gpinit.inc"
INT AsciiToUnicodeStr( const CHAR* ansiStr, WCHAR* unicodeStr, INT unicodeSize ) { return( MultiByteToWideChar( CP_ACP, 0, ansiStr, -1, unicodeStr, unicodeSize ) > 0 ); }
int round(float f) { return (int) (f+0.5); }
const int k_xsize = 128; // default thumbnail size
const int k_ysize = 96;
int g_xsize = k_xsize; int g_ysize = k_ysize; float g_scale = 1; int g_quality = 5; int g_compression = 70; BOOL g_HasSetScaleFactor = FALSE; BOOL g_KeepAspectRation = FALSE; BOOL g_GotFileNames = FALSE; WCHAR filename[1024]; WCHAR outfilename[1024];
#define Fail() goto cleanup
void USAGE() { printf("******************************************************\n"); printf("Usage: crop [-?] [-w width] [-h height] [-s factor] srcImg dstImg\n"); printf("-w----Specify the thumbnail image width. Default is 128\n"); printf("-h----Specify the thumbnail image height. Default is 96\n"); printf("-s----Specify the scale factor\n"); printf("-q----Specify the render quality [1-5] where 5(default) is the best\n"); printf("-a----Keep the apsect ratio and crop the excess of the image\n"); printf("-c----Set the compression factor [0-100] where 100 is least compressed\n"); printf("-?----Print this usage message\n"); printf("Note: If scale factor is specified, then width and height you specified are ignored\n\n\n"); printf("Sample usage:\n"); printf(" crop -w 200 -h 300 foo.jpg thumb.jpg\n"); printf(" crop -s 0.5 foo.jpg thumb.jpg\n"); printf(" crop foo.jpg thumb.jpg\n"); }// USAGE()
void ValidateArguments(int argc, char* argv[]) { argc--; argv++; // Filter out program name
while ( argc > 0 ) { if ( strcmp(*argv, "-w") == 0 ) { argc--; argv++;
if ( argc == 0 ) { // Not enough parameters
USAGE(); exit(1); } g_xsize = atoi(*argv++); argc--; } else if ( strcmp(*argv, "-h") == 0 ) { argc--; argv++;
if ( argc == 0 ) { // Not enough parameters
USAGE(); exit(1); } g_ysize = atoi(*argv++); argc--; } else if ( strcmp(*argv, "-s") == 0 ) { argc--; argv++;
if ( argc == 0 ) { // Not enough parameters
USAGE(); exit(1); } g_scale = (float)atof(*argv++); g_HasSetScaleFactor = TRUE; argc--; } else if ( strcmp(*argv, "-q") == 0 ) { argc--; argv++;
if ( argc == 0 ) { // Not enough parameters
USAGE(); exit(1); } g_quality = atoi(*argv++); argc--; } else if ( strcmp(*argv, "-a") == 0 ) { g_KeepAspectRation = TRUE; argc--; argv++; } else if ( strcmp(*argv, "-c") == 0 ) { argc--; argv++;
if ( argc == 0 ) { // Not enough parameters
USAGE(); exit(1); } g_compression = atoi(*argv++); argc--; } else if ( strcmp(*argv, "-?") == 0 ) { USAGE(); exit(1); } else { // source and dest image name
if ( argc < 2 ) { // Not enough parameters
USAGE(); exit(1); } AsciiToUnicodeStr(*argv++, filename, 1024); argc--; AsciiToUnicodeStr(*argv++, outfilename, 1024); argc--; g_GotFileNames = TRUE; } }// while ( argc > 0 )
if ( g_GotFileNames == FALSE ) { // No input file name yet, bail out
USAGE(); exit(1); } }// ValidateArguments()
void _cdecl main(int argc, char **argv ) { if (!gGdiplusInitHelper.IsValid()) { printf("error - GDI+ initialization failed\n"); return; }
// Parse input parameters
ValidateArguments(argc, argv);
using namespace Gdiplus;
Status status = Ok;
ImageCodecInfo* codecs = NULL; UINT count; UINT cbCodecs;
// Open the source image
Bitmap* dstBmp = NULL; Graphics *gdst = NULL; RectF srcRect;
Bitmap *srcBmp = new Bitmap(filename, TRUE); if ( (srcBmp == NULL) || (srcBmp->GetLastStatus() != Ok) ) { printf("Error opening image %s\n", filename); Fail(); }
// Ask the source image for it's size.
int width = srcBmp->GetWidth(); int height = srcBmp->GetHeight();
srcRect = RectF(0.0f, 0.0f, (REAL)width, (REAL)height);
printf("Input image is %d x %d\n", width, height);
// Compute the optimal scale factor without changing the aspect ratio
if ( g_HasSetScaleFactor == FALSE ) { float scalex = (float)g_xsize / width; float scaley = (float)g_ysize / height; g_scale = min(scalex, scaley); }
// If we want to keep the aspect ratio, then we need to crop the srcBmp
UINT dstWidth = (UINT)(width * g_scale + 0.5); UINT dstHeight = (UINT)(height * g_scale + 0.5);
if ( g_KeepAspectRation == TRUE ) { float scalex = (float)g_xsize / width; float scaley = (float)g_ysize / height; g_scale = max(scalex, scaley); srcRect = RectF((REAL)width/2.0f, (REAL)height/2.0f, 0.0f, 0.0f); srcRect.Inflate(g_xsize/g_scale/2.0f, g_ysize/g_scale/2.0f); dstWidth = g_xsize; dstHeight = g_ysize; }
// Create a destination image to draw onto
dstBmp = new Bitmap(dstWidth, dstHeight, PixelFormat32bppPARGB); if ( (dstBmp == NULL) || (dstBmp->GetLastStatus() != Ok) ) { printf("Error create temp Bitmap with size %d x %x\n", dstWidth, dstHeight); Fail(); } gdst = new Graphics(dstBmp); if ( (gdst == NULL) || (gdst->GetLastStatus() != Ok) ) { printf("Error create graphics\n"); Fail(); } // Make up a dest rect that we need image to draw to
{ RectF dstRect(0.0f, 0.0f, (REAL)dstWidth, (REAL)dstHeight);
// Set the resampling quality to the bicubic filter
switch ( g_quality ) { case 1: gdst->SetInterpolationMode(InterpolationModeBilinear); break;
case 2: gdst->SetInterpolationMode(InterpolationModeNearestNeighbor); break;
case 3: gdst->SetInterpolationMode(InterpolationModeBicubic); break; case 4: gdst->SetInterpolationMode(InterpolationModeHighQualityBilinear); break;
case 5: default: gdst->SetInterpolationMode(InterpolationModeHighQualityBicubic); break; }
// Set the compositing quality to copy source pixels rather than
// alpha blending. This will preserve any alpha in the source image.
gdst->SetCompositingMode(CompositingModeSourceCopy);
// Draw the source image onto the destination with the correct scale
// and quality settings.
status = gdst->DrawImage(srcBmp, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, UnitPixel );
if (status != Ok) { printf("Error drawing the image\n"); Fail(); } }
// Now start finding a codec to output the image.
cbCodecs = 0; GetImageEncodersSize(&count, &cbCodecs);
// Allocate space for the codec list
codecs = static_cast<ImageCodecInfo *>(malloc (cbCodecs));
if (codecs == NULL) { printf("error: failed to allocate memory for codecs\n"); Fail(); }
// Get the list of encoders
status = GetImageEncoders(count, cbCodecs, codecs);
if (status != Ok) { printf("Error: GetImageEncoders returned %d\n", status); Fail(); }
// Search the codec list for the JPEG codec.
// Use the Mime Type field to specify the correct codec.
for(UINT i=0; i<count; i++) { if(wcscmp(codecs[i].MimeType, L"image/jpeg")==0) {break;} }
if(i>=count) { fprintf(stderr, "failed to find the codec\n"); Fail(); }
// Output the image to disk.
CLSID tempClsID; tempClsID = codecs[i].Clsid; EncoderParameters params; params.Count = 1;
params.Parameter[0].Guid = EncoderCompression; params.Parameter[0].NumberOfValues = 1; params.Parameter[0].Type = EncoderParameterValueTypeLong; params.Parameter[0].Value = (void*) &g_compression;
status = dstBmp->Save( outfilename, &tempClsID, ¶ms );
if (status != Ok) { fprintf(stderr, "SaveImage--Save() failed\n"); Fail(); }
printf("Create new image at %d x %d\n", dstWidth, dstHeight); // We're golden - everything worked.
printf("Done\n");
// Clean up the objects we used.
cleanup:
free(codecs); delete gdst; delete dstBmp; delete srcBmp; }
|