[ 
https://issues.apache.org/jira/browse/CB-570?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13276336#comment-13276336
 ] 

Simon MacDonald commented on CB-570:
------------------------------------

I'm pretty sure that Android does not support width/height on DATA_URL's. We 
should check this from cross platform inconsistencies.
                
> WP7 takePicture DATA_URL Not Resizing Image
> -------------------------------------------
>
>                 Key: CB-570
>                 URL: https://issues.apache.org/jira/browse/CB-570
>             Project: Apache Cordova
>          Issue Type: Bug
>          Components: WP7
>    Affects Versions: 1.6.1
>         Environment: Cordova 1.6.1, VS.NET 2010, WP7.5 emulators
>            Reporter: Alan Neveu
>            Assignee: Herm Wong
>             Fix For: 1.8.0
>
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> The code in Camera.cs that should resize the picture file before returning 
> the base64 encoded string has not been completed as of 1.6.1. The result is 
> that the full 5 megapixel or 8 megapixel file gets base64 encoded and 
> returned. Das ist vady badst yah! I wrote some code that uses a solid 
> approach to resizing the image and I'll share it here so that Jesse can 
> restructure it a bit using forms that match the rest of the project.  This 
> code works great and it was used in basically this same format on another 
> Silverlight app that has been in the WP7 Marketplace for over a year with 
> 8,000 installs and no errors with this code.  Enjoy!
> /*  
>       Licensed under the Apache License, Version 2.0 (the "License");
>       you may not use this file except in compliance with the License.
>       You may obtain a copy of the License at
>       
>       http://www.apache.org/licenses/LICENSE-2.0
>       
>       Unless required by applicable law or agreed to in writing, software
>       distributed under the License is distributed on an "AS IS" BASIS,
>       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>       See the License for the specific language governing permissions and
>       limitations under the License.
> */
> using System;
> using System.Net;
> using System.Windows;
> using System.Windows.Controls;
> using System.Windows.Documents;
> using System.Windows.Ink;
> using System.Windows.Input;
> using System.Windows.Media;
> using System.Windows.Media.Animation;
> using System.Collections.Generic;
> using Microsoft.Phone.Tasks;
> using System.Runtime.Serialization;
> using System.IO;
> using System.IO.IsolatedStorage;
> using System.Windows.Media.Imaging;
> using Microsoft.Phone;
> namespace WP7CordovaClassLib.Cordova.Commands
> {
>     public class Camera : BaseCommand
>     {
>         /// <summary>
>         /// Return base64 encoded string
>         /// </summary>
>         private const int DATA_URL = 0;
>         /// <summary>
>         /// Return file uri
>         /// </summary>
>         private const int FILE_URI = 1;
>         /// <summary>
>         /// Choose image from picture library
>         /// </summary>
>         private const int PHOTOLIBRARY = 0;
>         /// <summary>
>         /// Take picture from camera
>         /// </summary>
>         private const int CAMERA = 1;
>         /// <summary>
>         /// Choose image from picture library
>         /// </summary>
>         private const int SAVEDPHOTOALBUM = 2;
>         /// <summary>
>         /// Take a picture of type JPEG
>         /// </summary>
>         private const int JPEG = 0;
>         /// <summary>
>         /// Take a picture of type PNG
>         /// </summary>
>         private const int PNG = 1;
>         /// <summary>
>         /// Folder to store captured images
>         /// </summary>
>         private const string isoFolder = "CapturedImagesCache";
>         /// <summary>
>         /// Represents captureImage action options.
>         /// </summary>
>         [DataContract]
>         public class CameraOptions
>         {
>             /// <summary>
>             /// Source to getPicture from.
>             /// </summary>
>             [DataMember(IsRequired = false, Name = "sourceType")]
>             public int PictureSourceType { get; set; }
>             /// <summary>
>             /// Format of image that returned from getPicture.
>             /// </summary>
>             [DataMember(IsRequired = false, Name = "destinationType")]
>             public int DestinationType { get; set; }
>             /// <summary>
>             /// Quality of saved image
>             /// </summary>
>             [DataMember(IsRequired = false, Name = "quality")]
>             public int Quality { get; set; }
>             /// <summary>
>             /// Height in pixels to scale image
>             /// </summary>
>             [DataMember(IsRequired = false, Name = "targetHeight")]
>             public int TargetHeight { get; set; }
>             /// <summary>
>             /// Width in pixels to scale image
>             /// </summary>
>             [DataMember(IsRequired = false, Name = "targetWidth")]
>             public int TargetWidth { get; set; }
>             /// <summary>
>             /// Creates options object with default parameters
>             /// </summary>
>             public CameraOptions()
>             {
>                 this.SetDefaultValues(new StreamingContext());
>             }
>             /// <summary>
>             /// Initializes default values for class fields.
>             /// Implemented in separate method because default constructor is 
> not invoked during deserialization.
>             /// </summary>
>             /// <param name="context"></param>
>             [OnDeserializing()]
>             public void SetDefaultValues(StreamingContext context)
>             {
>                 PictureSourceType = CAMERA;
>                 DestinationType = FILE_URI;
>                 Quality = 80;
>                 TargetHeight = -1;
>                 TargetWidth = -1;
>             }
>         }
>         /// <summary>
>         /// Used to open photo library
>         /// </summary>
>         PhotoChooserTask photoChooserTask;
>         /// <summary>
>         /// Used to open camera application
>         /// </summary>
>         CameraCaptureTask cameraTask;
>         /// <summary>
>         /// Camera options
>         /// </summary>
>         CameraOptions cameraOptions;
>         public void takePicture(string options)
>         {
>             try
>             {
>                 this.cameraOptions = String.IsNullOrEmpty(options) ?
>                         new CameraOptions() : 
> JSON.JsonHelper.Deserialize<CameraOptions>(options);
>             }
>             catch (Exception ex)
>             {
>                 this.DispatchCommandResult(new 
> PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
>                 return;
>             }
>             //TODO Check if all the options are acceptable
>             if (cameraOptions.PictureSourceType == CAMERA)
>             {
>                 cameraTask = new CameraCaptureTask();
>                 cameraTask.Completed += onTaskCompleted;
>                 cameraTask.Show();
>             }
>             else
>             {
>                 if ((cameraOptions.PictureSourceType == PHOTOLIBRARY) || 
> (cameraOptions.PictureSourceType == SAVEDPHOTOALBUM))
>                 {
>                     photoChooserTask = new PhotoChooserTask();
>                     photoChooserTask.Completed += onTaskCompleted;
>                     photoChooserTask.Show();
>                 }
>                 else
>                 {
>                     DispatchCommandResult(new 
> PluginResult(PluginResult.Status.NO_RESULT));
>                 }
>             }
>         }
>         public void onTaskCompleted(object sender, PhotoResult e)
>         {
>             if (e.Error != null)
>             {
>                 DispatchCommandResult(new 
> PluginResult(PluginResult.Status.ERROR));
>                 return;
>             }
>             switch (e.TaskResult)
>             {
>                 case TaskResult.OK:
>                     try
>                     {
>                         string imagePathOrContent = string.Empty;
>                         if (cameraOptions.DestinationType == FILE_URI)
>                         {
>                             WriteableBitmap image = 
> PictureDecoder.DecodeJpeg(e.ChosenPhoto);
>                             imagePathOrContent = 
> this.SaveImageToLocalStorage(image, Path.GetFileName(e.OriginalFileName));
>                         }
>                         else if (cameraOptions.DestinationType == DATA_URL)
>                         {
>                             Byte[] bytFile;
>                             Byte[] bytFileResized;
>                             int intResult = 0;
>                             long lngLength;
>                             BitmapImage objBitmap;
>                             System.IO.MemoryStream objBitmapStream;
>                             System.IO.MemoryStream objBitmapStreamResized = 
> new System.IO.MemoryStream();
>                             WriteableBitmap objWB;
>                             //Get the JPEG bytes from the source chosen 
> photo, probably 5 megapixel!
>                             lngLength = e.ChosenPhoto.Length;
>                             bytFile = new Byte[lngLength];
>                             intResult = e.ChosenPhoto.Read(bytFile, 0, 
> (int)lngLength);
>                             //Convert the bytes to a WriteableBitmap
>                             objBitmap = new BitmapImage();
>                             objBitmapStream = new 
> System.IO.MemoryStream(bytFile);
>                             objBitmap.SetSource(objBitmapStream);
>                             objWB = new WriteableBitmap(objBitmap);
>                             //Resize the image
>                             
> System.Windows.Media.Imaging.Extensions.SaveJpeg(objWB, 
> objBitmapStreamResized, cameraOptions.TargetWidth, 
> cameraOptions.TargetHeight, 0, cameraOptions.Quality);
>                             //Convert the resized stream to a byte array.
>                             lngLength = objBitmapStreamResized.Length;
>                             bytFileResized = new Byte[lngLength]; //-1
>                             objBitmapStreamResized.Position = 0; //for some 
> reason we have to set Position to zero, but we don't have to earlier when we 
> get the bytes from the chosen photo...
>                             intResult = 
> objBitmapStreamResized.Read(bytFileResized, 0, (int)lngLength);
>                             //Convert the byte array to base64 string.
>                             imagePathOrContent = 
> Convert.ToBase64String(bytFileResized);
>                         }
>                         else
>                         {
>                             DispatchCommandResult(new 
> PluginResult(PluginResult.Status.ERROR, "Incorrect option: destinationType"));
>                             return;
>                         }
>                         DispatchCommandResult(new 
> PluginResult(PluginResult.Status.OK, imagePathOrContent));
>                     }
>                     catch (Exception)
>                     {
>                         DispatchCommandResult(new 
> PluginResult(PluginResult.Status.ERROR, "Error retrieving image."));
>                     }
>                     break;
>                 case TaskResult.Cancel:
>                     DispatchCommandResult(new 
> PluginResult(PluginResult.Status.ERROR, "Selection cancelled."));
>                     break;
>                 default:
>                     DispatchCommandResult(new 
> PluginResult(PluginResult.Status.ERROR, "Selection did not complete!"));
>                     break;
>             }
>         }
>         /// <summary>
>         /// Returns image content in a form of base64 string
>         /// </summary>
>         /// <param name="stream">Image stream</param>
>         /// <returns>Base64 representation of the image</returns>
>         private string GetImageContent(Stream stream)
>         {
>             int streamLength = (int)stream.Length;
>             byte[] fileData = new byte[streamLength + 1];
>             stream.Read(fileData, 0, streamLength);
>             stream.Close();
>             return Convert.ToBase64String(fileData);
>         }
>         /// <summary>
>         /// Saves captured image in isolated storage
>         /// </summary>
>         /// <param name="imageFileName">image file name</param>
>         /// <returns>Image path</returns>
>         private string SaveImageToLocalStorage(WriteableBitmap image, string 
> imageFileName)
>         {
>             if (image == null)
>             {
>                 throw new ArgumentNullException("imageBytes");
>             }
>             try
>             {
>                 var isoFile = 
> IsolatedStorageFile.GetUserStoreForApplication();
>                 if (!isoFile.DirectoryExists(isoFolder))
>                 {
>                     isoFile.CreateDirectory(isoFolder);
>                 }
>                 string filePath = System.IO.Path.Combine("/" + isoFolder + 
> "/", imageFileName);
>                 using (var stream = isoFile.CreateFile(filePath))
>                 {
>                     // resize image if Height and Width defined via options 
>                     if (cameraOptions.TargetHeight > 0 && 
> cameraOptions.TargetWidth > 0)
>                     {
>                         image.SaveJpeg(stream, cameraOptions.TargetWidth, 
> cameraOptions.TargetHeight, 0, cameraOptions.Quality);
>                     }
>                     else
>                     {
>                         image.SaveJpeg(stream, image.PixelWidth, 
> image.PixelHeight, 0, cameraOptions.Quality);
>                     }
>                 }
>                 return new Uri(filePath, UriKind.Relative).ToString();
>             }
>             catch (Exception)
>             {
>                 //TODO: log or do something else
>                 throw;
>             }
>         }
>     }
> }

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to