LINUX.ORG.RU

FreeImage: появляются синие пиксели в буфере _GetBits()


0

1

Простая программа, отображает пиксели в виде RGB-кубика.

/* Отображение цветового пространства в виде RGB-куба */

#include <stdio.h>  /* printf() */
#include <FreeImage.h>
#include <stdlib.h>

int main (int argc, char **argv) {
  char *filename_i;
  char *filename_o;
  if (argc < 3) {
    printf("%s [filename_i] [filename_o]\n", argv[0]);
    return -1;
  }
  filename_i = argv[1];
  filename_o = argv[2];

  FreeImage_Initialise (1);

  FIBITMAP *dib0, *dib1;
  dib0 = FreeImage_Load(FreeImage_GetFIFFromFilename(filename_i), filename_i, 0);

  BYTE *data0 = FreeImage_GetBits(dib0);
  WORD w0 = FreeImage_GetWidth(dib0);
  WORD h0 = FreeImage_GetHeight(dib0);
  WORD bpp0 = FreeImage_GetBPP(dib0);
  bpp0 /= 8;
  WORD stride0 = FreeImage_GetLine(dib0);
  printf("w: %d\n", w0);
  printf("h: %d\n", h0);
  printf("bpp: %d\n", bpp0);
  printf("stride: %d\n", stride0);

const int W = 256;
const int H = 256;
  WORD w1 = 3*W;
  WORD h1 = H;
  WORD bpp1 = 3;
  dib1 = FreeImage_Allocate(w1,h1,bpp1*8); // bytes per pixel

  printf("%d %d %d\n",
   FreeImage_GetWidth(dib1),
   FreeImage_GetHeight(dib1),
   FreeImage_GetBPP(dib1));

  WORD stride1 = FreeImage_GetLine(dib1);

  BYTE *data1 = FreeImage_GetBits(dib1);
#define min(a,b) ((a <= b)?(a):(b))
#define max(a,b) ((a > b)?(a):(b))
#define normX(d,x) max(0,min((w##d)-1,(x)))
#define normY(d,y) max(0,min((h##d)-1,(y)))

#define fB(d,x,y) data##d[(y)*stride##d+(x)*bpp##d+0]
#define fG(d,x,y) data##d[(y)*stride##d+(x)*bpp##d+1]
#define fR(d,x,y) data##d[(y)*stride##d+(x)*bpp##d+2]

// safe pixel access
#define sB(d,x,y) data##d[normY(d,(y))*stride##d+normX(d,(x))*bpp##d+0]
#define sG(d,x,y) data##d[normY(d,(y))*stride##d+normX(d,(x))*bpp##d+1]
#define sR(d,x,y) data##d[normY(d,(y))*stride##d+normX(d,(x))*bpp##d+2]

  // Фильтр по голограммам.
  for (int y = 0; y < h0; y++) {
    for (int x = 0; x < w0; x++) {
      int r00 = fR(0,x,y);
      int g00 = fG(0,x,y);
      int b00 = fB(0,x,y);
      if ((b00 > 120) && (r00+g00 < 10)) {
        printf("%d %d : %02X %02X %02X\n", x, y, r00, g00, b00);
      }
      int X1,Y1;
      int X2,Y2;
      int X3,Y3;
      X1 = r00; Y1 = (g00+b00)/2;
      X2 = (r00+b00)/2; Y2 = g00;
      X3 = (r00+g00)/2; Y3 = b00;

      sR(1,X1+0*W,Y1) = r00;
      sG(1,X1+0*W,Y1) = g00;
      sB(1,X1+0*W,Y1) = b00;

      sR(1,X2+1*W,Y2) = r00;
      sG(1,X2+1*W,Y2) = g00;
      sB(1,X2+1*W,Y2) = b00;

      sR(1,X3+2*W,Y3) = r00;
      sG(1,X3+2*W,Y3) = g00;
      sB(1,X3+2*W,Y3) = b00;
    }
  }

  FreeImage_Save(FreeImage_GetFIFFromFilename(filename_o), dib1, filename_o);
  FreeImage_DeInitialise();
  printf ("Quit.\n");
  return 0;
}
Компилируется так:
#!/bin/bash
NAME="clrgb"
gcc -g -o _$NAME $NAME.cpp -lfreeimage
Запускается так:
./_clrgb smirenie-xxs011.jpg clrgb-test-output.png
Вот исходная картинка: http://php.kirovnet.ru/images/smirenie-xxs011.jpg
Вот результат: http://php.kirovnet.ru/images/clrgb-test-output.png

Видно, что на третьей проекции - появились синие пиксели.
Их на исходном изображении нет.
Но в буфере data0 (при работе программы) они появляются:
$ ./_clrgb smirenie-xxs011.jpg clrgb-test-output.png
w: 570
h: 429
bpp: 3
stride: 1710
768 256 24
1 3 : 00 00 CD
3 6 : 00 00 C5
5 9 : 00 00 C7
7 12 : 00 00 C0
9 15 : 00 00 D1
11 18 : 00 00 C9
13 21 : 00 00 C3
15 24 : 00 00 CB
17 27 : 00 00 C1
19 30 : 00 00 B5
21 33 : 00 00 BE
23 36 : 00 00 9C
...
Как видно, синие пиксели распространены по координатам, составляющим (X,Y) - арифметические прогрессии с шагом 2 и 3.
Потратил уже часа 4, чтобы понять проблему - почему они появляются. Есть идеи?
Пока думаю, что это - баг FreeImage.
Проверьте программу с картинкой у себя.

★★★★★

Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.