簡體   English   中英

C-解析任意圖像文件

[英]C - Parsing arbitrary image file

對於一個學習示例,我給了一個圖像文件以這種格式進行解析:

  • 八個字節將高度和寬度表示為32位整數。
  • 文件的其余部分是填充有像素信息的圖像數據,由32位信息表示:
    • 紅色,綠色,藍色各8位
    • 8位透明度信息

我已經創建了一個結構,並且可以成功地用二進制文件中的數據填充它。

但是,我現在的任務是縮小/裁剪圖像。 我計划取兩個x,y坐標。 一個坐標表示圖像數據中的開始像素,然后另一個坐標確定結束像素,以便它將從原始圖像中切割出一個矩形並將其保存到文件中(結果圖像將是2組中的矩形)。坐標)。

什么是進行此種植操作的有效方法? 我正在考慮將每個“像素”放入一個像素結構中,並具有一個二維像素數組。 但是,這似乎使它變得比必要的更為復雜。

我已經在網上搜索過,但是發現的大多數與圖像處理有關的示例都使用了api。

最好的事情是擁有一個新的結構,將其視為一個對象。 從文件加載圖像或創建新圖像(用零填充)。 之后,您可以使用使用幫助器功能來獲取像素或向/從圖像對象放置像素。

在內部,您可以將對象表示為字節數組(無符號char *)或結構數組,但是需要仔細定義它們。 現在,我將使用字節數組方法。 為了使結構正常工作,您可能需要小心,例如,確保結構的大小與下面的大小相同。 使用字節數組,您只需將(y * width + x)* pixel_size用作像素的指針,將+0表示紅色,將+1表示綠色,等等。由於這聽起來像是一個播放項目或工作分配,因此不必它運行起來很快,只需使其運行即可,讓編譯器擔心速度。

----進行改造----

for (x=0;x<x_new_max;x++)
for (y=0;y<y_new_max;y++) {
   unsigned old_x = transform_x(x); // essentially old_x = x * scale;
   unsigned old_y = transform_y(y); // essentially old_y = y * scale;
   put_pixel(new_image,x,y,get_pixel(old_image,old_x,old_y));
}

或類似的東西,轉換函數是關鍵,x = x * scale,比例將取決於操作函數,即使您在整數數學方面也不錯,則可以以float或fixed進行轉換。 x比例尺和y比例尺可能不同。

將圖片縮小一半new_max_x = old_max_x / 2; new_max_y = old_max_y / 2; x_scale = 0.5; y_scale = 0.5;

玩得開心

這取決於您如何設置圖像類。 如果您將像素存儲在矩陣中,則可以執行以下操作:

for (int i = 0; i <= height*shrink_factor; ++i){
     for (int j = y1; j <= width*shrink_factor; ++j){
        new.pixels[i][j] = old.pixels[i/shrink_factor][j/shrink_factor];
     }
}

對於裁剪:

for (int i = x1; i <= x2; ++i){
    for(int j = y1; j <= y2; ++j){
        new.pixels[i-x1][j-y1] = old.pixels[i][j];
    }
}

為新的圖像數據分配一個內存塊。 然后將指針src設置為指向原始圖像數據的左上像素,另一個dst指向新圖像數據的開始。 然后,只需為新圖像的每一行將一條(新)行的像素數據從src復制到dst在每行之后將src原始寬度,將dst新寬度。

編輯:我做了一個快速的實現-這是裁剪操作的關鍵部分。

我用於圖像數據的結構:

struct image {
  uint32_t    w;      /* width in pixels */
  uint32_t    h;      /* height in pixels */
  uint32_t    *data;  /* pixel data */
};

...這是裁剪代碼,其中oimgnimg是分別指向原始圖像和裁剪圖像的struct image的指針。 已分配裁剪圖像的data (大小為nimg->w * nimg->h * sizeof(uint32_t) ),但未初始化。 xyoimg裁剪區域的左上角坐標。 nimg->wnimg->h已設置為裁剪圖像的寬度和高度(以像素為單位)。

/* src is offset by y lines, plus x pixels into source image data */
uint32_t *src = oimg->data + y * oimg->w + x;
/* dst is at start of new image data */
uint32_t *dst = nimg->data;

for (i = 0; i < nimg->h; i++) {
  /* memcpy() one full new image line (nimg->w * sizeof(uint32_t)) */
  memcpy(dst, src, sizeof(uint32_t) * nimg->w);
  dst += nimg->w;  /* increment dst by a full new image line */
  src += oimg->w;  /* increment src by a full source image line */
}

上面的代碼假定在一個圖像行的末尾與下一個圖像行的末尾之間沒有多余的數據,並且每個圖像都有自己的像素數據。 一些庫將保留“跨步”值以及圖像寬度,該值保留行之間的偏移量。 這允許在圖像線之間添加額外的填充或未使用的像素,這對於保持對齊或允許包含較大圖像的一部分的圖像可以共享像素數據,而不是每個圖像都有單獨的副本是有用的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM