Автор Тема: Разбиваем Bitmap на по пиксельную матрицу  (Прочитано 10312 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Viktor1703 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1512
  • Репутация: 405
    • Награды
  • Версия AutoIt: 3.3.12.0
Написал код для разбиения картинки на пиксельную матрицу, применить данный пример практически негде, сегодня мне понадобилось сделать такую конструкцию и я решил выложить его здесь, буду рад советам по упрощению и оптимизации кода.

Код: AutoIt [Выделить]
#include <GDIP.au3>
#include <GDIPlus.au3>
#include <Array.au3>

$Matrix = MatrixGetColor(@ScriptDir & '\Image1.png')
_ArrayDisplay($Matrix)

Func MatrixGetColor($sImage)
   
   Local $hImage, $iWidth, $iHeight, $iBitmap, $hBitmap
   
   _GDIPlus_Startup()
   $hImage = _GDIPlus_ImageLoadFromFile($sImage)
   $iWidth = _GDIPlus_ImageGetWidth($hImage)
   $iHeight = _GDIPlus_ImageGetHeight($hImage)
   $iBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
   $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($iBitmap)
   
   Dim $iMatrix[$iHeight][$iWidth]
   
   For $H = 0 To $iHeight - 1
      For $W = 0 To $iWidth - 1
         $iMatrix[$H][$W] = '0x' & Hex(_GDIPlus_BitmapGetPixel($hBitmap, $W, $H), 6)
      Next
   Next
   
   _GDIPlus_ImageDispose($hImage)
   _WinAPI_DeleteObject($iBitmap)
   _WinAPI_DeleteObject($hBitmap)
   _GDIPlus_Shutdown()
   
   Return $iMatrix
EndFunc  
 


Для работы необходима библиотека GDIP UDF

Русское сообщество AutoIt

Разбиваем Bitmap на по пиксельную матрицу
« Отправлен: Февраль 15, 2012, 22:46:28 »

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #1, Отправлен: Февраль 15, 2012, 22:56:47 »
Если честно, то абсолютно бестолковый ход. Я конечно его не тестировал, но скорость должна быть "феноминальной".

Вообще, если у вас возникла необходимость переводить битмап в массив, то от этого сразу же нужно отказаться в пользу чего-нибудь другого. В крайнем случае использовать машинный код. Например, см. _WinAPI_IsAlphaBitmap() из WinAPIEx.au3.

Не подскажите, зачем вам понадобился массив?


Думай, прежде чем говорить.

Оффлайн Viktor1703 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1512

  • Автор темы
  • Репутация: 405
    • Награды
  • Версия AutoIt: 3.3.12.0
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #2, Отправлен: Февраль 15, 2012, 23:04:54 »
Да очень просто, я сам не сторонник такого хода, но меня попросили, есть возможность в Skype отправлять Html теги, вот и получается что можно таким образом отправить картинку:

<font color="#FEFEFE">#</font>
Получается что мы пишем # - почти белого цвета, но в Skype можно установить ещё и размер текста через тег и сделать пиксель белого цвета.

Если интересно. то вот пост на Хабрахабр на эту тему

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #3, Отправлен: Февраль 15, 2012, 23:15:25 »
Тогда, я думаю, лучше сразу резать данные битмапа рег. выражениями в html код.

Русское сообщество AutoIt

Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #3 Отправлен: Февраль 15, 2012, 23:15:25 »

Оффлайн Viktor1703 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1512

  • Автор темы
  • Репутация: 405
    • Награды
  • Версия AutoIt: 3.3.12.0
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #4, Отправлен: Февраль 15, 2012, 23:24:33 »
Чуть - чуть не понял, как это будет выглядеть? :think:

Оффлайн Yashied [?]

  • AutoIt MVP
  • Глобальный модератор
  • *
  • Сообщений: 5379
  • Репутация: 2694
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.x.x
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #5, Отправлен: Февраль 15, 2012, 23:26:31 »
Код: AutoIt [Выделить]
#Include <GDIPlus.au3>

_GDIPlus_Startup()
$hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & '\Image.png')
$Width = _GDIPlus_ImageGetWidth($hBitmap)
$Height = _GDIPlus_ImageGetHeight($hBitmap)
$tMap = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Width, $Height, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
$bData = DllStructGetData(DllStructCreate('byte[' & ($Width * $Height * 4) & ']', DllStructGetData($tMap, 'Scan0')), 1)
_GDIPlus_BitmapUnlockBits($hBitmap, $tMap)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()

ConsoleWrite($bData & @CR)


Остается как-то отформатировать эту строку с помощью рег. выражений в то, что нужно. Но я с ними не дружу.

:)

Оффлайн Viktor1703 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1512

  • Автор темы
  • Репутация: 405
    • Награды
  • Версия AutoIt: 3.3.12.0
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #6, Отправлен: Февраль 15, 2012, 23:34:50 »
И на этом большое спасибо :) с рег. выражениями попробую позже разобратся :)

Оффлайн Ilyialat [?]

  • Новичок
  • *
  • Сообщений: 54
  • Репутация: 2
    • Награды
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #7, Отправлен: Август 28, 2012, 20:32:12 »
ImageSearch работает медленней pixelsearch... Попробую разбить файл на массив и использовать PixelSearch =) Спасибо =)

Русское сообщество AutoIt

Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #7 Отправлен: Август 28, 2012, 20:32:12 »

Оффлайн WSWR [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 929
  • Репутация: 351
    • Награды
  • Версия AutoIt: 3.3.14.0
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #8, Отправлен: Август 29, 2012, 01:23:05 »
Yashied
Цитировать
Остается как-то отформатировать эту строку с помощью рег. выражений в то, что нужно. Но я с ними не дружу.
Превращает строку в массив цветов пикселей, еще бы нужно координаты добавить...
Код: AutoIt [Выделить]
#include <GDIPlus.au3>
#include <Array.au3>
#include <string.au3>
#include <Color.au3>

_GDIPlus_Startup()
$hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir&'\test.jpg')
$Width = _GDIPlus_ImageGetWidth($hBitmap)
$Height = _GDIPlus_ImageGetHeight($hBitmap)
$tMap = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Width, $Height, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
$bData = DllStructGetData(DllStructCreate('byte[' & ($Width * $Height * 4) & ']', DllStructGetData($tMap, 'Scan0')), 1)
_GDIPlus_BitmapUnlockBits($hBitmap, $tMap)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()

ConsoleWrite($Width & ' '&$Height&@CR)
;ConsoleWrite($bData&@CR)
$bData=StringTrimLeft($bData&@CR, 2)

$color=''
For $i = 1 To (StringLen($bData)) Step 8
$color=$color & '_' & StringMid($bData, $i, 8)
Next

$Array1=StringSplit($color,"_")
_ArrayDelete($Array1,0)
_ArrayDelete($Array1,0)
_ArrayDelete($Array1,Ubound($Array1)-1)
_ArrayTrim($Array1,2,1)

For $i = 0 To Ubound($Array1)-1
$Array1[$i]='0x'&Hex(_ColorGetBlue('0x'&$Array1[$i]),2) & Hex(_ColorGetGreen('0x'&$Array1[$i]),2) & Hex(_ColorGetRed('0x'&$Array1[$i]),2)
Next
_ArrayDisplay($Array1)
 

Несколько переделал, и скорость возросла в пару десятков раз, однако, все еще не исключаю, что и это не самый быстрый вариант.
« Последнее редактирование: Август 29, 2012, 21:40:49 от WSWR »

Оффлайн Yura [?]

  • Новичок
  • *
  • Сообщений: 36
  • Репутация: 7
    • Награды
  • Версия AutoIt: 3.3.14.0
Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #9, Отправлен: Ноябрь 25, 2015, 15:11:36 »
Несколько переделал, и скорость возросла в пару десятков раз, однако, все еще не исключаю, что и это не самый быстрый вариант.

Возможно быстрее будет так:

Код: AutoIt [Выделить]
Func img_get_colors2($img_name)
    _GDIPlus_Startup()
    $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\images\"&$img_name&".bmp") ; image location
    $Width = _GDIPlus_ImageGetWidth($hBitmap)
    $Height = _GDIPlus_ImageGetHeight($hBitmap)
    $tMap = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $Width, $Height, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    $bData = DllStructGetData(DllStructCreate('byte[' & ($Width * $Height * 4) & ']', DllStructGetData($tMap, 'Scan0')), 1)
    _GDIPlus_BitmapUnlockBits($hBitmap, $tMap)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()

    Local $aCol[$Height][$Width]
    For $i = 0 To $Height - 1
        For $j = 0 To $Width - 1
            $col_1 = StringMid($bData, 8*($j + $i*$Width) + 3, 2) ; color swap  
            $col_2 = StringMid($bData, 8*($j + $i*$Width) + 5, 2)
            $col_3 = StringMid($bData, 8*($j + $i*$Width) + 7, 2)
            $aCol[$i][$j] = "0x"&$col_3&$col_2&$col_1
            ;$aCol[$i][$j] = "0x"&StringMid($bData, 8*($j + $i*$Width) + 3, 6) ; without color swap
        Next
    Next

    ;_ArrayDisplay($aCol)
    Return($aCol)
EndFunc


Функция превращает строку в двухмерный массив цветов пикселей. Конвертация между RGB и BGR по выбору. Вывод в строку переделать тоже не проблема.

Русское сообщество AutoIt

Re: Разбиваем Bitmap на по пиксельную матрицу
« Ответ #9 Отправлен: Ноябрь 25, 2015, 15:11:36 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
0 Ответов
1754 Просмотров
Последний ответ Январь 25, 2012, 00:24:01
от Viktor1703
3 Ответов
2508 Просмотров
Последний ответ Май 28, 2013, 11:47:33
от SlavaS
0 Ответов
1134 Просмотров
Последний ответ Декабрь 12, 2012, 21:22:04
от HolyWay
0 Ответов
1706 Просмотров
Последний ответ Декабрь 21, 2012, 00:21:11
от Viktor1703
2 Ответов
1931 Просмотров
Последний ответ Апрель 09, 2013, 18:54:12
от Mancoffee
9 Ответов
4886 Просмотров
Последний ответ Октябрь 11, 2013, 14:14:46
от madmasles
7 Ответов
3220 Просмотров
Последний ответ Февраль 11, 2014, 07:36:57
от Viktor1703
1 Ответов
1218 Просмотров
Последний ответ Март 04, 2014, 01:36:29
от Viktor1703
1 Ответов
1203 Просмотров
Последний ответ Октябрь 24, 2014, 20:57:45
от ArvenPK
6 Ответов
1604 Просмотров
Последний ответ Декабрь 08, 2015, 13:12:33
от Yura