コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

ndsでのjpeg表示に再挑戦(8)

jpegのデコードはできるようになったのですが、元々、コマンドライン上で使うプログラムとして作られているので、エラーが起きたときに、exit()してコマンドプロンプトに戻る仕様に作られており、呼び出したところにエラーと共に戻ってこない問題があります。

jerror.cを修正してエラー時に戻るようにする

jpegの展開プログラムはとてもよくできているので、エラーが発生してexit()するときには、必ずファイナライズ処理をして、error_exit()関数に飛んでくるように作られています。そこで、このerror_exit()の部分にエラー発生時に元に戻るプログラムを追記しました。

また、中にはエラーが発生しても、できるだけデコードを行って、error_exit()に戻ってこないで、デコード処理を途中で止めて、jpeg_start_decompress()を抜けてくるものもあります。この場合にも対応できるように、グローバル変数としてDecodeErrorを用意しました。
以下コードの説明です。

グローバル変数を2つ宣言

jmp_buf EnvData;	//setjump用
bool	DecodeError;	//展開エラーフラグ

昨日のブログに書いたjpeg2pmm()関数をjpeg2pmmMain()に変更。そして、DecodeError = true;を追加。

// ********************************************
// jpegファイルをpmmファイルに変換します
// ********************************************
int	jpeg2pmmMain( FILE *inFp, FILE *outFp )
{
struct jpeg_decompress_struct	cinfo;
struct jpeg_error_mgr	jerr;
djpeg_dest_ptr dest_mgr = NULL;
JDIMENSION num_scanlines;

  DecodeError = true;

 以下略

  return( DecodeError );
}

そして、エラー時に戻ってくるプログラムです。正確にはエラー時には戻り値1と共にsetjmp()のところに戻ってきます。

// ********************************************
// jpegファイルをpmmファイルに変換します
// ********************************************
bool	jpeg2pmm( FILE *inFp, FILE *outFp )
{
bool	ret = true;

  //try{}
  if( setjmp( EnvData )==0 ){
    ret = jpeg2pmmMain( inFp, outFp );
  }
  //catch{}
  else{
    ret = false;
  }
  //finally{}
  {
    if( ret==false ){
      ShinoUpPrint( SubScreenA, (u8 *)"エラーが起きました", RGB(31,31,31),RGB(0,0,0), 1,RGB(0,0,0) );
    }
  }
  return ret;
}

jerror.cの変更箇所です。

#ifdef USE_NDS_ERROR_ROUTINES
#include <nds.h>
#include <setjmp.h>
#include "../tarosa_Shinofont03.h"
#include "../tarosa_Graphic20100228.h"		//自作のグラフィック
extern uint16	*SubScreenA;
extern jmp_buf 	EnvData;		//setjump用
extern bool		DecodeError;	//展開エラーフラグ
#endif

error_exit()の処理変更部

METHODDEF(void)
error_exit (j_common_ptr cinfo)
{
  /* Always display the message */
  (*cinfo->err->output_message) (cinfo);

  /* Let the memory manager delete any temp files before we die */
  jpeg_destroy(cinfo);
  
#ifdef USE_NDS_ERROR_ROUTINES
  longjmp( EnvData, 1 );	//setjmp()に飛ぶ
#else
  exit(EXIT_FAILURE);
#endif
}

そして、DecodeError = false;の追記ですが、エラー発生時には、必ずエラーメッセージを表示するoutput_message()関数を通るので、ここに追記しました。

ETHODDEF(void)
output_message (j_common_ptr cinfo)
{
  char buffer[JMSG_LENGTH_MAX];

  /* Create the message */
  (*cinfo->err->format_message) (cinfo, buffer);

#ifdef USE_WINDOWS_MESSAGEBOX
  /* Display it in a message dialog box */
  MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
	     MB_OK | MB_ICONERROR);
#else
#ifdef USE_NDS_ERROR_ROUTINES
  //エラーメッセージ表示
  ShinoUpPrint( SubScreenA, (u8 *)buffer, RGB(31,0,0),RGB(0,0,0), 1,RGB(0,0,0) );
  DecodeError = false;
#else
  /* Send it to stderr, adding a newline */
  fprintf(stderr, "%s\n", buffer);
#endif
#endif
}

以上で、無事、エラーの時でもエラーを表示して、jpeg2pmm()の呼び出し元に返ってくるようになりました。また、jconfig.hには、#define USE_NDS_ERROR_ROUTINESを追加しています。

今日はこの辺で。

本当にやりたいことリスト

(ブログの終わりにやりたいことを書いておきたいと思います)

  • 求職活動・・・このブログで興味を持った人一声かけてください。m(_ _)m
  • Androidプログラム
  • Web系のプログラム