本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

libtiffによるグラフィックス・プログラミング: 第2回

今回は、カラーについて少々

Michael Still (mikal@stillhq.com), Senior software engineer, Tower Software
Michael Still
Michaelは、数年間オーストラリアの政府機関向けに大規模な画像データベースの管理や開発を行うなど、画像処理の分野に従事してきました。現在は世界最先端のEDMSやTRIMというレコード管理パッケージの製造を行うTower Software社に勤務しています。またオープン・ソースのPDF生成APIであるPandaや、他のオープンソース・コードの開発者でもあります。

概要: TIFFは、非常に普及してはいるものの、かなり複雑なラスター画像フォーマットです。Libtiffは、TIFF仕様を標準的な形で実現したもので、無料で提供され、数多くのオペレーティング・システムで利用できます。本稿では、libtiffでグレースケール画像やカラー画像を扱う方法を紹介します。

日付:  2002年 6月 01日
レベル:  初級 この記事の原文:  英語
アクティビティー: 7822 ビュー
お気軽にご意見・ご感想をお寄せください: 


前回の記事では、libtiffによるモノクロのグラフィックス・プログラミングについて解説しましたが、今回は、その続きとして、グレースケール画像、カラー画像を取り上げます。前回のモノクロの記事のコードを読み、理解しているものとして話を進めます。

まず、カラーやグレースケールの画像データの保存方法の理論について、少しおさらいしておきたいと思います。これは、すべての画像フォーマットにあてはまる理論です。おさらいを済ませたところで、libtiffの具体的な使い方について紹介したいと思います。

いくつかの用語について

画像は多数のピクセルで構成されます。モノクロ画像の場合、ピクセルは0か1の2つの値のいずれかをとります。これは1ビットで表現できます。これに対して、グレースケール画像やカラー画像の場合、ピクセルは、もっと広い範囲の値を保存する必要があります。1ピクセルが255個のグレーのレベルをとるとすると、そのピクセルは8ビットで保存しなければならないことになります。これらの値の1つ1つのことをサンプルと呼びます。TIFFでは、この値のサイズをTIFFTAG_BITSPERSAMPLE というタグで表現します。これは、モノクロの場合は1であり、グレースケールの場合は、もっと大きな数になります。

カラー画像の場合は、さらに多くの情報を保存する必要があります。各ピクセルごとに、赤、緑、青の値を保存する必要があります。これらの値は、それぞれ別々のサンプルに保存されます。したがって、TIFFTAG_SAMPLESPERPIXEL を定義しなければならないことになります。これは、モノクロ画像、グレースケール画像の場合は1ですが、カラー画像の場合は通常3となります。また、各サンプルのサイズも定義する必要がありますので、さらにTIFFTAG_BITSPERSAMPLE の値を設定する必要もあります。


カラー、グレースケールの保存の理論

カラー画像、グレースケール画像をサポートする際に、まず理解しておくべきことは、メモリー中での画像データのフォーマットです。カラー画像、グレースケール画像の表現方法には、主に2つのやり方があります。以下では、これらの表現方法を、まずグレースケールについて説明し、次にそれをカラーに拡張する形で説明します。

ピクセル・データの直接保存

前回の記事でモノクロ画像でのピクセル情報の保存方法を説明しましたが、それは複数のstripの形で保存されるのでした。グレースケール画像やカラー画像でも同じ方法を用いることができますが、この画像データの表現方法は、非常に非効率的です。たとえば、画像の背景がベタ (solid) である場合、数多くのピクセルが同じ値をとります。ピクセル・データがstripの形で保存される場合、同じ値をとる大量のスペースが無駄になります。

ありがたいことに、もっと効率的な画像データの保存方法があります。1ピクセルあたり24ビットで、4つの色だけを使用する単純な画像があったとします。4つの色の値からなるルックアップ・テーブルを作成すると (各色は、24ビット値で表現される)、画像strip自体には、色に対応するエントリー番号を保存するだけでよいことになります。この場合、まるまる24ビット使う代わりに、たった2ビットで済みます。

以下のような計算になります。1,000ピクセル×1,000ピクセルの24ビット・カラー画像を保存するには、2千4百万ビットが必要です。この画像が、色を4つ使用する画像だったとすると、stripデータの4百万ビットとカラー・テーブルの98ビットで済むことになります。これは、ファイル・フォーマットのヘッダー情報やフッター情報を含まない数字であり、また未圧縮のビットマップに対する数字です。ルックアップ・テーブルが有効であることは明白です。このようなスタイルのルックアップ・テーブルのことをパレットと呼びます。たぶん画家が持ち歩くものに由来してのことでしょう。

この考え方は、グレースケール画像にも成り立ちます。違うのは、パレットの中の「色」がグレーの濃淡となる点だけです。

libtiffの圧縮アルゴリズム

libtiffには、いろいろな圧縮アルゴリズムが用意されています。下の表は、それらのアルゴリズムを整理したものです。


表1. Libtiffの圧縮アルゴリズム
圧縮アルゴリズム適している分野TIFFTAG
CCITT G4 Fax、G3 Faxこの項目は、整合性をもたせるために入れてあります。モノクロ画像を扱うコーディングを行う方は、たぶんCCITTファックスの圧縮手法を使用することになるでしょう。これらの圧縮アルゴリズムでは、カラーはサポートされません。 COMPRESSION_CCITTFAX3, COMPRESSION_CCITTFAX4
JPEGJPEG圧縮は、写真などの大きな画像に有効です。ただし、この圧縮の場合、通常、損失を伴います (圧縮過程の中で、画像データが棄てられるという意味で)。したがって、JPEGは、元どおりに読めなければならないテキストを圧縮するのには適していません。また、もう1つ注意しておくべきことは、損失が蓄積的であるという点です。これについては、次の節で詳しく説明します。 COMPRESSION_JPEG
LZWこれは、GIF画像で使用されている圧縮アルゴリズムです。Unisysのライセンスが必要なため、この圧縮コーデックに対するサポートは、libtiffからは外してあります。やはりこの圧縮アルゴリズムをサポートしておきたいという方のために、パッチも用意されていますが、みなさんのコードと連携されるプログラムの大半は、LZWをサポートしなくなっています。 COMPRESSION_LZW
Deflateこれはgzipの圧縮アルゴリズムで、PNGにも使用されているものです。カラー画像には、この圧縮アルゴリズムをお薦めしたいと思います。 COMPRESSION_DEFLATE

損失が蓄積される ?

JPEGなどの損失型圧縮アルゴリズムでは、なぜ損失が蓄積されるのでしょうか。JPEGを使って画像を圧縮することを考えてみることにします。そして、画像に、たとえばバーコードを付加する必要があったとします。そこで画像の解凍を行い、バーコードを付加し、再度圧縮するものとします。再圧縮を行うと、新しい1群の損失が招来されます。これを何回も繰り返していくと、ついには大きなしみのような画像になってしまうことが想像できます。

これが問題となるかどうかは、データの種類によりけりです。これが、どの程度の問題なのかを調べるために、画像の解凍と再圧縮を繰り返すlibtiffのサンプル・プログラムを作成してみました。そこで発見したことは、図画 (pictures) のデータは、繰り返して圧縮を行った場合でも、ずっと復元性が高いということでした。


図1. 圧縮前の図画
図1

図2. 圧縮前のサンプル・テキスト
図2

私が使用したコードでは、JPEG圧縮アルゴリズムの損失を調整するための1つの方法である「品質」の等級を25%としました。品質を低くすればするほど、圧縮率は高くなります。デフォルトは75%です。


図3. 圧縮を200回繰り返した後の図画
図3

図4. 圧縮を200回繰り返した後のテキスト
図4

カラー画像の書き込み

次に、カラー画像をディスクに書き込むことを行います。今回は単純な例であり、いろいろな点で洗練したものにする余地があることは頭に入れておいてください。


リスト1. カラー画像の書き込み
                
#include <tiffio.h>
#include <stdio.h>
int main(int argc, char *argv[]){
  TIFF *output;
  uint32 width, height;
  char *raster;
  // Open the output image
  if((output = TIFFOpen("output.tif", "w")) == NULL){
    fprintf(stderr, "Could not open outgoing image\n");
    exit(42);
  }
  // We need to know the width and the height before we can malloc
  width = 42;
  height = 42;
  if((raster = (char *) malloc(sizeof(char) * width * height * 3)) == NULL){
    fprintf(stderr, "Could not allocate enough memory\n");
    exit(42);
  }
  // Magical stuff for creating the image
  // ...
  // Write the tiff tags to the file
  TIFFSetField(output, TIFFTAG_IMAGEWIDTH, width);
  TIFFSetField(output, TIFFTAG_IMAGELENGTH, height);
  TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
  TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
  TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, 8);
  TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, 3);
  // Actually write the image
  if(TIFFWriteEncodedStrip(output, 0, raster, width * height * 3) == 0){
    fprintf(stderr, "Could not write image\n");
    exit(42);
  }
  TIFFClose(output);
}

このコードには、理論のところで説明したことがいくつか示されています。画像は1ピクセルあたり3サンプルであり、それぞれのサンプルに8ビットを使用します。したがって、この画像は24ビットのRGB画像です。これがモノクロ画像またはグレースケール画像なら、この値 (1ピクセルあたりのサンプル数) は1となるところです。タグPHOTOMETRIC_RGB は、画像データがstrip自体に保存されることを示します (パレット化されるのではなく)。これについては、後で説明します。

1ピクセルあたりのサンプル数に他の値はない ?

私の例では、1ピクセルあたりのサンプル数は3です。これがモノクロ画像かグレースケール画像なら、1ピクセルあたりのサンプル数は1となるところです。

他の値をとることも可能です。たとえば、場合によっては、特定のピクセルに透過値すなわちアルファ・チャネルを保存することもあります。その場合、1ピクセルあたりのサンプル数は4となります。

1ピクセルあたりのサンプル数は任意に決めることができます。ピクセルに特別な情報を含める必要がある場合には好都合です。ただし、そうした場合、単純な仮定を行っている画像ビューアーは、正しく動作しない可能性があります。私は、以前勤めていた会社で、その会社のPDF生成プログラムがクラッシュしないように、アルファ・チャネルなどを除去するコードを書かされたことがありました。

もう1つここで触れておきたいことに、画像の平面構成 (planar configuration) の問題があります。上のコードではPLANARCONFIG_CONTIG を指定していますが、これは、各ピクセルの赤、緑、青の情報を、画像データのstripに、いっしょにまとめて保存することを意味します。他の選択肢としてはPLANARCONFIG_SEPARATE がありますが、その場合は、画像の赤のサンプルがまとめて保存され、次に青のサンプルが、最後に緑のサンプルがまとめて保存されます。

パレット化カラー画像の書き込み

さて、それではこの画像のパレット化バージョンは、どうやって記述するのでしょうか。libtiffを使えば、これもまったくわけがありません。TIFFTAG_PHOTOMETRIC の値をPHOTOMETRIC_PALETTE に変えれば良いだけの話です。変わるのは1語だけですので、コード・サンプルを掲載するまでもありません。


カラー画像の読み出し

次に行うべきことは、他人の作成したカラー画像やグレースケール画像を安定的に読めるようにすることですが、これも大した問題ではありません。最初、呼び出し側がごちゃごちゃするのをある程度緩和しようと思い、よっぽどTIFFReadRGBAStrip() 呼び出しとTIFFReadRGBBSTile() 呼び出しの体裁を変更しようかとも思いましたが、これらの関数には、TIFFReadRGBAStrip() のmanページに書かれているように、少し制約があります。


TIFFReadRGBAStrip() のmanページからの抜粋
                
   TIFFReadRGBAStrip reads a single strip of a strip-based image into memory,
   storing  the  result  in  the  user supplied RGBA raster. The raster is
   assumed to be an array of width times   rowsperstrip   32-bit   entries,
   where   width   is  the  width  of  the  image (TIFFTAG_IMAGEWIDTH) and
   rowsperstrip is the maximum lines in a strip (TIFFTAG_ROWSPERSTRIP).
   The  strip  value  should  be  the  strip  number  (strip  zero  is the
   first) as returned by the TIFFComputeStrip function, but always for sample 0.
   Note  that  the  raster  is  assume  to  be  organized  such  that the pixel
   at location (x,y) is raster[y*width+x];  with  the  raster  origin in the
   lower-left hand corner of the strip. That is bottom  to  top  organization.
   When reading a partial last strip in the file the last line of the image
   will begin at the beginning of the buffer.
   Raster  pixels  are  8-bit packed red, green, blue, alpha samples. The
   macros TIFFGetR, TIFFGetG, TIFFGetB,  and  TIFFGetA  should  be used to
   access individual samples. Images without Associated Alpha matting
   information have a constant Alpha of 1.0 (255).
   See  the TIFFRGBAImage(3T) page for more details on how various image types
   are converted to RGBA values.
NOTES
   Samples must be either 1, 2, 4, 8, or 16 bits. Colorimetric samples/pixel
   must be either 1, 3, or 4 (i.e. SamplesPerPixel minus ExtraSamples).
   Palette  image  colormaps that appear to be incorrectly written as 8-bit
   values are automatically scaled to 16-bits.
   TIFFReadRGBAStrip  is  just  a wrapper around the more general
   TIFFRGBAImage(3T) facilities. It's main  advantage  over  the similar
   TIFFReadRGBAImage() function is that for large images a single buffer
   capable  of  holding  the  whole  image doesn't need to be allocated, only
   enough for one strip. The TIFFReadRGBATile() function does a similar
   operation for tiled images.

この関数には、妙な点がいくつかあります。まず、この関数は、これまで記述してきた他のコードの場合とは別のところを (0, 0) として定義しています。先のコードでは、(0, 0) の点は画像の左上隅でした。それに対して、この呼び出しは、左下隅を (0, 0) として定義しています。また、1サンプルあたりのビット数について、有効なすべての値をサポートしていないという制約もあります。こうした癖が気に入らないという方は、私が前回の記事でモノクロ画像を扱ったときと同じようにTIFFReadEncodedStrip() を使う手もあることを思い出してください。


リスト2. TIFFReadEncodedStrip() によるカラー画像の読み出し
                
#include <stdio.h>
#include <tiffio.h>
int main(int argc, char *argv[]){
  TIFF *image;
  uint32 width, height, *raster;
  tsize_t stripSize;
  unsigned long imagesize, c, d, e;
  // Open the TIFF image
  if((image = TIFFOpen(argv[1], "r")) == NULL){
    fprintf(stderr, "Could not open incoming image\n");
    exit(42);
  }
  // Find the width and height of the image
  TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width);
  TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
  imagesize = height * width + 1;
  if((raster = (uint32 *) malloc(sizeof(uint32) * imagesize)) == NULL){
    fprintf(stderr, "Could not allocate enough memory\n");
    exit(42);
  }
  // Read the image into the memory buffer
  if(TIFFReadRGBAStrip(image, 0, raster) == 0){
    fprintf(stderr, "Could not read image\n");
    exit(42);
  }
// Here I fix the reversal of the image (vertically) and show you
// how to get the color values from each pixel
  d = 0;
  for(e = height - 1; e != -1; e--){
    for(c = 0; c < width; c++){
      // Red = TIFFGetR(raster[e * width + c]);
      // Green = TIFFGetG(raster[e * width + c]);
      // Blue = TIFFGetB(raster[e * width + c]);
    }
  }
  free(raster);
  TIFFClose(image);
}


高度な話

さて、どんな画像フォーマットでも基本的な読み書きができるようになったところで、最後に2つのことについて触れておきたいと思います。

コード・サンプルの拡張

libtiffの中でファイル入出力関数をフックする方法について詳しく知りたい方は、私のPDFライブラリーPandaに収めてあるimages.cというファイルを参照してください。PandaのWebページは、稿末の参考文献に示してあります。

ファイル以外の場所にTIFFデータを保存する方法

これまでのコード・サンプルは、すべて、ファイルとの間で読み書きを行うものでした。画像データをファイルに保存するのではないが、libtiffやtiffを使用したいという場合は数多くあります。たとえば、カスタマーのIDカード用の写真を、データベースに保存しておきたいというような場合です。

私が最もよく扱う例はPDF文書で、画像をPDF文書に埋め込む場合です。これらの画像には、必要ならTIFFのサブセットが使用でき、モノクロ画像なら、当然TIFFが適しています。

Libtiffでは、ライブラリー中のファイル入出力関数をみなさん独自のものに置き換えることができます。それにはTIFFClientOpen() というメソッドを使用します。以下は、そのコード・サンプルです (ただし、このコードは、基本的な考え方を説明するためのもので、コンパイルできません)。


リスト3. TIFFClientOpenの使い方
                
#include <tiffio.h>
#include <pthread.h>
// Function prototypes
static tsize_t libtiffDummyReadProc (thandle_t fd, tdata_t buf, tsize_t size);
static tsize_t libtiffDummyWriteProc (thandle_t fd, tdata_t buf, tsize_t size);
static toff_t libtiffDummySeekProc (thandle_t fd, toff_t off, int i);
static int libtiffDummyCloseProc (thandle_t fd);
// We need globals because of the callbacks (they don't allow us to pass state)
char *globalImageBuffer;
unsigned long globalImageBufferOffset;
// This mutex keeps the globals safe by ensuring only one user at a time
pthread_mutex_t convMutex = PTHREAD_MUTEX_INITIALIZER;
...
TIFF *conv;
// Lock the mutex
pthread_mutex_lock (&convMutex);
globalImageBuffer = NULL;
globalImageBufferOffset = 0;
// Open the dummy document (which actually only exists in memory)
conv = TIFFClientOpen ("dummy", "w", (thandle_t) - 1, libtiffDummyReadProc,
            libtiffDummyWriteProc, libtiffDummySeekProc,
            libtiffDummyCloseProc, NULL, NULL, NULL);
// Setup the image as if it was any other tiff image here, including setting tags
...
// Actually do the client open
TIFFWriteEncodedStrip (conv, 0, stripBuffer, imageOffset);
// Unlock the mutex
pthread_mutex_unlock (&convMutex);
...
/////////////////// Callbacks to libtiff
...
static tsize_t
libtiffDummyReadProc (thandle_t fd, tdata_t buf, tsize_t size)
{
  // Return the amount of data read, which we will always set as 0 because
  // we only need to be able to write to these in-memory tiffs
  return 0;
}
static tsize_t
libtiffDummyWriteProc (thandle_t fd, tdata_t buf, tsize_t size)
{
  // libtiff will try to write an 8 byte header into the tiff file. We need
  // to ignore this because PDF does not use it...
  if ((size == 8) && (((char *) buf)[0] == 'I') && (((char *) buf)[1] == 'I')
     && (((char *) buf)[2] == 42))
    {
    // Skip the header -- little endian
    }
  else if ((size == 8) && (((char *) buf)[0] == 'M') &&
       (((char *) buf)[1] == 'M') && (((char *) buf)[2] == 42))
    {
    // Skip the header -- big endian
    }
  else
    {
    // Have we done anything yet?
    if (globalImageBuffer == NULL)
    if((globalImageBuffer = (char *) malloc (size * sizeof (char))) == NULL)
        {
          fprintf(stderr, "Memory allocation error\n");
          exit(42);
        }
    // Otherwise, we need to grow the memory buffer
    else
    {
      if ((globalImageBuffer = (char *) realloc (globalImageBuffer,
                             (size * sizeof (char)) +
                             globalImageBufferOffset)) == NULL)
        fprintf(stderr, "Could not grow the tiff conversion memory buffer\n");
            exit(42);
    }
    // Now move the image data into the buffer
    memcpy (globalImageBuffer + globalImageBufferOffset, buf, size);
    globalImageBufferOffset += size;
    }
  return (size);
}
static toff_t
libtiffDummySeekProc (thandle_t fd, toff_t off, int i)
{
  // This appears to return the location that it went to
  return off;
}
static int
libtiffDummyCloseProc (thandle_t fd)
{
  // Return a zero meaning all is well
  return 0;
}

カラーからグレースケールへの変換

カラー画像をグレースケールに変換するには、どうすればよいのでしょうか。私は、最初、赤、緑、青を平均すればよいと答えていました。が、この答は間違いです。実際には、人の目からすると、よく見える色とそうでない色とがあります。したがって、正確なグレースケールの表示にするには、カラー・サンプルごとに異なる係数を掛ける必要があります。正しい係数は、赤が0.299、緑が0.587、青が0.114です。


まとめ

本稿では、グレースケール画像やカラー画像を扱うときのlibtiffのプログラム方法を紹介しました。とっかかりとなりそうなサンプル・コードもいくつか紹介しました。これで、みなさんもlibtiffを使ってどんどんコーディングを行えるだけの知識が得られたのではないでしょうか。


参考文献

  • libtiffによるモノクロのグラフィックス・プログラミングを取り上げたRead Michaelの前回の記事 (developerWorks、2002年3月)。

  • 本稿で取り上げた処理を行うソース・ファイルは、以下からダウンロードできます。
    • カラー画像の読み出し:read.c
    • カラー画像の書き込み:write.c
    • ファイル入出力関数のカスタマイズ:client.c
    • 圧縮の繰り返し:recompress.c


  • libtiffのWebサイトからlibtiffのソースがダウンロードできます。それぞれのオペレーティング・システムに対応したバイナリー・パッケージも見つかるはずです。

  • libtiffの中でファイル入出力関数をフックする方法について詳しく知りたい方は、MichaelのPandaページにあるimages.cというファイルを参照してください。

  • グレースケールへの変換方法については、Poynton's Color FAQを参照してください。

  • developerWorks のLinuxゾーンには、他にもLinux関係の記事が多数掲載されています。

著者について

Michael Still

Michaelは、数年間オーストラリアの政府機関向けに大規模な画像データベースの管理や開発を行うなど、画像処理の分野に従事してきました。現在は世界最先端のEDMSやTRIMというレコード管理パッケージの製造を行うTower Software社に勤務しています。またオープン・ソースのPDF生成APIであるPandaや、他のオープンソース・コードの開発者でもあります。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux
ArticleID=228949
ArticleTitle=libtiffによるグラフィックス・プログラミング: 第2回
publish-date=06012002
author1-email=mikal@stillhq.com
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。