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

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

ただいまの
回答率

90.86%

  • PHP

    18170questions

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

  • Android

    5978questions

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

  • Ajax

    980questions

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

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 176

ayako0802

score 3

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

 状況

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
と記述されています。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2017/12/22 22:02

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

    キャンセル

  • asahina1979

    2017/12/22 22:02

    エラーレポート:http://subtech.g.hatena.ne.jp/cho45/20100210/1265797885

    キャンセル

  • Tomak

    2017/12/23 17:05

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

    キャンセル

回答 1

checkベストアンサー

+1

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

$file_tmp = imagecreatefromjpeg($file_tmp);
//Resource id #2
echo $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()の続きがあるのかないのかわらないので、とりあえず画像のアップロードという意味では下記で完了です。

try {
    $file_tmp = $_FILES['take-picture-input']['tmp_name'];

    //保存用ファイル名を設定
    $timestamp = date('YmdHis', time());
    $file_name = $timestamp.'.jpg';
    $tmp_name  = realpath('./tmp/upload/').$file_name;

    if ($_FILES['take-picture-input']['error'] != UPLOAD_ERR_OK) {
        throw new Exception('アップロードに失敗しました。');
    }

    //画像タイプ判別
    $mimeType = mime_content_type($file_tmp);

    //JPEGのみ許可?
    $accepted = array('jpg' => 'image/jpeg');
    //$accepted = array('gif' => 'image/gif', 'jpg' => 'image/jpeg', 'png' => 'image/png');

    if (false === array_search($mimeType, $accepted)) {
        throw new Exception('ファイルは画像ではありません。タイプ:'. $mimeType);
    }

    //アップロード画像移動
    if (! move_uploaded_file($file_tmp, $tmp_name)) {
        throw new Exception('アップロード画像の移動に失敗しました。アップ先:'. $tmp_name .'アップ元:'. $file_tmp);
    }

    echo '画像のアップロードに成功しました。パス:'. $tmp_name;

/*
    //何したいのかよくわからないので、とりあえずコメントアウト
    //サムネイル画像とか画像を加工したい?

    //画像オープン
    $file_tmp = @imagecreatefromjpeg($tmp_name);

    //成功
    if (false !== $file_tmp) {
        //画像に対して何らかの処理?
        echo $tmp_name;
    }
    //失敗
    else {
        //unlink($tmp_name);
        throw new Exception('画像オープンに失敗しました。パス:'. $tmp_name);
    }
*/
}
catch(Exception $e) {
    echo $e->getMessage();
}

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/25 18: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 ('画像オープンに失敗しました');
    }
    ```

    キャンセル

  • 2017/12/25 22:52

    何度もコードを書いていただき、有難うございます!!

    テストの結果、
    正常に処理される実機
    異常に処理される実機
    共に
    「画像のアップロード」には成功しました。
    しかし、
    コメントアウト部分を外すと、
    「画像オープンに失敗しました。」
    となります。
    当然 echo $file_tmp; しても画像リソースIDはかえってきません。
    やはり、
    $file_tmp = @imagecreatefromjpeg($tmp_name);
    の部分がうまくいっていないようです。
    (12月25日11:30追記の情報が間違っておりました。)

    また、imagecreatefromjpegが動作する画像・動作しない画像についての
    追記を質問本体で行なっているので、もしよければご確認頂ければ幸いです。



    余談ですが、
    imagecreatefromjpeg後は
    写真の向きを訂正し、適切なサイズに縮小、他の画像との合成などの処理を行いますが、
    その処理自体は書き終わっており、
    現在ご質問している環境以外の不都合は発生していない状態です。

    キャンセル

  • 2017/12/25 23: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);

    キャンセル

  • 2017/12/26 14: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

    となり、一旦解決の運びとなりました。
    この度は本当に有難うございました!!

    キャンセル

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

  • ただいまの回答率 90.86%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    18170questions

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

  • Android

    5978questions

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

  • Ajax

    980questions

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

  • トップ
  • PHPに関する質問
  • SC-01K(android7.1.1)の標準カメラアプリで取得した画像をPHPのimagecreatefromjpegで処理した際のバグ