質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

2045閲覧

SC-01K(android7.1.1)の標準カメラアプリで取得した画像をPHPのimagecreatefromjpegで処理した際のバグ

ayako0802

総合スコア11

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2017/12/22 10:54

編集2017/12/25 13:48

初めての質問です。何卒よろしくお願いします。

状況

SC-01K
android7.1.1にて
webからカメラを起動した際
標準カメラを選択し撮影した画像データをアップロードし、
php側で保存しようとすると、正常に保存されません。
imagecreatefromjpegがうまく処理できていないようです。

同一機種における googleのカメラアプリや
SO-01J(android7.0)
や、iPhoneSE(iOS 10.3.3)
では正常に処理されております。

試したこと

  • getimagesize
  • exif_imagetype
  • mime_content_type

で、ファイルタイプを調査しましたが、
いずれもjpegと判定されています。

photoupload.js

$.ajax({ url : './photoupload.php', type : 'POST', data : formdata, cache : false, contentType : false, processData : false, dataType : 'text' }) .done(function(data, textStatus, jqXHR){ //成功処理 }) .fail(function(jqXHR, textStatus, errorThrown){ //失敗処理 });

photoupload.php

$file_tmp = $_FILES['take-picture-input']['tmp_name']; //保存用ファイル名を設定 $timestamp = date('YmdHis', time()); $file_name = $timestamp.'.jpg'; $tmp_name = './tmp/upload/'.$file_name; $file_tmp = imagecreatefromjpeg($file_tmp); imagejpeg($file_tmp ,$tmp_name); echo $tmp_name;

12月25日11:30追記

asahina1979様 Tomak様
編集・追記のご依頼有難うございます。

正常に処理される機種ですと、

$file_tmp = imagecreatefromjpeg($file_tmp); imagejpeg($file_tmp ,$tmp_name);

の処理で、サーバ側の

$tmp_name = './tmp/upload/'.$file_name;

のディレクトリに画像が保存されるのですが、
該当の環境ですと、保存されません。

また、
正常に処理される実機でも
異常に処理される実機でも
正常に処理される実機でのみ

$file_tmp = imagecreatefromjpeg($file_tmp);

に対して

echo $file_tmp;

とすると、

Resource id #2

という値が帰ってきます。

該当部分のサーバログを確認しましたが、
特にエラーなど出していない様子です。
(IPや時間などは確認しているので、別のログを見ているわけではなさそうです)

12月25日18:05追記

補足になってしまいますが。
SC-01Kの「標準カメラアプリ」の「インカメラ」でのみ現状の現象が発生致します。
「アウトカメラ」では該当の現象は発生致しません。

12月25日22:50追記

以下テスト画像は全て同一機種SC-01Kで撮影しています。

動作する画像1
(SC-01Kのgoogleカメラアプリのアウトカメラで撮影)
4.2 MB
3024 × 4032

動作する画像2
(SC-01Kのgoogleカメラアプリのインカメラで撮影)
1.4 MB
2448 × 3264

動作する画像3
(SC-01K標準カメラアプリのアウトカメラで撮影)
2.7 MB
3024 × 4032

動作しない画像1
(SC-01K標準カメラアプリのインカメラで撮影)
1.5 MB
1592 × 3264

動作しない画像のみ、Macのプレビューのインスペクタを見ると
「JFIF」という項目があります。(他の画像に該当項目はありません。)
密度の単位: 2
JFIFバージョン: 1.0.1
幅の密度: 59
高さの密度: 59
と記述されています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/12/22 13:02

どううまくいかないのか?例外がでてるなら例外を
Tomak

2017/12/23 08:05

php側にエラー処理を入れてますでしょうか? エラー処理を入れていない場合は最低限「try~catch」でくくります。 また、phpのエラーログにもFatal ErrorやWarningが出るようにphp.iniの設定をしてみてはいかがでしょうか? 普通はphpを動かしているWebサーバーのログにログが表示されるはずです。
guest

回答1

0

ベストアンサー

下記のように表示されているということは、最低限アップロードファイルのオープンには成功しているという意味になります。imagecreatefromjpeg()の正常系の戻り値は画像リソースIDとなります。
http://php.net/manual/ja/function.imagecreatefromjpeg.php

php

1$file_tmp = imagecreatefromjpeg($file_tmp); 2//Resource id #2 3echo $file_tmp;

つまり、アップロード画像が保存されない場合は、読み込みは成功しているが、書き込みが不成功ということだと思います。

下記サンプルコードは画像の移動をmove_upload_file()で行うようにしてあります。
ソースコードを根本的に改善したわけではなく、単純に詳細なエラー処理を入れただけです。これでどこの処理で不具合が起きているのかはっきりすると思います。

※注意
たぶん今回は関係ないですが、PHP-5.4以下でセーフモードONでPHPが動いている場合、画像移動先ディレクトリのオーナー確認が行われます。echoでエラーメッセージ表示をおこなう場合は、echoした後もコードが実行されてしまうことに注意しなければなりません。

※PHP-5.3対応
PHP-5.3ではarray()[]とは書けないので編集しました。また、画像のMIMEタイプを判別してから移動するようにしました。PHP-5.3でもtry~catch()throw new Exception()などを使うことができます。

imagecreatefromjpeg()の続きがあるのかないのかわらないので、とりあえず画像のアップロードという意味では下記で完了です。

php

1try { 2 $file_tmp = $_FILES['take-picture-input']['tmp_name']; 3 4 //保存用ファイル名を設定 5 $timestamp = date('YmdHis', time()); 6 $file_name = $timestamp.'.jpg'; 7 $tmp_name = realpath('./tmp/upload/').$file_name; 8 9 if ($_FILES['take-picture-input']['error'] != UPLOAD_ERR_OK) { 10 throw new Exception('アップロードに失敗しました。'); 11 } 12 13 //画像タイプ判別 14 $mimeType = mime_content_type($file_tmp); 15 16 //JPEGのみ許可? 17 $accepted = array('jpg' => 'image/jpeg'); 18 //$accepted = array('gif' => 'image/gif', 'jpg' => 'image/jpeg', 'png' => 'image/png'); 19 20 if (false === array_search($mimeType, $accepted)) { 21 throw new Exception('ファイルは画像ではありません。タイプ:'. $mimeType); 22 } 23 24 //アップロード画像移動 25 if (! move_uploaded_file($file_tmp, $tmp_name)) { 26 throw new Exception('アップロード画像の移動に失敗しました。アップ先:'. $tmp_name .'アップ元:'. $file_tmp); 27 } 28 29 echo '画像のアップロードに成功しました。パス:'. $tmp_name; 30 31/* 32 //何したいのかよくわからないので、とりあえずコメントアウト 33 //サムネイル画像とか画像を加工したい? 34 35 //画像オープン 36 $file_tmp = @imagecreatefromjpeg($tmp_name); 37 38 //成功 39 if (false !== $file_tmp) { 40 //画像に対して何らかの処理? 41 echo $tmp_name; 42 } 43 //失敗 44 else { 45 //unlink($tmp_name); 46 throw new Exception('画像オープンに失敗しました。パス:'. $tmp_name); 47 } 48*/ 49} 50catch(Exception $e) { 51 echo $e->getMessage(); 52}

imagecreatefromjpeg()を使う場合で、「画像オープンに失敗しました」であれば、アップロード自体は完了しており、画像はサーバーに上がっているはずです。
画像を編集するならGD(imagecreatefromjpeg())などを使う必要ありますが、単純にアップロードするだけなら使う必要がありません。そして、PHPで画像をオープンする際はPHPのmemory_limit制限に依存します。

サーバーの搭載メモリを超えている大きなサイズの画像を処理したい場合は、外部コマンド「ImageMagic」などを使用します。

その他確認事項としては、サーバーにPOSTしたファイルをダウンロードして確認してみる方法もあります。つまり、JPEGだけど中身は別形式になってるとかいうケースもあります。

投稿2017/12/25 07:11

編集2017/12/25 11:44
Tomak

総合スコア1652

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ayako0802

2017/12/25 09:03

とても丁寧なコード、有難うございます! そのままでは動作しなかったため、末尾のように一部を書き直して動作させました。 (php5.3.3です。基本的なことを申しそびれておりすみません。) 結果、正常に保存される機種は指定したディレクトリに保存され 正常に保存されない環境は「画像オープンに失敗しました」となりました。 補足になってしまいますが。 SC-01Kの標準カメラアプリの「インカメラ」でのみ現状の現象が発生致します。 「アウトカメラ」では該当の現象は発生致しません。 ``` $file_tmp = $_FILES['take-picture-input']['tmp_name']; //保存用ファイル名を設定 $timestamp = date('YmdHis', time()); $file_name = $timestamp.'.jpg'; // $tmp_name = realpath('./tmp/upload/').$file_name; $tmp_name = './tmp/upload/'.$file_name; if ($_FILES['take-picture-input']['error'] != UPLOAD_ERR_OK) { echo ('アップロードに失敗しました。'); } //アップロード画像移動 if (! move_uploaded_file($file_tmp, $tmp_name)) { echo ('アップロード画像の移動に失敗しました。アップ先:'. $tmp_name .'アップ元:'. $file_tmp); } //画像タイプ判別 $mimeType = mime_content_type($tmp_name); //JPEGのみ許可? $accepted = array('jpg' => 'image/jpeg'); //$accepted = array('gif' => 'image/gif', 'jpg' => 'image/jpeg', 'png' => 'image/png'); if (false === array_search($mimeType, $accepted)) { //unlink($tmp_name); echo ('ファイルは画像ではありません。タイプ:'. $mimeType); } //画像オープン $file_tmp = @imagecreatefromjpeg($tmp_name); //成功 if (false !== $file_tmp) { //画像に対して何らかの処理? echo $tmp_name; } //失敗 else { //unlink($tmp_name); echo ('画像オープンに失敗しました'); } ```
ayako0802

2017/12/25 13:52

何度もコードを書いていただき、有難うございます!! テストの結果、 正常に処理される実機 異常に処理される実機 共に 「画像のアップロード」には成功しました。 しかし、 コメントアウト部分を外すと、 「画像オープンに失敗しました。」 となります。 当然 echo $file_tmp; しても画像リソースIDはかえってきません。 やはり、 $file_tmp = @imagecreatefromjpeg($tmp_name); の部分がうまくいっていないようです。 (12月25日11:30追記の情報が間違っておりました。) また、imagecreatefromjpegが動作する画像・動作しない画像についての 追記を質問本体で行なっているので、もしよければご確認頂ければ幸いです。 余談ですが、 imagecreatefromjpeg後は 写真の向きを訂正し、適切なサイズに縮小、他の画像との合成などの処理を行いますが、 その処理自体は書き終わっており、 現在ご質問している環境以外の不都合は発生していない状態です。
Tomak

2017/12/25 14:44 編集

方針を変えて、画像を file_get_contents() してから画像を読み込むという方法もありそうです。 ---- // GD画像リソースID $file_tmp = imagecreatefromstring(file_get_contents($tmp_name)); その他には下記のように、多分ヘッダーの問題なような気がするので、エラーを無視するようにするとうまくいくかもしれません。ただしJFIFのDPI情報の引き出しがうまくいってない可能性もあるのでその場合は上記の「file_get_contents()」を使うと良いと思います。 --- ini_set('gd.jpeg_ignore_warning', 1); $file_tmp = @imagecreatefromjpeg($tmp_name);
ayako0802

2017/12/26 05:10

Tomak様、わかりやすいご回答有難うございます。 $file_tmp = imagecreatefromstring(file_get_contents($file_tmp)); でも、また、 ini_set('gd.jpeg_ignore_warning', 1); $file_tmp = @imagecreatefromjpeg($file_tmp); でも、画像idが帰ってくることと、 サーバに保存できることが確認できました。 また、展開できた画像は JFIF 密度の単位: 0 JFIFバージョン: 1.0.1 幅の密度: 1 高さの密度: 1 となり、一旦解決の運びとなりました。 この度は本当に有難うございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問