incubator-callback-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Herm Wong (JIRA)" <j...@apache.org>
Subject [jira] [Resolved] (CB-570) WP7 takePicture DATA_URL Not Resizing Image
Date Thu, 21 Jun 2012 17:05:42 GMT

     [ https://issues.apache.org/jira/browse/CB-570?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Herm Wong resolved CB-570.
--------------------------

    Resolution: Fixed

https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-wp7.git;a=commit;h=c7a075e3b1b07f6931f030219272c6fc9844528d
                
> 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.9.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

        

Mime
View raw message